Autoenkoder i TensorFlow med eksempel
Hva er Autoencoder i Deep Learning?
An Autokoder er et verktøy for å lære datakoding effektivt på en uovervåket måte. Det er en type kunstig nevrale nettverk som hjelper deg å lære representasjonen av datasett for dimensjonalitetsreduksjon ved å trene det nevrale nettverket til å ignorere signalstøyen. Det er et flott verktøy for å gjenskape en input.
Med enkle ord tar maskinen, la oss si et bilde, og kan produsere et nært beslektet bilde. Inngangen i denne typen nevrale nettverk er umerket, noe som betyr at nettverket er i stand til å lære uten tilsyn. Mer presist er inngangen kodet av nettverket for kun å fokusere på den mest kritiske funksjonen. Dette er en av grunnene til at autoencoder er populær for dimensjonsreduksjon. Dessuten kan autoenkodere brukes til å produsere generative læringsmodeller. For eksempel kan det nevrale nettverket trenes med et sett med ansikter og deretter produsere nye ansikter.
Hvordan fungerer TensorFlow Autoencoder?
Hensikten med en autoenkoder er å produsere en tilnærming av inngangen ved kun å fokusere på de essensielle funksjonene. Du tenker kanskje hvorfor ikke bare lære hvordan du kopierer og limer inn input for å produsere utdata. Faktisk er en autokoder et sett med begrensninger som tvinger nettverket til å lære nye måter å representere dataene på, annerledes enn bare å kopiere utdataene.
En typisk autoenkoder er definert med en inngang, en intern representasjon og en utgang (en tilnærming av inngangen). Læringen skjer i lagene knyttet til den interne representasjonen. Faktisk er det to hovedblokker av lag som ser ut som et tradisjonelt nevralt nettverk. Den lille forskjellen er at laget som inneholder utgangen må være lik inngangen. På bildet nedenfor går den originale inngangen inn i den første blokken kalt encoder. Denne interne representasjonen komprimerer (reduserer) størrelsen på inngangen. I den andre blokken skjer rekonstruksjonen av inngangen. Dette er dekodingsfasen.
Modellen vil oppdatere vektene ved å minimere tapsfunksjonen. Modellen straffes hvis rekonstruksjonsutgangen er forskjellig fra inngangen.
Tenk deg konkret et bilde med en størrelse på 50×50 (dvs. 250 piksler) og et nevralt nettverk med bare ett skjult lag som består av hundre nevroner. Læringen gjøres på et funksjonskart som er to ganger mindre enn innspillet. Det betyr at nettverket må finne en måte å rekonstruere 250 piksler med bare en vektor av nevroner lik 100.
Eksempel på stablet autoencoder
I denne Autoencoder-opplæringen lærer du hvordan du bruker en stablet autoencoder. Arkitekturen ligner på et tradisjonelt nevralt nettverk. Inndataene går til et skjult lag for å bli komprimert, eller redusere størrelsen, og når deretter rekonstruksjonslagene. Målet er å produsere et utgangsbilde så nært som originalen. Modellen må lære en måte å oppnå oppgaven sin på under et sett av begrensninger, det vil si med en lavere dimensjon.
I dag er autoenkodere i Dyp læring brukes hovedsakelig til å forringe et bilde. Se for deg et bilde med riper; et menneske er fortsatt i stand til å gjenkjenne innholdet. Ideen med å denoising autoencoder er å legge til støy til bildet for å tvinge nettverket til å lære mønsteret bak dataene.
Den andre nyttige familien av Autoencoder Deep Learning er variasjonsautokoder. Denne typen nettverk kan generere nye bilder. Tenk deg at du trener et nettverk med bildet av en mann; et slikt nettverk kan produsere nye ansikter.
Hvordan bygge en autokoder med TensorFlow
I denne opplæringen lærer du hvordan du bygger en stablet autoenkoder for å rekonstruere et bilde.
Du vil bruke CIFAR-10 datasett som inneholder 60000 32 32×50000 fargebilder. Autoencoder-datasettet er allerede delt mellom 10000 XNUMX bilder for trening og XNUMX XNUMX for testing. Det er opptil ti klasser:
- Fly
- Automobile
- Fugl
- Katt
- Hjort
- Hund
- Frog
- Hest
- Ship
- Lastebil
Du må laste ned bildene i denne URLen https://www.cs.toronto.edu/~kriz/cifar.html og pakke den ut. Mappen for-10-batches-py inneholder fem batcher med data med 10000 XNUMX bilder hver i tilfeldig rekkefølge.
Før du bygger og trener modellen din, må du bruke litt databehandling. Du vil fortsette som følger:
- Importer dataene
- Konverter dataene til svart-hvitt-format
- Legg til alle batchene
- Konstruer opplæringsdatasettet
- Konstruer en bildevisualisering
Bildeforbehandling
Trinn 1) Importer dataene
I følge det offisielle nettstedet kan du laste opp dataene med følgende kode. Autoencoder-koden vil laste inn dataene i en ordbok med dato og etikett. Merk at koden er en funksjon.
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
Trinn 2) Konverter dataene til svart-hvitt-format
For enkelhets skyld vil du konvertere dataene til en gråtone. Det vil si med kun én dimensjon mot tre for farger bilde. Det meste av det nevrale nettverket fungerer bare med én dimensjons input.
def grayscale(im): return im.reshape(im.shape[0], 3, 32, 32).mean(1).reshape(im.shape[0], -1)
Trinn 3) Legg til alle batchene
Nå som begge funksjonene er opprettet og datasettet lastet, kan du skrive en løkke for å legge til dataene i minnet. Hvis du sjekker nøye, heter unzip-filen med dataene data_batch_ med et tall fra 1 til 5. Du kan gå over filene og legge den til data.
Når dette trinnet er gjort, konverterer du fargedataene til et gråskalaformat. Som du kan se, er formen på dataene 50000 1024 og 32. 32*2014 piksler er nå flatet ut til XNUMX.
# 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)
Merk: Endre './cifar-10-batches-py/data_batch_' til den faktiske plasseringen av filen. For eksempel for Windows maskinen, kan banen være filnavn = 'E:\cifar-10-batches-py\data_batch_' + str(i)
Trinn 4) Konstruer treningsdatasettet
For å gjøre treningen raskere og enklere vil du trene en modell kun på hestebildene. Hestene er den syvende klassen i etikettdataene. Som nevnt i dokumentasjonen til CIFAR-10-datasettet, inneholder hver klasse 5000 bilder. Du kan skrive ut formen på dataene for å bekrefte at det er 5.000 1024 bilder med XNUMX kolonner som vist nedenfor tensorflow Autoencoder eksempeltrinn.
horse_i = np.where(y == 7)[0] horse_x = x[horse_i] print(np.shape(horse_x)) (5000, 1024)
Trinn 5) Konstruer en bildevisualisering
Til slutt konstruerer du en funksjon for å plotte bildene. Du trenger denne funksjonen for å skrive ut det rekonstruerte bildet fra autoenkoderen.
En enkel måte å skrive ut bilder på er å bruke objektet imshow fra matplotlib-biblioteket. Merk at du må konvertere formen på dataene fra 1024 til 32*32 (dvs. formatet til et bilde).
# 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")
Funksjonen tar 3 argumenter:
- Bilde: inngangen
- Form: liste, dimensjonen til bildet
- Cmap:velg fargekartet. Som standard, grå
Du kan prøve å plotte det første bildet i datasettet. Du burde se en mann på en hest.
plot_image(horse_x[1], shape=[32, 32], cmap = "Greys_r")
Sett datasettestimator
Greit, nå som datasettet er klart til bruk, kan du begynne å bruke Tensorflow. Før vi bygger modellen, la oss bruke Dataset-estimatoren til Tensorflow for å mate nettverket.
Du vil bygge et datasett med TensorFlow-estimator. For å friske opp sinnet ditt, må du bruke:
- from_tensor_slices
- gjenta
- batch
Den fullstendige koden for å bygge datasettet er:
dataset = tf.data.Dataset.from_tensor_slices(x).repeat().batch(batch_size)
Merk at x er en plassholder med følgende form:
- [None,n_inputs]: Sett til None fordi antall bildefeed til nettverket er lik batchstørrelsen.
for detaljer, se veiledningen på lineær regresjon.
Etter det må du lage iteratoren. Uten denne kodelinjen vil ingen data gå gjennom rørledningen.
iter = dataset.make_initializable_iterator() # create the iteratorfeatures = iter.get_next()
Nå som rørledningen er klar, kan du sjekke om det første bildet er det samme som før (dvs. en mann på en hest).
Du setter batchstørrelsen til 1 fordi du bare vil mate datasettet med ett bilde. Du kan se dimensjonen til dataene med print(sess.run(features).shape). Det er lik (1, 1024). 1 betyr at bare ett bilde med 1024 er feed hver. Hvis batchstørrelsen er satt til to, vil to bilder gå gjennom rørledningen. (Ikke endre batchstørrelsen. Ellers vil det gi en feil. Bare ett bilde om gangen kan gå til funksjonen 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)
Bygg nettverket
Det er på tide å bygge nettverket. Du vil trene en stablet autoenkoder, det vil si et nettverk med flere skjulte lag.
Nettverket ditt vil ha ett inputlag med 1024 punkter, dvs. 32×32, formen på bildet.
Enkoderblokken vil ha ett topp skjult lag med 300 nevroner, et sentralt lag med 150 nevroner. Dekoderblokken er symmetrisk med koderen. Du kan visualisere nettverket på bildet nedenfor. Merk at du kan endre verdiene for skjulte og sentrale lag.
Å bygge en autoencoder er veldig lik alle andre dyplæringsmodeller.
Du vil konstruere modellen ved å følge disse trinnene:
- Definer parametrene
- Definer lagene
- Definer arkitekturen
- Definer optimaliseringen
- Kjør modellen
- Evaluer modellen
I forrige avsnitt lærte du hvordan du oppretter en pipeline for å mate modellen, så det er ikke nødvendig å opprette datasettet en gang til. Du vil konstruere en autoencoder med fire lag. Du bruker Xavier-initialiseringen. Dette er en teknikk for å sette startvektene lik variansen til både input og output. Til slutt bruker du elu-aktiveringsfunksjonen. Du regulariserer tapsfunksjonen med L2-regularizer.
Trinn 1) Definer parametrene
Det første trinnet innebærer å definere antall nevroner i hvert lag, læringshastigheten og hyperparameteren til regularizeren.
Før det importerer du funksjonen delvis. Det er en bedre metode for å definere parametrene til de tette lagene. Koden nedenfor definerer verdiene til autoencoder-arkitekturen. Som nevnt før har autokoderen to lag, med 300 nevroner i det første laget og 150 i det andre laget. Verdiene deres er lagret i n_hidden_1 og n_hidden_2.
Du må definere læringshastigheten og L2-hyperparameteren. Verdiene lagres 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 kalles med objektet xavier_initializer fra estimatorbidraget. I samme estimator kan du legge til regularizer 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)
Trinn 2) Definer lagene
Alle parametrene til de tette lagene er satt; du kan pakke alt i variabelen dense_layer ved å bruke objektet partial. dense_layer som bruker 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)
Trinn 3) Definer arkitekturen
Hvis du ser på bildet av arkitekturen, legger du merke til at nettverket stabler tre lag med et utgangslag. I koden nedenfor kobler du de riktige lagene. For eksempel beregner det første laget punktproduktet mellom inngangsmatrisefunksjonene og matrisene som inneholder de 300 vektene. Etter at punktproduktet er beregnet, går utgangen til Elu-aktiveringsfunksjonen. Utgangen blir inngangen til neste lag, det er derfor du bruker den til å beregne hidden_2 og så videre. Matrismultiplikasjonen er den samme for hvert lag fordi du bruker den samme aktiveringsfunksjonen. Merk at det siste laget, utganger, ikke bruker en aktiveringsfunksjon. Det er fornuftig fordi dette er det rekonstruerte innspillet
## 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)
Trinn 4) Definer optimaliseringen
Det siste trinnet er å konstruere optimalisereren. Du bruker Mean Square Error som en tapsfunksjon. Hvis du husker veiledningen om lineær regresjon, vet du at MSE beregnes med forskjellen mellom den forutsagte utgangen og den virkelige etiketten. Her er etiketten funksjonen fordi modellen prøver å rekonstruere inngangen. Derfor vil du ha gjennomsnittet av summen av differansen av kvadratet mellom predikert utgang og inngang. Med TensorFlow kan du kode tapsfunksjonen som følger:
loss = tf.reduce_mean(tf.square(outputs - features))
Deretter må du optimalisere tapsfunksjonen. Du bruker Adam optimizer for å beregne gradientene. Den objektive funksjonen er å minimere tapet.
## Optimize loss = tf.reduce_mean(tf.square(outputs - features)) optimizer = tf.train.AdamOptimizer(learning_rate) train = optimizer.minimize(loss)
En innstilling til før du trener modellen. Du vil bruke en batchstørrelse på 150, det vil si å mate rørledningen med 150 bilder hver iterasjon. Du må beregne antall iterasjoner manuelt. Dette er trivielt å gjøre:
Hvis du vil passere 150 bilder hver gang og du vet at det er 5000 bilder i datasettet, er antall iterasjoner lik . I python kan du kjøre følgende koder og sørge for at utgangen er 33:
BATCH_SIZE = 150 ### Number of batches : length dataset / batch size n_batches = horse_x.shape[0] // BATCH_SIZE print(n_batches) 33
Trinn 5) Kjør modellen
Sist men ikke minst, tren modellen. Du trener modellen med 100 epoker. Det vil si at modellen vil se 100 ganger bildene til optimaliserte vekter.
Du er allerede kjent med kodene for å trene en modell i Tensorflow. Den lille forskjellen er å røre dataene før du kjører treningen. På denne måten trener modellen raskere.
Du er interessert i å skrive ut tapet etter ti epoker for å se om modellen lærer noe (dvs. tapet avtar). Opplæringen tar 2 til 5 minutter, avhengig av maskinvaren din.
## 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
Trinn 6) Evaluer modellen
Nå som du har trent modellen din, er det på tide å evaluere den. Du må importere testsettet 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'])
MERKNADER: For en Windows maskin, blir koden test_data = unpickle(r”E:\cifar-10-batches-py\test_batch”)
Du kan prøve å skrive ut bildene 13, som er en hest
plot_image(test_x[13], shape=[32, 32], cmap = "Greys_r")
For å evaluere modellen vil du bruke pikselverdien til dette bildet og se om koderen kan rekonstruere det samme bildet etter å ha krympet 1024 piksler. Merk at du definerer en funksjon for å evaluere modellen på forskjellige bilder. Modellen skal fungere bedre kun på hester.
Funksjonen tar to argumenter:
- df: Importer testdataene
- bildenummer: angi hvilket bilde som skal importeres
Funksjonen er delt inn i tre deler:
- Omform bildet til riktig dimensjon, dvs. 1, 1024
- Mat modellen med det usette bildet, kod/dekod bildet
- Skriv ut det ekte og rekonstruerte bildet
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()
Nå som evalueringsfunksjonen er definert, kan du ta en titt på det rekonstruerte bildet nummer tretten
reconstruct_image(df =test_x, image_number = 13)
INFO:tensorflow:Restoring parameters from ./model.ckpt Model restored. (1, 1024)
Sammendrag
- Hovedformålet med en autoencoder er å komprimere inngangsdataene, og deretter komprimere dem til en utgang som ligner de originale dataene.
- Arkitekturen til en autoencoder symmetrisk med et pivotlag kalt det sentrale laget.
- Du kan opprette autoenkoderen ved å bruke:
Delvis: for å lage de tette lagene med den typiske innstillingen:
tf.layers.dense, activation=tf.nn.elu, kernel_initializer=xav_init, kernel_regularizer=l2_regularizer
tett_lag(): for å lage matrisemultiplikasjonen
loss = tf.reduce_mean(tf.square(outputs - features)) optimizer = tf.train.AdamOptimizer(learning_rate) train = optimizer.minimize(loss)