Autoencoder in TensorFlow met voorbeeld
⚡ Slimme samenvatting
Autoencoders comprimeren een invoer tot een kleinere interne representatie en herbouwen deze vervolgens, waarbij ze de belangrijkste kenmerken leren zonder labels. Deze handleiding stapelt vier dense lagen in TensorFlow en reconstrueert CIFAR-10 paardenafbeeldingen.

Wat is Autoencoder in Deep Learning?
An Auto-encoder is een hulpmiddel om efficiënt datacodering te leren in een ongecontroleerd manier. Het is een soort kunstmatig neuraal netwerk Dit helpt je om de representatie van datasets voor dimensionaliteitsreductie te leren door het neurale netwerk te trainen om signaalruis te negeren. Het is een geweldig hulpmiddel om een invoer te reconstrueren.
Simpel gezegd, de machine neemt bijvoorbeeld een afbeelding en kan er een sterk verwante afbeelding mee produceren. De input in dit type neuraal netwerk is ongelabeld, wat betekent dat het netwerk in staat is om te leren zonder supervisie. Nauwkeuriger gezegd, de input wordt door het netwerk gecodeerd om zich alleen te richten op de meest cruciale kenmerken. Dit is een van de redenen waarom autoencoders populair zijn voor dimensionaliteitsreductie. Bovendien kunnen autoencoders worden gebruikt om generatieve leermodellen te creëren. Zo kan het neurale netwerk bijvoorbeeld worden getraind met een set gezichten en vervolgens nieuwe gezichten genereren.
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 leerproces vindt plaats in de lagen die aan de interne representatie zijn gekoppeld. In feite zijn er twee hoofdblokken van lagen die lijken op een traditioneel neuraal netwerk. Het kleine verschil is dat de laag die de uitvoer bevat gelijk moet zijn aan de invoer. In het onderstaande diagram gaat de oorspronkelijke invoer naar het eerste blok, de zogenaamde encoder. Deze interne representatie comprimeert (verkleint) de grootte van de invoer. In het tweede blok vindt de reconstructie van de invoer plaats. Dit is de decoderingsfase.

Het model zal de gewichten bijwerken door de verliesfunctie te minimaliseren. Het model wordt bestraft als de reconstructie-output verschilt van de input.
Concreet, stel je een afbeelding voor van 50×50 (oftewel 2,500 pixels) en een neuraal netwerk met slechts één verborgen laag bestaande uit honderd neuronen. Het leerproces vindt plaats op een feature map die vijfentwintig keer kleiner is dan de invoer. Dit betekent dat het netwerk een manier moet vinden om 2,500 pixels te reconstrueren met slechts een vector van neuronen gelijk aan 100.
Gestapeld Autoencoder-voorbeeld
In deze tutorial over autoencoders leer je hoe je een stacked autoencoder gebruikt. De architectuur is vergelijkbaar met die van een traditioneel neuraal netwerk. De invoer gaat naar een verborgen laag om te worden gecomprimeerd, oftewel de grootte ervan te verkleinen, en bereikt vervolgens de reconstructielagen. Het doel is om een uitvoerbeeld te produceren dat zo dicht mogelijk bij het origineel ligt. Het model moet leren hoe het zijn taak kan volbrengen onder bepaalde beperkingen, oftewel met een lagere dimensie.
Tegenwoordig worden autoencoders in deep learning vooral gebruikt om ruis uit afbeeldingen te verwijderen. Stel je een afbeelding voor met krassen; een mens kan de inhoud nog steeds herkennen. Het idee achter een ruisverwijderende autoencoder is om ruis aan de afbeelding toe te voegen, zodat het netwerk gedwongen wordt het patroon achter de data te leren.
De andere nuttige familie van autoencoders Diepe leren Dit is een variationele auto-encoder. Dit type netwerk kan nieuwe afbeeldingen genereren. Stel je voor dat je een netwerk traint met de afbeelding van een man; zo'n netwerk kan nieuwe gezichten produceren.
De onderstaande tabel plaatst de gestapelde autoencoder die in deze handleiding is gebouwd naast de andere families die u waarschijnlijk zult tegenkomen, zodat de beperking die elk ervan toevoegt gemakkelijk te vergelijken is.
| Autoencoder-type | Beperking toegevoegd | Typisch gebruik |
|---|---|---|
| Onvolledig / gestapeld | Codeerlaag smaller dan de invoer | Dimensionale reductie, kenmerkextractie |
| Ruisonderdrukking | Ruis toegevoegd aan de ingang, schoon doel | Beeld- en signaalopschoning |
| Schaars | Straf op het aantal actieve eenheden | Interpreteerbare, op onderdelen gebaseerde kenmerken |
| variatie | De codeerlaag leert een kansverdeling. | Nieuwe samples genereren |
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-dataset, die 60000 kleurenfoto's van 32×32 pixels bevat. De Autoencoder-dataset is al opgesplitst in 50000 afbeeldingen voor training en 10000 voor testen. Er zijn maximaal tien klassen.
- Vliegtuig
- Automobile
- Vogel
- Kat
- Hert
- Hond
- Kikker
- Paard
- Verzenden
- Vrachtwagen
Je moet de afbeeldingen downloaden van de CIFAR-10 datasetpagina Pak het archief uit. De map cifar-10-batches-py bevat vijf batches met elk 10000 afbeeldingen in een 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
Versie-opmerking: De code in deze handleiding is gericht op TensorFlow 1.x. In TensorFlow 2 bestaat de module tf.contrib niet meer en zijn placeholders, sessies en de initialiseerbare iterator ondergebracht in tf.compat.v1. Het aanroepen van tf.compat.v1.disable_v2_behavior() na de import is de snelste manier om de code ongewijzigd uit te voeren.
Voorbewerking van afbeeldingen
Stap 1) Importeer de gegevens
Volgens de officiële website kun je de data uploaden met de volgende code. De Autoencoder-code laadt de data in een dictionary met de data en het label. Let op: de code is een functie.
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 aangemaakt en de dataset is geladen, kunt u een lus schrijven om de gegevens in het geheugen toe te voegen. Als u goed kijkt, ziet u dat het uitgepakte bestand met de gegevens de naam data_batch_ heeft, gevolgd door een nummer van 1 tot en met 5. U kunt door de bestanden heen lopen en de gegevens aan de dataset toevoegen.
Na deze stap worden de kleurgegevens omgezet naar grijswaarden. Zoals je ziet, hebben de gegevens de afmetingen 50000 bij 1024. De 32 x 32 pixels zijn nu afgevlakt tot 1024.
# 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)
Let op: Vervang './cifar-10-batches-py/data_batch_' door de daadwerkelijke locatie van uw bestand. Bijvoorbeeld voor een 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 hebben label 7 in de labelgegevens. Zoals vermeld in de documentatie van de CIFAR-10-dataset, bevat elke klasse 5000 afbeeldingen. Je kunt de structuur van de gegevens afdrukken om te bevestigen dat er 5,000 afbeeldingen zijn met 1024 kolommen, zoals weergegeven in de onderstaande TensorFlow Autoencoder-voorbeeldstap.
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 eenvoudige manier om afbeeldingen af te drukken is door de functie `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 (oftewel 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:
- Afbeelding: de invoer
- Vorm: lijst, de afmetingen van de afbeelding
- Cmap: kies de kleurenkaart. Standaard is dit 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")
De functie retourneert de onderstaande miniatuur in grijstinten en bevestigt dat de omvorming van 1024 waarden terug naar een afbeelding van 32×32 correct is.
Gegevenssetschatter instellen
Oké, nu de dataset klaar is voor gebruik, kun je TensorFlow gaan gebruiken. Voordat je het model bouwt, gebruik je de Dataset-estimator 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 placeholder is met de vorm [None,n_inputs]. De eerste dimensie is ingesteld op None omdat het aantal afbeeldingen dat aan het netwerk wordt aangeboden gelijk is aan de batchgrootte, die pas tijdens de uitvoering wordt bepaald. Raadpleeg de handleiding voor meer informatie. Lineaire regressie met TensorFlow.
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).
Je hebt de batchgrootte ingesteld op 1 omdat je de dataset slechts met één afbeelding wilt voeden. Je kunt de dimensie van de data zien met print(sess.run(features).shape). Deze is gelijk aan (1, 1024). De 1 betekent dat er elke keer één afbeelding met 1024 waarden wordt aangeleverd. Als de batchgrootte is ingesteld op twee, worden er twee afbeeldingen tegelijk verwerkt. Wijzig de batchgrootte niet, anders krijg je een foutmelding, omdat er slechts één afbeelding tegelijk naar de functie plot_image() kan worden gestuurd.
## 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)
De pipeline retourneert dezelfde rider die rechtstreeks uit de NumPy-matrix is geplot, wat bewijst dat de placeholder, de iterator en de batchgrootte correct zijn gekoppeld.
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.
Je netwerk zal één invoerlaag hebben met 1024 punten, oftewel 32×32, de vorm van de afbeelding.
Het encoderblok heeft een bovenste verborgen laag met 300 neuronen en een centrale laag met 150 neuronen. Het decoderblok is symmetrisch ten opzichte van de encoder. Je kunt het netwerk visualiseren in het onderstaande diagram. Merk op dat je de waarden van de verborgen en centrale lagen kunt aanpassen.
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 het vorige gedeelte heb je geleerd hoe je een pipeline maakt om het model te voeden, dus het is niet nodig om de dataset opnieuw te creëren. Je gaat een autoencoder met vier lagen bouwen. Je gebruikt de Xavier-initialisatie. Dit is een techniek om de initiële gewichten in te stellen op basis van de variantie van zowel de invoer als de uitvoer. Ten slotte gebruik je de ELU-activeringsfunctie. Je regulariseert de verliesfunctie met een L2-regularisator.
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.
Voordat je dat doet, importeer je de partiële functie. Dit is een betere methode om de parameters van de dense lagen te definiëren. De onderstaande code definieert de waarden van de autoencoder-architectuur. Zoals eerder vermeld, heeft de encoder twee lagen, met 300 neuronen in de eerste laag en 150 in de tweede laag. Hun waarden worden opgeslagen in n_hidden_1 en n_hidden_2.
Je moet de leerfrequentie 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 `estimator contrib`. In dezelfde estimator kunt u de regularisatiefunctie 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)
Versie-opmerking: tf.contrib is verwijderd in TensorFlow 2. De directe vervangingen zijn tf.keras.initializers.GlorotUniform() voor xavier_initializer() en tf.keras.regularizers.l2() voor l2_regularizer().
Stap 2) Definieer de lagen
Alle parameters van de dense layers zijn ingesteld; je kunt alles in de variabele `dense_layer` verpakken met behulp van het object `partial`. `dense_layer` gebruikt vervolgens bij elke aanroep de ELU-activeringsfunctie, de Xavier-initialisatie en de 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 je naar het architectuurdiagram kijkt, zie je dat het netwerk uit drie lagen bestaat met een uitvoerlaag. In de onderstaande code verbind je de juiste lagen. De eerste laag berekent bijvoorbeeld het dotproduct tussen de invoermatrix met kenmerken en de matrix met de 300 gewichten. Nadat het dotproduct is berekend, gaat de uitvoer naar de ELU-activeringsfunctie. De uitvoer wordt de invoer voor de volgende laag, daarom gebruik je deze om hidden_2 te berekenen, enzovoort. De matrixvermenigvuldiging is voor elke laag hetzelfde, omdat je dezelfde activeringsfunctie gebruikt. Merk op dat de laatste laag, outputs, geen activeringsfunctie toepast. Dat is logisch, want dit is de gereconstrueerde invoer.
## 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 construeren van de optimizer. Je gebruikt de Mean Square Error (MSE) als verliesfunctie. Als je de tutorial over lineaire regressie nog herinnert, weet je dat de MSE wordt berekend als het verschil tussen de voorspelde uitvoer en het werkelijke label. Hier is het label de feature, omdat het model de invoer probeert te reconstrueren. Je wilt dus het gemiddelde van de som van de kwadraten van de verschillen tussen de voorspelde uitvoer en de invoer. Met TensorFlow kun je de verliesfunctie als volgt coderen:
loss = tf.reduce_mean(tf.square(outputs - features))
Vervolgens moet je de verliesfunctie optimaliseren. Je gebruikt de Adam-optimizer om de gradiënten te berekenen. De doelfunctie 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 je elke keer 150 afbeeldingen wilt verwerken en je weet dat de dataset 5000 afbeeldingen bevat, dan is het aantal iteraties gelijk aan 5000 gedeeld door 150. Python Je kunt de volgende code uitvoeren en controleren of 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
Tot slot train je het model. Je traint het model met 100 epochs. Dat wil zeggen dat het model de afbeeldingen 100 keer te zien krijgt tijdens het optimaliseren van de gewichten.
Je bent al bekend met de code voor het trainen van een model in TensorFlow. Het kleine verschil is dat je de data doorstuurt voordat je de training uitvoert. 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 je model getraind is, is het tijd om het te evalueren. Je moet de testset importeren vanuit 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'])
Let op: Voor een Windows machine, de code wordt test_data = unpickle(r”E:\cifar-10-batches-py\test_batch”)
Je kunt proberen afbeelding 13 af te drukken, dat is een paard.
plot_image(test_x[13], shape=[32, 32], cmap = "Greys_r")
De grafiek bevestigt dat de testbatch correct is geladen en dat afbeelding 13 tot de klasse behoort waarop het model is getraind.
Om het model te evalueren, gebruikt u de pixelwaarde van deze afbeelding en controleert u of de encoder dezelfde afbeelding kan reconstrueren nadat deze is verkleind tot 1024 pixels. Merk op dat u een functie definieert om het model te evalueren op verschillende afbeeldingen. Het model zou alleen beter moeten werken op paarden.
De functie heeft twee argumenten nodig:
- df: Importeer de testgegevens
- image_number: geeft aan welke afbeelding moet worden geïmporteerd
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)
De afbeelding toont de originele testafbeelding aan de linkerkant en de uitvoer van de autoencoder aan de rechterkant, waardoor het verlies aan fijne details na de compressie van 1024 naar 150 gemakkelijk te beoordelen is.




