Autoencoder i TensorFlow med eksempel

Hvad er Autoencoder i Deep Learning?

An Autoencoder er et værktøj til at lære datakodning effektivt på en uovervåget måde. Det er en type kunstigt neuralt netværk, der hjælper dig med at lære repræsentationen af ​​datasæt til dimensionsreduktion ved at træne det neurale netværk til at ignorere signalstøjen. Det er et fantastisk værktøj til at genskabe et input.

Med enkle ord tager maskinen, lad os sige et billede, og kan producere et nært beslægtet billede. Inputtet i denne type neurale netværk er umærket, hvilket betyder, at netværket er i stand til at lære uden overvågning. Mere præcist kodes inputtet af netværket for kun at fokusere på den mest kritiske funktion. Dette er en af ​​grundene til, at autoencoder er populær til dimensionsreduktion. Desuden kan autoencodere bruges til at producere generative læringsmodeller. For eksempel kan det neurale netværk trænes med et sæt ansigter og kan derefter producere nye ansigter.

Hvordan virker TensorFlow Autoencoder?

Formålet med en autoencoder er at producere en tilnærmelse af inputtet ved kun at fokusere på de væsentlige funktioner. Du tænker måske, hvorfor ikke bare lære at kopiere og indsætte input for at producere output. Faktisk er en autoencoder et sæt begrænsninger, der tvinger netværket til at lære nye måder at repræsentere data på, anderledes end blot at kopiere outputtet.

En typisk autoencoder er defineret med et input, en intern repræsentation og et output (en tilnærmelse af input). Læringen sker i de lag, der er knyttet til den indre repræsentation. Faktisk er der to hovedblokke af lag, der ligner et traditionelt neuralt netværk. Den lille forskel er, at laget, der indeholder outputtet, skal være lig med inputtet. På billedet nedenfor går det originale input ind i den første blok kaldet encoder. Denne interne repræsentation komprimerer (reducerer) størrelsen af ​​input. I den anden blok sker rekonstruktionen af ​​inputtet. Dette er afkodningsfasen.

Arbejde med Autoencoder
Arbejde med Autoencoder

Arbejde med Autoencoder

Modellen vil opdatere vægtene ved at minimere tabsfunktionen. Modellen straffes, hvis rekonstruktionsoutputtet er forskelligt fra inputtet.

Forestil dig konkret et billede med en størrelse på 50×50 (dvs. 250 pixels) og et neuralt netværk med kun ét skjult lag bestående af hundrede neuroner. Indlæringen foregår på et feature map, som er to gange mindre end inputtet. Det betyder, at netværket skal finde en måde at rekonstruere 250 pixels med kun en vektor af neuroner svarende til 100.

Eksempel på stablet autoencoder

I denne autoencoder-vejledning lærer du, hvordan du bruger en stablet autoencoder. Det architecture ligner et traditionelt neuralt netværk. Inputtet går til et skjult lag for at blive komprimeret eller reducere dets størrelse og når derefter rekonstruktionslagene. Målet er at producere et outputbillede så tæt på som originalen. Modellen skal lære en måde at udføre sin opgave på under et sæt af begrænsninger, det vil sige med en lavere dimension.

I dag er autoencoders i Deep Learning bruges hovedsageligt til at forringe et billede. Forestil dig et billede med ridser; et menneske er stadig i stand til at genkende indholdet. Ideen med at denoising autoencoder er at tilføje støj til billedet for at tvinge netværket til at lære mønsteret bag dataene.

Den anden nyttige familie af Autoencoder Deep Learning er variationsautoencoder. Denne type netværk kan generere nye billeder. Forestil dig, at du træner et netværk med billedet af en mand; et sådant netværk kan producere nye ansigter.

Sådan bygger du en autoencoder med TensorFlow

I denne vejledning lærer du, hvordan du bygger en stablet autoencoder for at rekonstruere et billede.

Du vil bruge CIFAR-10 datasæt som indeholder 60000 32×32 farvebilleder. Autoencoder-datasættet er allerede delt mellem 50000 billeder til træning og 10000 til test. Der er op til ti klasser:

  • Fly
  • Automobile
  • Bird
  • Cat
  • Deer
  • Dog
  • Frog
  • hest
  • Forsendelse
  • lastbil

Du skal downloade billederne i denne URL https://www.cs.toronto.edu/~kriz/cifar.html og udpakke den. Mappen for-10-batches-py indeholder fem batches af data med 10000 billeder hver i en tilfældig rækkefølge.

Før du bygger og træner din model, skal du anvende noget databehandling. Du vil fortsætte som følger:

  1. Importer dataene
  2. Konverter dataene til sort/hvid-format
  3. Tilføj alle batches
  4. Konstruer træningsdatasættet
  5. Konstruer en billedvisualisering

Billedforbehandling

Trin 1) Importer dataene

Ifølge den officielle hjemmeside kan du uploade dataene med following kode. Autoencoder-koden vil indlæse dataene i en ordbog med data og label. Bemærk, at koden er en funktion.

import numpy as np
import tensorflow as tf
import pickle
def unpickle(file):
    import pickle
    with open(file, 'rb') as fo:
        dict = pickle.load(fo, encoding='latin1')
    return dict

Trin 2) Konverter dataene til sort/hvid-format

For nemheds skyld konverterer du dataene til en gråtoneskala. Det vil sige med kun én dimension mod tre for farver billede. Det meste af det neurale netværk fungerer kun med én dimensionsinput.

def grayscale(im):
    return im.reshape(im.shape[0], 3, 32, 32).mean(1).reshape(im.shape[0], -1)

Trin 3) Tilføj alle batches

Nu hvor begge funktioner er oprettet og datasættet indlæst, kan du skrive en loop for at tilføje dataene i hukommelsen. Hvis du tjekker omhyggeligt, hedder unzip-filen med dataene data_batch_ med et tal fra 1 til 5. Du kan loope over filerne og tilføje dem til data.

Når dette trin er udført, konverterer du farvedataene til et gråskalaformat. Som du kan se, er formen af ​​dataene 50000 og 1024. De 32*32 pixels er nu fladt til 2014.

# Load the data into memory
data, labels = [], []
## Loop over the b
for i in range(1, 6):
    filename = './cifar-10-batches-py/data_batch_' + str(i)
    open_data = unpickle(filename)
    if len(data) > 0:
        data = np.vstack((data, open_data['data']))
        labels = np.hstack((labels, open_data['labels']))
    else:
        data = open_data['data']
        labels = open_data['labels']

data = grayscale(data)
x = np.matrix(data)
y = np.array(labels)
print(x.shape)
(50000, 1024)

Bemærk: Skift './cifar-10-batches-py/data_batch_' til den faktiske placering af din fil. For eksempel for Windows maskine, stien kunne være filnavn = 'E:\cifar-10-batches-py\data_batch_' + str(i)

Trin 4) Konstruer træningsdatasættet

For at gøre træningen hurtigere og nemmere, træner du kun en model på hestebillederne. Hestene er den syvende klasse i mærkedataene. Som nævnt i dokumentationen til CIFAR-10-datasættet, indeholder hver klasse 5000 billeder. Du kan udskrive formen på dataene for at bekræfte, at der er 5.000 billeder med 1024 kolonner som vist i nedenstående TensorFlow Autoencoder eksempel trin.

horse_i = np.where(y == 7)[0]
horse_x = x[horse_i]
print(np.shape(horse_x)) 
(5000, 1024)

Trin 5) Konstruer en billedvisualisering

Til sidst konstruerer du en funktion til at plotte billederne. Du skal bruge denne funktion for at udskrive det rekonstruerede billede fra autoencoderen.

En nem måde at udskrive billeder på er at bruge objektet imshow fra matplotlib-biblioteket. Bemærk, at du skal konvertere formen på dataene fra 1024 til 32*32 (dvs. formatet af et billede).

# To plot pretty figures
%matplotlib inline
import matplotlib
import matplotlib.pyplot as plt
def plot_image(image, shape=[32, 32], cmap = "Greys_r"):
    plt.imshow(image.reshape(shape), cmap=cmap,interpolation="nearest")
    plt.axis("off")   

Funktionen tager 3 argumenter:

  • Billede: indgangen
  • Shape: liste, billedets dimension
  • cmap: vælg farvekortet. Som standard, grå

Du kan prøve at plotte det første billede i datasættet. Du burde se en mand på en hest.

plot_image(horse_x[1], shape=[32, 32], cmap = "Greys_r")

Konstruer en billedvisualisering

Indstil Datasæt Estimator

Okay, nu hvor datasættet er klar til brug, kan du begynde at bruge Tensorflow. Før vi bygger modellen, lad os bruge Dataset-estimatoren af ​​Tensorflow til at fodre netværket.

Du vil bygge et datasæt med TensorFlow-estimator. For at genopfriske dit sind skal du bruge:

  • from_tensor_slices
  • gentag
  • parti

Den fulde kode til at bygge datasættet er:

dataset = tf.data.Dataset.from_tensor_slices(x).repeat().batch(batch_size)

Bemærk, at x er en pladsholder med folloenwing form:

  • [None,n_inputs]: Indstil til None, fordi antallet af billedfeed til netværket er lig med batchstørrelsen.

ud aftails, se venligst selvstudiet vedr lineær regression.

Derefter skal du oprette iteratoren. Uden denne kodelinje vil ingen data gå gennem pipelinen.

iter = dataset.make_initializable_iterator() # create the iteratorfeatures = iter.get_next()

Nu hvor pipelinen er klar, kan du kontrollere, om det første billede er det samme som før (dvs. en mand på en hest).

Du indstiller batchstørrelsen til 1, fordi du kun ønsker at fodre datasættet med ét billede. Du kan se dimensionen af ​​dataene med print(sess.run(features).shape). Det er lig med (1, 1024). 1 betyder, at kun ét billede med 1024 er feed hver. Hvis batchstørrelsen er indstillet til to, vil to billeder gå gennem pipelinen. (Lad være med at ændre batchstørrelsen. Andetwise, vil det give en fejl. Kun ét billede ad gangen kan gå til funktionen plot_image().

## Parameters
n_inputs = 32 * 32
BATCH_SIZE = 1
batch_size = tf.placeholder(tf.int64)

# using a placeholder
x = tf.placeholder(tf.float32, shape=[None,n_inputs])
## Dataset
dataset = tf.data.Dataset.from_tensor_slices(x).repeat().batch(batch_size)
iter = dataset.make_initializable_iterator() # create the iterator
features = iter.get_next()

## Print the image
with tf.Session() as sess:
    # feed the placeholder with data
    sess.run(iter.initializer, feed_dict={x: horse_x,
                                         batch_size: BATCH_SIZE}) 
    print(sess.run(features).shape) 
    plot_image(sess.run(features), shape=[32, 32], cmap = "Greys_r")
(1, 1024)

Indstil Datasæt Estimator

Byg netværket

Det er tid til at opbygge netværket. Du træner en stablet autoencoder, det vil sige et netværk med flere skjulte lag.

Dit netværk vil have ét inputlag med 1024 punkter, dvs. 32×32, billedets form.

Indkoderblokken vil have et øverste skjult lag med 300 neuroner, et centralt lag med 150 neuroner. Dekoderblokken er symmetrisk med indkoderen. Du kan visualisere netværket på billedet nedenfor. Bemærk, at du kan ændre værdierne for skjulte og centrale lag.

Byg netværket
Opbygning af netværket til Autoencoder

At bygge en autoencoder ligner meget enhver anden deep learning-model.

Du vil konstruere modellen following Disse trin:

  1. Definer parametrene
  2. Definer lagene
  3. Definer architecture
  4. Definer optimeringen
  5. Kør modellen
  6. Vurder modellen

I det forrige afsnit lærte du, hvordan du opretter en pipeline til at fodre modellen, så der er ingen grund til at oprette datasættet igen. Du vil konstruere en autoencoder med fire lag. Du bruger Xavier-initialiseringen. Dette er en teknik til at indstille startvægtene lig med variansen af ​​både input og output. Til sidst bruger du elu-aktiveringsfunktionen. Du regulariserer tabsfunktionen med L2 regularizer.

Trin 1) Definer parametrene

Det første trin indebærer at definere antallet af neuroner i hvert lag, indlæringshastigheden og hyperparameteren for regularizeren.

Inden da importerer du funktionen delvist. Det er en bedre metode til at definere parametrene for de tætte lag. Koden nedenfor definerer værdierne for autoencoderen architecture. Som nævnt før har autoencoderen to lag med 300 neuroner i det første lag og 150 i det andet lag. Deres værdier er gemt i n_hidden_1 og n_hidden_2.

Du skal definere indlæringshastigheden og L2-hyperparameteren. Værdierne gemmes i learning_rate og l2_reg

from functools import partial

## Encoder
n_hidden_1 = 300
n_hidden_2 = 150  # codings

## Decoder
n_hidden_3 = n_hidden_1
n_outputs = n_inputs

learning_rate = 0.01
l2_reg = 0.0001

Xavier initialiseringsteknikken kaldes med objektet xavier_initializer fra estimatorbidraget. I samme estimator kan du tilføje regularizeren med l2_regularizer

## Define the Xavier initialization
xav_init =  tf.contrib.layers.xavier_initializer()
## Define the L2 regularizer
l2_regularizer = tf.contrib.layers.l2_regularizer(l2_reg)

Trin 2) Definer lagene

Alle parametrene for de tætte lag er blevet indstillet; du kan pakke alt i variablen dense_layer ved at bruge objektet partial. dense_layer, som bruger ELU-aktivering, Xavier-initialisering og L2-regularisering.

## Create the dense layer
dense_layer = partial(tf.layers.dense,
                         activation=tf.nn.elu,
                         kernel_initializer=xav_init,
                         kernel_regularizer=l2_regularizer)

Trin 3) Definer architecture

Hvis du ser på billedet af architecture, bemærker du, at netværket stabler tre lag med et outputlag. I koden nedenfor forbinder du de relevante lag. For eksempel beregner det første lag prikproduktet mellem input-matricens funktioner og de matricer, der indeholder de 300 vægte. Efter at prikproduktet er beregnet, går outputtet til Elu-aktiveringsfunktionen. Outputtet bliver input til det næste lag, det er derfor du bruger det til at beregne hidden_2 og så videre. Matrixmultiplikationen er den samme for hvert lag, fordi du bruger den samme aktiveringsfunktion. Bemærk, at det sidste lag, output, ikke anvender en aktiveringsfunktion. Det giver mening, fordi dette er det rekonstruerede input

## Make the mat mul
hidden_1 = dense_layer(features, n_hidden_1)
hidden_2 = dense_layer(hidden_1, n_hidden_2)
hidden_3 = dense_layer(hidden_2, n_hidden_3)
outputs = dense_layer(hidden_3, n_outputs, activation=None)

Trin 4) Definer optimeringen

Det sidste trin er at konstruere optimizeren. Du bruger Mean Square Error som en tabsfunktion. Hvis du husker tutorialen om lineær regression, ved du, at MSE beregnes med forskellen mellem det forudsagte output og den reelle etiket. Her er etiketten funktionen, fordi modellen forsøger at rekonstruere inputtet. Derfor vil du have middelværdien af ​​summen af ​​forskellen af ​​kvadratet mellem forudsagt output og input. Med TensorFlow kan du kode tabsfunktionen som følger:

loss = tf.reduce_mean(tf.square(outputs - features))

Derefter skal du optimere tabsfunktionen. Du bruger Adam optimizer til at beregne gradienterne. Den objektive funktion er at minimere tabet.

## Optimize
loss = tf.reduce_mean(tf.square(outputs - features))
optimizer = tf.train.AdamOptimizer(learning_rate)
train  = optimizer.minimize(loss)

Endnu en indstilling før træning af modellen. Du vil bruge en batchstørrelse på 150, det vil sige at fodre pipelinen med 150 billeder hver iteration. Du skal beregne antallet af iterationer manuelt. Dette er trivielt at gøre:

Hvis du vil sende 150 billeder hver gang, og du ved, at der er 5000 billeder i datasættet, er antallet af iterationer lig med . I python kan du køre following koder og sørg for, at outputtet er 33:

BATCH_SIZE = 150
### Number of batches :  length dataset / batch size
n_batches = horse_x.shape[0] // BATCH_SIZE
print(n_batches)
33

Trin 5) Kør modellen

Sidst, men ikke mindst, træne modellen. Du træner modellen med 100 epoker. Det vil sige, at modellen vil se 100 gange billederne til optimerede vægte.

Du er allerede bekendt med koderne til at træne en model i Tensorflow. Den lille forskel er at røre dataene, før du kører træningen. På den måde træner modellen hurtigere.

Du er interesseret i at udskrive tabet efter ti epoker for at se, om modellen lærer noget (dvs. tabet er faldende). Træningen tager 2 til 5 minutter, afhængigt af din maskinhardware.

## Set params
n_epochs = 100

## Call Saver to save the model and re-use it later during evaluation
saver = tf.train.Saver()

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    # initialise iterator with train data
    sess.run(iter.initializer, feed_dict={x: horse_x,
                                          batch_size: BATCH_SIZE})
    print('Training...')
    print(sess.run(features).shape) 
    for epoch in range(n_epochs):       
        for iteration in range(n_batches):
            sess.run(train)
        if epoch % 10 == 0:
            loss_train = loss.eval()   # not shown
            print("\r{}".format(epoch), "Train MSE:", loss_train) 
        #saver.save(sess, "./my_model_all_layers.ckpt") 
    save_path = saver.save(sess, "./model.ckpt")    
    print("Model saved in path: %s" % save_path)  
Training...
(150, 1024)
0 Train MSE: 2934.455
10 Train MSE: 1672.676
20 Train MSE: 1514.709
30 Train MSE: 1404.3118
40 Train MSE: 1425.058
50 Train MSE: 1479.0631
60 Train MSE: 1609.5259
70 Train MSE: 1482.3223
80 Train MSE: 1445.7035
90 Train MSE: 1453.8597
Model saved in path: ./model.ckpt

Trin 6) Vurder modellen

Nu hvor du har trænet din model, er det tid til at evaluere den. Du skal importere test-serien fra filen /cifar-10-batches-py/.

test_data = unpickle('./cifar-10-batches-py/test_batch')
test_x = grayscale(test_data['data'])
#test_labels = np.array(test_data['labels'])

BEMÆRK: For en Windows maskine, bliver koden test_data = unpickle(r”E:\cifar-10-batches-py\test_batch”)

Du kan prøve at printe billederne 13, som er en hest

plot_image(test_x[13], shape=[32, 32], cmap = "Greys_r")

Evaluer modellen

For at evaluere modellen skal du bruge pixelværdien af ​​dette billede og se, om koderen kan rekonstruere det samme billede efter at have krympet 1024 pixels. Bemærk, at du definerer en funktion til at evaluere modellen på forskellige billeder. Modellen burde kun fungere bedre på heste.

Funktionen tager to argumenter:

  • df: Importer testdataene
  • billednummer: angiv hvilket billede der skal importeres

Funktionen er opdelt i tre dele:

  1. Omform billedet til den korrekte dimension, dvs. 1, 1024
  2. Fodre modellen med det usete billede, indkode/afkode billedet
  3. Udskriv det rigtige og rekonstruerede billede
def reconstruct_image(df, image_number = 1):
    ## Part 1: Reshape the image to the correct dimension i.e 1, 1024
    x_test = df[image_number]
    x_test_1 = x_test.reshape((1, 32*32))
    
    ## Part 2: Feed the model with the unseen image, encode/decode the image
    with tf.Session() as sess:     
        sess.run(tf.global_variables_initializer()) 
        sess.run(iter.initializer, feed_dict={x: x_test_1,
                                      batch_size: 1})
    ## Part 3:  Print the real and reconstructed image
      # Restore variables from disk.
        saver.restore(sess, "./model.ckpt")  
        print("Model restored.")
      # Reconstruct image
        outputs_val = outputs.eval()
        print(outputs_val.shape)
        fig = plt.figure()
      # Plot real
        ax1 = fig.add_subplot(121)
        plot_image(x_test_1, shape=[32, 32], cmap = "Greys_r")
      # Plot estimated
        ax2 = fig.add_subplot(122)
        plot_image(outputs_val, shape=[32, 32], cmap = "Greys_r")
        plt.tight_layout()
        fig = plt.gcf()

Nu hvor evalueringsfunktionen er defineret, kan du se det rekonstruerede billede nummer tretten

reconstruct_image(df =test_x, image_number = 13)
INFO:tensorflow:Restoring parameters from ./model.ckpt
Model restored.
(1, 1024)

Evaluer modellen

Resumé

  • Det primære formål med en autoencoder er at komprimere inputdataene og derefter komprimere dem til et output, der ligner de originale data.
  • architecture af en autoencoder symmetrisk med et pivot lag kaldet det centrale lag.
  • Du kan oprette autoencoderen ved at bruge:
  • Delvis: for at skabe de tætte lag med den typiske indstilling:

      	tf.layers.dense,                         
      	activation=tf.nn.elu,                         
      	kernel_initializer=xav_init,                         
      	kernel_regularizer=l2_regularizer

    tæt_lag(): at lave matrixmultiplikationen

  • Du kan definere tabsfunktionen og optimeringen med:
  • loss = tf.reduce_mean(tf.square(outputs - features))
    optimizer = tf.train.AdamOptimizer(learning_rate)
    train  = optimizer.minimize(loss)
    
  • Kør sidst en session for at træne modellen.