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. Arkitekturen 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 fรธlgende 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 fรธlgende form:

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

for detaljer, se venligst selvstudiet om 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. Ellers 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 ved at fรธlge disse trin:

  1. Definer parametrene
  2. Definer lagene
  3. Definer arkitekturen
  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 autoencoder-arkitekturen. 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 arkitekturen

Hvis du ser pรฅ billedet af arkitekturen, 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 fรธlgende koder og sรธrge 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.
  • Arkitekturen af โ€‹โ€‹en autoencoder symmetrisk med et pivotlag 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.

Opsummer dette indlรฆg med: