Autokodare i TensorFlow med exempel
Vad är Autoencoder i Deep Learning?
An Autokodare är ett verktyg för att lära sig datakodning effektivt på ett oövervakat sätt. Det är en typ av konstgjorda neurala nätverk som hjälper dig att lära dig representationen av datamängder för dimensionsreduktion genom att träna det neurala nätverket att ignorera signalbruset. Det är ett utmärkt verktyg för att återskapa en ingång.
Med enkla ord, maskinen tar, låt oss säga en bild, och kan producera en närbesläktad bild. Ingången i denna typ av neurala nätverk är omärkt, vilket betyder att nätverket kan lära sig utan övervakning. Närmare bestämt är ingången kodad av nätverket för att bara fokusera på den mest kritiska egenskapen. Detta är en av anledningarna till att autoencoder är populärt för dimensionsreducering. Dessutom kan autoencoders användas för att producera generativa inlärningsmodeller. Till exempel kan det neurala nätverket tränas med en uppsättning ansikten och kan sedan producera nya ansikten.
Hur fungerar TensorFlow Autoencoder?
Syftet med en autoencoder är att producera en approximation av ingången genom att bara fokusera på de väsentliga funktionerna. Du kanske tänker varför inte bara lära dig hur man kopierar och klistrar in indata för att producera utdata. Faktum är att en autoencoder är en uppsättning begränsningar som tvingar nätverket att lära sig nya sätt att representera data, annorlunda än att bara kopiera utdata.
En typisk autokodare definieras med en ingång, en intern representation och en utgång (en approximation av ingången). Inlärningen sker i de lager som är knutna till den interna representationen. Faktum är att det finns två huvudblock av lager som ser ut som ett traditionellt neuralt nätverk. Den lilla skillnaden är att lagret som innehåller utgången måste vara lika med ingången. På bilden nedan går den ursprungliga ingången in i det första blocket som kallas kodare. Denna interna representation komprimerar (minskar) storleken på inmatningen. I det andra blocket sker rekonstruktionen av ingången. Detta är avkodningsfasen.
Modellen kommer att uppdatera vikterna genom att minimera förlustfunktionen. Modellen straffas om rekonstruktionsutgången skiljer sig från ingången.
Föreställ dig konkret en bild med en storlek på 50×50 (dvs. 250 pixlar) och ett neuralt nätverk med bara ett dolt lager bestående av hundra neuroner. Inlärningen sker på en funktionskarta som är två gånger mindre än inmatningen. Det betyder att nätverket måste hitta ett sätt att rekonstruera 250 pixlar med endast en vektor av neuroner lika med 100.
Exempel på staplad autokodare
I den här självstudien för Autoencoder kommer du att lära dig hur du använder en staplad autoencoder. Arkitekturen liknar ett traditionellt neuralt nätverk. Inmatningen går till ett dolt lager för att komprimeras eller minska dess storlek och når sedan rekonstruktionslagren. Målet är att producera en utgående bild så nära originalet. Modellen måste lära sig ett sätt att uppnå sin uppgift under en uppsättning begränsningar, det vill säga med en lägre dimension.
Nuförtiden, autoencoders in Deep Learning används främst för att försvaga en bild. Föreställ dig en bild med repor; en människa kan fortfarande känna igen innehållet. Idén med att denoising autoencoder är att lägga till brus till bilden för att tvinga nätverket att lära sig mönstret bakom data.
Den andra användbara familjen av Autoencoder Deep Learning är variationsautokodare. Den här typen av nätverk kan generera nya bilder. Föreställ dig att du tränar ett nätverk med bilden av en man; ett sådant nätverk kan skapa nya ansikten.
Hur man bygger en autokodare med TensorFlow
I den här handledningen kommer du att lära dig hur du bygger en staplad autokodare för att rekonstruera en bild.
Du kommer att använda CIFAR-10 dataset som innehåller 60000 32×32 färgbilder. Autoencoder-dataset är redan uppdelat mellan 50000 10000 bilder för träning och XNUMX XNUMX för testning. Det finns upp till tio klasser:
- Flygplan
- Automobile
- Fågel
- Cat
- Deer
- Dog
- groda
- Häst
- Ship
- Lastbil
Du måste ladda ner bilderna i denna URL https://www.cs.toronto.edu/~kriz/cifar.html och packa upp den. Mappen för-10-batches-py innehåller fem partier data med 10000 XNUMX bilder vardera i en slumpmässig ordning.
Innan du bygger och tränar din modell måste du tillämpa viss databehandling. Du kommer att gå tillväga enligt följande:
- Importera data
- Konvertera data till svartvitt format
- Lägg till alla satser
- Konstruera träningsdatauppsättningen
- Konstruera en bildvisualiserare
Bildförbehandling
Steg 1) Importera data
Enligt den officiella webbplatsen kan du ladda upp data med följande kod. Autoencoder-koden kommer att ladda data i en ordbok med datum och etikett. Observera att koden är 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
Steg 2) Konvertera data till svartvitt format
För enkelhetens skull kommer du att konvertera data till en gråskala. Det vill säga med endast en dimension mot tre för färgbild. Det mesta av det neurala nätverket fungerar bara med endimensionell input.
def grayscale(im): return im.reshape(im.shape[0], 3, 32, 32).mean(1).reshape(im.shape[0], -1)
Steg 3) Lägg till alla satser
Nu när båda funktionerna har skapats och datauppsättningen laddats kan du skriva en loop för att lägga till data i minnet. Om du kontrollerar noggrant, heter unzip-filen med data data_batch_ med ett nummer från 1 till 5. Du kan loopa över filerna och lägga till dem i data.
När detta steg är klart konverterar du färgdata till ett gråskaleformat. Som du kan se är formen på data 50000 och 1024. De 32*32 pixlarna är nu plattade till 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)
Obs: Ändra './cifar-10-batches-py/data_batch_' till den faktiska platsen för din fil. Till exempel för Windows maskin, sökvägen kan vara filnamn = 'E:\cifar-10-batches-py\data_batch_' + str(i)
Steg 4) Konstruera träningsdatauppsättningen
För att göra träningen snabbare och enklare kommer du att träna en modell endast på hästbilderna. Hästarna är den sjunde klassen i etikettdata. Som nämnts i dokumentationen för CIFAR-10-datauppsättningen innehåller varje klass 5000 bilder. Du kan skriva ut formen på data för att bekräfta att det finns 5.000 1024 bilder med XNUMX XNUMX kolumner som visas i nedan TensorFlow Exempelsteg för autoencoder.
horse_i = np.where(y == 7)[0] horse_x = x[horse_i] print(np.shape(horse_x)) (5000, 1024)
Steg 5) Konstruera en bildvisualiserare
Slutligen konstruerar du en funktion för att plotta bilderna. Du behöver denna funktion för att skriva ut den rekonstruerade bilden från autoencodern.
Ett enkelt sätt att skriva ut bilder är att använda objektet imshow från matplotlib-biblioteket. Observera att du måste konvertera formen på data från 1024 till 32*32 (dvs formatet på en bild).
# 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 tar 3 argument:
- Bild: ingången
- Forma: lista, bildens dimension
- cmap:välj färgkartan. Som standard, grå
Du kan försöka plotta den första bilden i datamängden. Du borde se en man på en häst.
plot_image(horse_x[1], shape=[32, 32], cmap = "Greys_r")
Ställ in Dataset Estimator
Okej, nu när datasetet är klart att använda kan du börja använda Tensorflow. Innan vi bygger modellen, låt oss använda Dataset-estimatorn för Tensorflow för att mata nätverket.
Du kommer att bygga en datamängd med TensorFlow estimator. För att fräscha upp ditt sinne måste du använda:
- from_tensor_slices
- upprepa
- sats
Den fullständiga koden för att bygga datamängden är:
dataset = tf.data.Dataset.from_tensor_slices(x).repeat().batch(batch_size)
Observera att x är en platshållare med följande form:
- [None,n_inputs]: Ställ in på None eftersom antalet bildmatningar till nätverket är lika med batchstorleken.
för detaljer, se handledningen om linjär regression.
Efter det måste du skapa iteratorn. Utan denna kodrad kommer ingen data att gå genom pipelinen.
iter = dataset.make_initializable_iterator() # create the iteratorfeatures = iter.get_next()
Nu när pipelinen är klar kan du kontrollera om den första bilden är densamma som tidigare (dvs en man på en häst).
Du ställer in batchstorleken till 1 eftersom du bara vill mata datamängden med en bild. Du kan se dimensionen på datan med print(sess.run(features).shape). Det är lika med (1, 1024). 1 betyder att endast en bild med 1024 matas vardera. Om batchstorleken är inställd på två, kommer två bilder att gå genom pipelinen. (Ändra inte batchstorleken. Annars kommer det att skapa ett fel. Endast en bild åt gången kan gå till 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)
Bygg nätverket
Det är dags att bygga nätverket. Du kommer att träna en staplad autokodare, det vill säga ett nätverk med flera dolda lager.
Ditt nätverk kommer att ha ett indatalager med 1024 punkter, dvs 32×32, bildens form.
Kodarblocket kommer att ha ett övre dolt lager med 300 neuroner, ett centralt lager med 150 neuroner. Avkodarblocket är symmetriskt till kodaren. Du kan visualisera nätverket på bilden nedan. Observera att du kan ändra värdena för dolda och centrala lager.
Att bygga en autoencoder är mycket likt vilken annan modell för djupinlärning som helst.
Du kommer att konstruera modellen enligt dessa steg:
- Definiera parametrarna
- Definiera lagren
- Definiera arkitekturen
- Definiera optimeringen
- Kör modellen
- Utvärdera modellen
I det föregående avsnittet lärde du dig hur man skapar en pipeline för att mata modellen, så det finns inget behov av att skapa datauppsättningen en gång till. Du kommer att konstruera en autoencoder med fyra lager. Du använder Xavier-initieringen. Detta är en teknik för att ställa in de initiala vikterna lika med variansen för både ingången och utmatningen. Slutligen använder du elu-aktiveringsfunktionen. Du reglerar förlustfunktionen med L2 regularizer.
Steg 1) Definiera parametrarna
Det första steget innebär att definiera antalet neuroner i varje lager, inlärningshastigheten och hyperparametern för regularizern.
Innan dess importerar du funktionen delvis. Det är en bättre metod att definiera parametrarna för de täta lagren. Koden nedan definierar värdena för autoencoder-arkitekturen. Som nämnts tidigare har autokodaren två lager, med 300 neuroner i det första lagret och 150 i det andra lagret. Deras värden lagras i n_hidden_1 och n_hidden_2.
Du måste definiera inlärningshastigheten och hyperparametern L2. Värdena lagras i learning_rate och 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-initieringstekniken anropas med objektet xavier_initializer från estimatorns bidrag. I samma estimator kan du lägga till regularizern 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)
Steg 2) Definiera lagren
Alla parametrar för de täta lagren har ställts in; du kan packa allt i variabeln dense_layer genom att använda objektet partial. dense_layer som använder ELU-aktivering, Xavier-initiering och L2-regularisering.
## Create the dense layer dense_layer = partial(tf.layers.dense, activation=tf.nn.elu, kernel_initializer=xav_init, kernel_regularizer=l2_regularizer)
Steg 3) Definiera arkitekturen
Om du tittar på bilden av arkitekturen, noterar du att nätverket staplar tre lager med ett utdatalager. I koden nedan kopplar du ihop lämpliga lager. Till exempel beräknar det första lagret punktprodukten mellan inmatningsmatrisegenskaperna och matriserna som innehåller de 300 vikterna. Efter att punktprodukten har beräknats går utsignalen till Elu-aktiveringsfunktionen. Utdatan blir indata för nästa lager, det är därför du använder den för att beräkna hidden_2 och så vidare. Matrismultiplikationen är densamma för varje lager eftersom du använder samma aktiveringsfunktion. Observera att det sista lagret, utgångar, inte tillämpar en aktiveringsfunktion. Det är vettigt eftersom detta är den rekonstruerade ingången
## 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)
Steg 4) Definiera optimeringen
Det sista steget är att konstruera optimeraren. Du använder Mean Square Error som en förlustfunktion. Om du kommer ihåg handledningen om linjär regression, vet du att MSE beräknas med skillnaden mellan den förutspådda utsignalen och den verkliga etiketten. Här är etiketten funktionen eftersom modellen försöker rekonstruera ingången. Därför vill du ha medelvärdet av summan av skillnaden i kvadraten mellan förutsagd utdata och ingång. Med TensorFlow kan du koda förlustfunktionen enligt följande:
loss = tf.reduce_mean(tf.square(outputs - features))
Sedan måste du optimera förlustfunktionen. Du använder Adam optimizer för att beräkna gradienterna. Den objektiva funktionen är att minimera förlusten.
## Optimize loss = tf.reduce_mean(tf.square(outputs - features)) optimizer = tf.train.AdamOptimizer(learning_rate) train = optimizer.minimize(loss)
Ytterligare en inställning innan du tränar modellen. Du vill använda en batchstorlek på 150, det vill säga mata pipelinen med 150 bilder varje iteration. Du måste beräkna antalet iterationer manuellt. Detta är trivialt att göra:
Om du vill skicka 150 bilder varje gång och du vet att det finns 5000 bilder i datamängden är antalet iterationer lika med . I python kan du köra följande koder och se till att utdata är 33:
BATCH_SIZE = 150 ### Number of batches : length dataset / batch size n_batches = horse_x.shape[0] // BATCH_SIZE print(n_batches) 33
Steg 5) Kör modellen
Sist men inte minst, träna modellen. Du tränar modellen med 100 epoker. Det vill säga, modellen kommer att se 100 gånger bilderna till optimerade vikter.
Du är redan bekant med koderna för att träna en modell i Tensorflow. Den lilla skillnaden är att röra data innan du kör träningen. På så sätt tränar modellen snabbare.
Du är intresserad av att skriva ut förlusten efter tio epoker för att se om modellen lär sig något (dvs. förlusten minskar). Utbildningen tar 2 till 5 minuter, beroende på din maskinvara.
## 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
Steg 6) Utvärdera modellen
Nu när du har tränat din modell är det dags att utvärdera den. Du måste importera testserien från 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'])
ANMÄRKNINGAR: För en Windows maskin, koden blir test_data = unpickle(r”E:\cifar-10-batches-py\test_batch”)
Du kan prova att skriva ut bilderna 13, som är en häst
plot_image(test_x[13], shape=[32, 32], cmap = "Greys_r")
För att utvärdera modellen kommer du att använda pixelvärdet för denna bild och se om kodaren kan rekonstruera samma bild efter att ha krympt 1024 pixlar. Observera att du definierar en funktion för att utvärdera modellen på olika bilder. Modellen borde fungera bättre bara på hästar.
Funktionen tar två argument:
- df: Importera testdata
- bildnummer: ange vilken bild som ska importeras
Funktionen är uppdelad i tre delar:
- Forma om bilden till rätt dimension, dvs 1, 1024
- Mata modellen med den osynliga bilden, koda/avkoda bilden
- Skriv ut den verkliga och rekonstruerade bilden
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 när utvärderingsfunktionen är definierad kan du ta en titt på den rekonstruerade bilden nummer tretton
reconstruct_image(df =test_x, image_number = 13)
INFO:tensorflow:Restoring parameters from ./model.ckpt Model restored. (1, 1024)
Sammanfattning
- Det primära syftet med en autoencoder är att komprimera indata och sedan komprimera den till en utdata som liknar originaldata.
- Arkitekturen för en autoencoder symmetrisk med ett pivotlager som heter det centrala lagret.
- Du kan skapa autokodaren med:
Partiell: för att skapa de täta lagren med den typiska inställningen:
tf.layers.dense, activation=tf.nn.elu, kernel_initializer=xav_init, kernel_regularizer=l2_regularizer
dense_layer(): för att göra matrismultiplikationen
loss = tf.reduce_mean(tf.square(outputs - features)) optimizer = tf.train.AdamOptimizer(learning_rate) train = optimizer.minimize(loss)