Autoencoder in TensorFlow met voorbeeld
Wat is Autoencoder in Deep Learning?
An Auto-encoder is een hulpmiddel om gegevenscodering efficiënt en zonder toezicht te leren. Het is een soort kunstmatig neuraal netwerk dat u helpt de representatie van datasets te leren voor dimensionaliteitsreductie door het neurale netwerk te trainen om de signaalruis te negeren. Het is een geweldig hulpmiddel voor het opnieuw creëren van een invoer.
In eenvoudige bewoordingen: de machine neemt, laten we zeggen, een afbeelding en kan een nauw verwante afbeelding produceren. De input in dit soort neurale netwerken is ongelabeld, wat betekent dat het netwerk zonder toezicht kan leren. Om precies te zijn: de invoer wordt door het netwerk gecodeerd om zich alleen op de meest kritische functie te concentreren. Dit is een van de redenen waarom autoencoder populair is voor dimensionaliteitsreductie. Bovendien kunnen autoencoders worden gebruikt om te produceren generatieve leermodellen. Het neurale netwerk kan bijvoorbeeld worden getraind met een reeks gezichten en vervolgens nieuwe gezichten produceren.
Hoe werkt TensorFlow Autoencoder?
Het doel van een autoencoder is om een benadering van de invoer te produceren door zich alleen op de essentiële kenmerken te concentreren. Je denkt misschien waarom je niet alleen leert hoe je de invoer kunt kopiëren en plakken om de uitvoer te produceren. In feite is een autoencoder een reeks beperkingen die het netwerk dwingen nieuwe manieren te leren om de gegevens weer te geven, anders dan alleen het kopiëren van de uitvoer.
Een typische autoencoder wordt gedefinieerd met een invoer, een interne representatie en een uitvoer (een benadering van de invoer). Het leren vindt plaats in de lagen die aan de interne representatie zijn verbonden. In feite zijn er twee hoofdblokken met lagen die op een traditioneel neuraal netwerk lijken. Het kleine verschil is dat de laag die de uitvoer bevat gelijk moet zijn aan de invoer. In de onderstaande afbeelding gaat de originele invoer naar het eerste blok dat de encoder. Deze interne representatie comprimeert (verkleint) de omvang van de invoer. In het tweede blok vindt de reconstructie van de invoer plaats. Dit is de decodeerfase.
Het model zal de gewichten bijwerken door de verliesfunctie te minimaliseren. Het model wordt bestraft als de reconstructie-output verschilt van de input.
Stel je concreet een afbeelding voor met een formaat van 50×50 (dwz 250 pixels) en een neuraal netwerk met slechts één verborgen laag bestaande uit honderd neuronen. Het leren gebeurt op een feature map die twee keer kleiner is dan de invoer. Het betekent dat het netwerk een manier moet vinden om 250 pixels te reconstrueren met slechts een vector van neuronen gelijk aan 100.
Gestapeld Autoencoder-voorbeeld
In deze Autoencoder-zelfstudie leert u hoe u een gestapelde autoencoder gebruikt. De architectuur is vergelijkbaar met een traditioneel neuraal netwerk. De invoer gaat naar een verborgen laag om te worden gecomprimeerd of de grootte ervan te verkleinen en bereikt vervolgens de reconstructielagen. Het doel is om een uitvoerafbeelding te produceren die zo dicht mogelijk bij het origineel ligt. Het model moet een manier leren om zijn taak te bereiken onder een reeks beperkingen, dat wil zeggen met een lagere dimensie.
Tegenwoordig zijn er auto-encoders in Diepe leren worden voornamelijk gebruikt om ruis in een afbeelding te verwijderen. Stel je een afbeelding voor met krassen; een mens kan de inhoud nog steeds herkennen. Het idee van het ontruisen van autoencoder is om ruis aan het beeld toe te voegen om het netwerk te dwingen het patroon achter de gegevens te leren kennen.
De andere nuttige familie van Autoencoder Deep Learning is de variabele autoencoder. Dit type netwerk kan nieuwe beelden genereren. Stel je voor dat je een netwerk traint met het beeld van een man; zo'n netwerk kan nieuwe gezichten opleveren.
Hoe u een auto-encoder bouwt met TensorFlow
In deze zelfstudie leert u hoe u een gestapelde autoencoder bouwt om een afbeelding te reconstrueren.
Je gebruikt de CIFAR-10-gegevensset die 60000 32×32 kleurenafbeeldingen bevat. De Autoencoder-dataset is al verdeeld over 50000 afbeeldingen voor training en 10000 voor testen. Er zijn maximaal tien klassen:
- Vliegtuig
- Automobile
- Vogel
- Kat
- Hert
- Hond
- Kikker
- Paard
- Verzenden
- Vrachtwagen
U moet de afbeeldingen in deze URL https://www.cs.toronto.edu/~kriz/cifar.html downloaden en uitpakken. De map for-10-batches-py bevat vijf batches met gegevens met elk 10000 afbeeldingen in willekeurige volgorde.
Voordat u uw model bouwt en traint, moet u enige gegevensverwerking toepassen. U gaat als volgt te werk:
- Importeer de gegevens
- Converteer de gegevens naar zwart-witformaat
- Voeg alle batches toe
- Construeer de trainingsgegevensset
- Bouw een beeldvisualizer
Voorbewerking van afbeeldingen
Stap 1) Importeer de gegevens
Volgens de officiële website kunt u de gegevens uploaden met de volgende code. De Autoencoder-code laadt de gegevens in een woordenboek met de gegevens en label. Merk op dat de code een functie is.
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
Stap 2) Converteer de gegevens naar zwart-witformaat
Voor de eenvoud converteert u de gegevens naar grijswaarden. Dat wil zeggen, met slechts één dimensie tegen drie voor het kleurenbeeld. Het grootste deel van het neurale netwerk werkt alleen met invoer uit één dimensie.
def grayscale(im): return im.reshape(im.shape[0], 3, 32, 32).mean(1).reshape(im.shape[0], -1)
Stap 3) Voeg alle batches toe
Nu beide functies zijn gemaakt en de dataset is geladen, kunt u een lus schrijven om de gegevens in het geheugen toe te voegen. Als je het zorgvuldig controleert, heet het uitgepakte bestand met de gegevens data_batch_ met een nummer van 1 tot 5. Je kunt de bestanden doorlopen en aan de gegevens toevoegen.
Wanneer deze stap is voltooid, converteert u de kleurgegevens naar een grijswaardenindeling. Zoals u kunt zien, is de vorm van de gegevens 50000 en 1024. De 32*32 pixels zijn nu afgevlakt naar 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)
Opmerking: Wijzig './cifar-10-batches-py/data_batch_' naar de daadwerkelijke locatie van uw bestand. Bijvoorbeeld voor Windows machine, kan het pad de bestandsnaam = 'E:\cifar-10-batches-py\data_batch_' + str(i) zijn
Stap 4) Construeer de trainingsgegevensset
Om de training sneller en gemakkelijker te maken, train je een model alleen op de paardenafbeeldingen. De paarden zijn de zevende klasse in de labelgegevens. Zoals vermeld in de documentatie van de CIFAR-10-dataset, bevat elke klasse 5000 afbeeldingen. U kunt de vorm van de gegevens afdrukken om te bevestigen dat er 5.000 afbeeldingen met 1024 kolommen zijn, zoals hieronder weergegeven TensorFlow Voorbeeldstap Autoencoder.
horse_i = np.where(y == 7)[0] horse_x = x[horse_i] print(np.shape(horse_x)) (5000, 1024)
Stap 5) Bouw een beeldvisualizer
Ten slotte construeert u een functie om de afbeeldingen te plotten. U hebt deze functie nodig om het gereconstrueerde beeld vanuit de autoencoder af te drukken.
Een gemakkelijke manier om afbeeldingen af te drukken is door het object imshow uit de matplotlib-bibliotheek te gebruiken. Houd er rekening mee dat u de vorm van de gegevens moet converteren van 1024 naar 32*32 (dwz het formaat van een afbeelding).
# 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")
De functie heeft 3 argumenten nodig:
- Beeld: de invoer
- Vorm: lijst, de afmeting van de afbeelding
- cmap: kies de kleurenkaart. Standaard grijs
U kunt proberen de eerste afbeelding in de gegevensset te plotten. Je zou een man op een paard moeten zien.
plot_image(horse_x[1], shape=[32, 32], cmap = "Greys_r")
Gegevenssetschatter instellen
Oké, nu de dataset klaar is voor gebruik, kun je Tensorflow gaan gebruiken. Voordat we het model bouwen, gebruiken we de Dataset-schatter van Tensorflow om het netwerk te voeden.
Je bouwt een dataset met de TensorFlow-schatter. Om je geest op te frissen, moet je het volgende gebruiken:
- van_tensor_slices
- herhaling
- partij
De volledige code om de dataset te bouwen is:
dataset = tf.data.Dataset.from_tensor_slices(x).repeat().batch(batch_size)
Merk op dat x een tijdelijke aanduiding is met de volgende vorm:
- [None,n_inputs]: Stel in op Geen omdat het aantal beeldfeeds naar het netwerk gelijk is aan de batchgrootte.
voor meer informatie, zie de tutorial op lineaire regressie.
Daarna moet u de iterator maken. Zonder deze regel code gaan er geen gegevens door de pijplijn.
iter = dataset.make_initializable_iterator() # create the iteratorfeatures = iter.get_next()
Nu de pijplijn gereed is, kunt u controleren of de eerste afbeelding hetzelfde is als voorheen (dwz een man op een paard).
U stelt de batchgrootte in op 1 omdat u de dataset alleen met één afbeelding wilt voeden. U kunt de dimensie van de gegevens zien met print(sess.run(features).shape). Deze is gelijk aan (1, 1024). 1 betekent dat er slechts één afbeelding met 1024 per afbeelding wordt gevoed. Als de batchgrootte is ingesteld op twee, gaan er twee afbeeldingen door de pijplijn. (Wijzig de batchgrootte niet. Anders wordt er een fout gegenereerd. Er kan slechts één afbeelding tegelijk naar de functie plot_image() gaan.)
## 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)
Bouw het netwerk
Het is tijd om het netwerk aan te leggen. Je traint een gestapelde autoencoder, dat wil zeggen een netwerk met meerdere verborgen lagen.
Uw netwerk heeft één invoerlaag met 1024 punten, dat wil zeggen 32×32, de vorm van de afbeelding.
Het encoderblok zal één verborgen bovenste laag hebben met 300 neuronen, een centrale laag met 150 neuronen. Het decoderblok is symmetrisch ten opzichte van de encoder. U kunt het netwerk visualiseren in de onderstaande afbeelding. Merk op dat u de waarden van verborgen en centrale lagen kunt wijzigen.
Het bouwen van een autoencoder lijkt sterk op elk ander deep learning-model.
U bouwt het model volgens de volgende stappen:
- Definieer de parameters
- Definieer de lagen
- Definieer de architectuur
- Definieer de optimalisatie
- Voer het model uit
- Evalueer het model
In de vorige sectie hebt u geleerd hoe u een pijplijn kunt maken om het model te voeden, zodat u de gegevensset niet opnieuw hoeft te maken. Je gaat een autoencoder bouwen met vier lagen. U gebruikt de Xavier-initialisatie. Dit is een techniek om de initiële gewichten gelijk te stellen aan de variantie van zowel de invoer als de uitvoer. Tenslotte maak je gebruik van de elu-activeringsfunctie. Je regulariseert de verliesfunctie met L2 regularizer.
Stap 1) Definieer de parameters
De eerste stap impliceert het definiëren van het aantal neuronen in elke laag, de leersnelheid en de hyperparameter van de regularizer.
Daarvoor importeert u de functie gedeeltelijk. Het is een betere methode om de parameters van de dichte lagen te definiëren. De onderstaande code definieert de waarden van de autoencoderarchitectuur. Zoals eerder vermeld, heeft de autoencoder twee lagen, met 300 neuronen in de eerste lagen en 150 in de tweede lagen. Hun waarden worden opgeslagen in n_hidden_1 en n_hidden_2.
U moet de leersnelheid en de L2-hyperparameter definiëren. De waarden worden opgeslagen in learning_rate en 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
De Xavier-initialisatietechniek wordt aangeroepen met het object xavier_initializer uit de schattercontrib. In dezelfde schatter kunt u de regularizer toevoegen met 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)
Stap 2) Definieer de lagen
Alle parameters van de dichte lagen zijn ingesteld; je kunt alles in de variabele density_layer inpakken door het object gedeeltelijk te gebruiken. density_layer die gebruik maakt van de ELU-activering, Xavier-initialisatie en L2-regularisatie.
## Create the dense layer dense_layer = partial(tf.layers.dense, activation=tf.nn.elu, kernel_initializer=xav_init, kernel_regularizer=l2_regularizer)
Stap 3) Definieer de architectuur
Als u naar de afbeelding van de architectuur kijkt, ziet u dat het netwerk drie lagen stapelt met een uitvoerlaag. In de onderstaande code verbindt u de juiste lagen. De eerste laag berekent bijvoorbeeld het dot-product tussen de invoermatrices en de matrices met de 300 gewichten. Nadat het dot-product is berekend, gaat de uitvoer naar de Elu-activeringsfunctie. De uitvoer wordt de invoer van de volgende laag, daarom gebruikt u deze om hidden_2 te berekenen, enzovoort. De matricesvermenigvuldiging is voor elke laag hetzelfde, omdat u dezelfde activeringsfunctie gebruikt. Merk op dat de laatste laag, uitvoer, geen activeringsfunctie toepast. Het is logisch, omdat dit de gereconstrueerde invoer is
## 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)
Stap 4) Definieer de optimalisatie
De laatste stap is het bouwen van de optimizer. U gebruikt de Mean Square Error als verliesfunctie. Als u zich de tutorial over lineaire regressie herinnert, weet u dat de MSE wordt berekend op basis van het verschil tussen de voorspelde output en het echte label. Hier is het label het kenmerk omdat het model de invoer probeert te reconstrueren. Daarom wilt u het gemiddelde van de som van het verschil in het kwadraat tussen de voorspelde uitvoer en invoer. Met TensorFlow kunt u de verliesfunctie als volgt coderen:
loss = tf.reduce_mean(tf.square(outputs - features))
Vervolgens moet u de verliesfunctie optimaliseren. U gebruikt Adam Optimizer om de gradiënten te berekenen. De objectieve functie is het minimaliseren van het verlies.
## Optimize loss = tf.reduce_mean(tf.square(outputs - features)) optimizer = tf.train.AdamOptimizer(learning_rate) train = optimizer.minimize(loss)
Nog één instelling voordat u het model traint. U wilt een batchgrootte van 150 gebruiken, dat wil zeggen dat u de pijplijn elke iteratie met 150 afbeeldingen voedt. U moet het aantal iteraties handmatig berekenen. Dit is triviaal om te doen:
Als u elke keer 150 afbeeldingen wilt doorgeven en u weet dat er 5000 afbeeldingen in de dataset zitten, is het aantal iteraties gelijk aan . In Python kunt u de volgende codes uitvoeren en ervoor zorgen dat de uitvoer 33 is:
BATCH_SIZE = 150 ### Number of batches : length dataset / batch size n_batches = horse_x.shape[0] // BATCH_SIZE print(n_batches) 33
Stap 5) Voer het model uit
Tenslotte, maar daarom niet minder belangrijk, train het model. Je traint het model met 100 tijdperken. Dat wil zeggen dat het model 100 keer de afbeeldingen zal zien met geoptimaliseerde gewichten.
Je bent al bekend met de codes om een model te trainen in Tensorflow. Het kleine verschil is dat de gegevens worden doorgesluisd voordat de training wordt uitgevoerd. Op deze manier traint het model sneller.
U bent geïnteresseerd in het afdrukken van het verlies na tien tijdperken om te zien of het model iets leert (dat wil zeggen: het verlies neemt af). De training duurt 2 tot 5 minuten, afhankelijk van de hardware van uw machine.
## 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
Stap 6) Evalueer het model
Nu u uw model hebt getraind, is het tijd om het te evalueren. U moet de testserie importeren uit het bestand /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'])
NOTITIE: Voor een Windows machine, de code wordt test_data = unpickle(r”E:\cifar-10-batches-py\test_batch”)
Je kunt proberen de afbeelding 13, dat is een paard, af te drukken
plot_image(test_x[13], shape=[32, 32], cmap = "Greys_r")
Om het model te evalueren, gebruikt u de pixelwaarde van deze afbeelding en kijkt u of de encoder dezelfde afbeelding kan reconstrueren na het verkleinen van 1024 pixels. Houd er rekening mee dat u een functie definieert om het model op verschillende afbeeldingen te evalueren. Het model zou alleen beter moeten werken bij paarden.
De functie heeft twee argumenten nodig:
- df: Importeer de testgegevens
- afbeelding_nummer: geef aan welke afbeelding u wilt importeren
De functie is verdeeld in drie delen:
- Geef de afbeelding een nieuwe vorm naar de juiste afmeting, bijvoorbeeld 1, 1024
- Voed het model met de onzichtbare afbeelding, codeer/decodeer de afbeelding
- Druk de echte en gereconstrueerde afbeelding af
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 de evaluatiefunctie is gedefinieerd, kunt u de gereconstrueerde afbeelding nummer dertien bekijken
reconstruct_image(df =test_x, image_number = 13)
INFO:tensorflow:Restoring parameters from ./model.ckpt Model restored. (1, 1024)
Samenvatting
- Het primaire doel van een autoencoder is om de invoergegevens te comprimeren en deze vervolgens te decomprimeren tot een uitvoer die sterk op de originele gegevens lijkt.
- De architectuur van een autoencoder is symmetrisch met een pivotlaag, de zogenaamde centrale laag.
- U kunt de autoencoder maken met behulp van:
Partieel: om de dichte lagen te creëren met de typische instelling:
tf.layers.dense, activation=tf.nn.elu, kernel_initializer=xav_init, kernel_regularizer=l2_regularizer
dichte_laag(): om de matrixvermenigvuldiging te maken
loss = tf.reduce_mean(tf.square(outputs - features)) optimizer = tf.train.AdamOptimizer(learning_rate) train = optimizer.minimize(loss)