Wat is een autoencoder?
Een Autoencoder is een hulpmiddel om efficiënt en zonder toezicht gegevenscodering te leren. Het is een soort kunstmatig neuraal netwerk dat u helpt de weergave van datasets te leren voor dimensionaliteitsvermindering door het neurale netwerk te trainen om de signaalruis te negeren. Het is een geweldig hulpmiddel om een invoer opnieuw te creëren.
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 niet gelabeld, wat betekent dat het netwerk zonder supervisie kan leren. Nauwkeuriger gezegd, de invoer wordt gecodeerd door het netwerk om alleen op de meest kritieke functie te focussen. Dit is een van de redenen waarom autoencoder populair is voor het verminderen van dimensionaliteit. Bovendien kunnen autoencoders worden gebruikt om generatieve leermodellen te produceren . Het neurale netwerk kan bijvoorbeeld worden getraind met een reeks gezichten en vervolgens nieuwe gezichten produceren.
In deze zelfstudie van TensorFlow Autoencoder leert u:
- Wat is een autoencoder?
- Hoe werkt Autoencoder?
- Gestapelde Autoencoder-voorbeeld
- Bouw een autoencoder met TensorFlow
- Voorverwerking van afbeeldingen
- Stel Dataset Estimator in
- Bouw het netwerk op
Hoe werkt Autoencoder?
Het doel van een autoencoder is om een benadering van de invoer te produceren door alleen op de essentiële functies te focussen. U kunt zich afvragen waarom u niet alleen leert hoe u de invoer moet 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 input, een interne representatie en een output (een benadering van de input). Het leren vindt plaats in de lagen die aan de interne representatie zijn bevestigd. In feite zijn er twee hoofdblokken van lagen die eruitzien als een traditioneel neuraal netwerk. Het kleine verschil is dat de laag met de uitvoer gelijk moet zijn aan de invoer. In de onderstaande afbeelding gaat de originele invoer naar het eerste blok dat de encoder wordt genoemd . Deze interne weergave comprimeert (verkleint) de grootte van de invoer. In het tweede blok vindt de reconstructie van de ingang plaats. Dit is de decoderingsfase.
Het model werkt de gewichten bij door de verliesfunctie te minimaliseren. Het model wordt bestraft als de reconstructie-output verschilt van de input.
Stel je concreet een plaatje voor met een afmeting van 50x50 (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 input. Het betekent dat het netwerk een manier moet vinden om 250 pixels te reconstrueren met alleen een vector van neuronen gelijk aan 100.
Gestapelde 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 om 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 een manier leren om zijn taak te volbrengen onder een reeks beperkingen, dat wil zeggen met een lagere dimensie.
Tegenwoordig worden Autoencoders in Deep Learning voornamelijk gebruikt om een afbeelding te verhelpen. Stel je een afbeelding voor met krassen; een mens kan de inhoud nog steeds herkennen. Het idee van het ruisonderdrukken van autoencoder is om ruis aan het beeld toe te voegen om het netwerk te dwingen het patroon achter de gegevens te leren.
De andere nuttige familie van Autoencoder Deep Learning is variationele autoencoder. Dit type netwerk kan nieuwe afbeeldingen genereren. Stel je voor dat je een netwerk traint met het beeld van een man; zo'n netwerk kan nieuwe gezichten opleveren.
Bouw een autoencoder met TensorFlow
In deze tutorial leer je hoe je een gestapelde autoencoder bouwt om een afbeelding te reconstrueren.
U gebruikt de CIFAR-10-dataset die 60000 32x32 kleurenafbeeldingen bevat. De Autoencoder-dataset is al verdeeld over 50000 afbeeldingen voor training en 10000 afbeeldingen voor testen. Er zijn maximaal tien klassen:
- Vliegtuig
- Auto
- Vogel
- Kat
- Herten
- Hond
- Kikker
- Paard
- Schip
- Vrachtwagen
U moet de afbeeldingen in deze URL https://www.cs.toronto.edu/~kriz/cifar.html downloaden en uitpakken. De map voor-10-batches-py bevat vijf batches met gegevens met elk 10.000 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 trainingsdataset
- Construeer een afbeeldingsvisualizer
Voorverwerking van afbeeldingen
Stap 1) Importeer de gegevens.
Volgens de officiële website kun je de gegevens uploaden met de volgende code. De Autoencoder-code laadt de gegevens in een woordenboek met de gegevens en het label . Merk op dat de code een functie is.
import numpy as npimport tensorflow as tfimport pickledef unpickle(file):import picklewith open(file, 'rb') as fo:dict = pickle.load(fo, encoding='latin1')return dict
Stap 2) Converteer de gegevens naar een zwart-witformaat
Voor het gemak converteert u de gegevens naar grijswaarden. Dat wil zeggen, met slechts één dimensie tegen drie voor kleurenbeeld. Het grootste deel van het neurale netwerk werkt alleen met invoer van éé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 gegevensset is geladen, kunt u een lus schrijven om de gegevens in het geheugen toe te voegen. Als u zorgvuldig controleert, krijgt het unzip-bestand met de gegevens de naam data_batch_ met een nummer van 1 tot 5. U kunt de bestanden doorlopen en aan de gegevens toevoegen.
Wanneer deze stap is voltooid, converteert u de kleurgegevens naar een grijsschaalindeling. Zoals u kunt zien, is de vorm van de gegevens 50000 en 1024. De 32 * 32 pixels zijn nu afgevlakt tot 2014.
# Load the data into memorydata, labels = [], []## Loop over the bfor 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. Voor een Windows-machine zou het pad bijvoorbeeld filename = 'E: \ cifar-10-batches-py \ data_batch_' + str (i) kunnen zijn
Stap 4) Construeer de trainingsdataset
Om de training sneller en gemakkelijker te maken, train je een model alleen op de paardenbeelden. 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 weergegeven in de onderstaande voorbeeldstap van TensorFlow Autoencoder.
horse_i = np.where(y == 7)[0]horse_x = x[horse_i]print(np.shape(horse_x))(5000, 1024)
Stap 5) Construeer een afbeeldingsvisualizer
Ten slotte construeer je een functie om de afbeeldingen te plotten. U hebt deze functie nodig om de gereconstrueerde afbeelding vanaf de autoencoder af te drukken.
Een gemakkelijke manier om afbeeldingen af te drukken, is door het object imshow uit de matplotlib-bibliotheek te gebruiken. Merk op 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 inlineimport matplotlibimport matplotlib.pyplot as pltdef 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:
- Afbeelding: de input
- Vorm: lijst, de afmeting van de afbeelding
- Cmap: kies de kleurenkaart. Standaard grijs
U kunt proberen de eerste afbeelding in de dataset te plotten. Je zou een man op een paard moeten zien.
plot_image(horse_x[1], shape=[32, 32], cmap = "Greys_r")
Stel Dataset Estimator in
Goed, nu de dataset klaar is voor gebruik, kunt u Tensorflow gaan gebruiken. Laten we, voordat we het model bouwen, de Dataset-schatter van Tensorflow gebruiken om het netwerk te voeden.
Je bouwt een Dataset met TensorFlow Estimator. Om je geest op te frissen, moet je het volgende gebruiken:
- from_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 None omdat het aantal afbeeldingsfeeds naar het netwerk gelijk is aan de batchgrootte.
Raadpleeg de tutorial over lineaire regressie voor meer informatie.
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 klaar 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 maar met één afbeelding wilt voeden. U kunt de dimensie van de gegevens zien met print (sess.run (features) .shape). Het is gelijk aan (1, 1024). 1 betekent dat er slechts één afbeelding met 1024 wordt ingevoerd. Als de batchgrootte is ingesteld op twee, gaan er twee afbeeldingen door de pijplijn. (Wijzig de batchgrootte niet. Anders zal er een fout optreden. Er kan slechts één afbeelding tegelijk naar de functie plot_image () gaan.
## Parametersn_inputs = 32 * 32BATCH_SIZE = 1batch_size = tf.placeholder(tf.int64)# using a placeholderx = tf.placeholder(tf.float32, shape=[None,n_inputs])## Datasetdataset = tf.data.Dataset.from_tensor_slices(x).repeat().batch(batch_size)iter = dataset.make_initializable_iterator() # create the iteratorfeatures = iter.get_next()## Print the imagewith tf.Session() as sess:# feed the placeholder with datasess.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 op
Het is tijd om het netwerk op te bouwen. Je traint een gestapelde autoencoder, dat wil zeggen een netwerk met meerdere verborgen lagen.
Uw netwerk heeft één invoerlaag met 1024 punten, dwz 32x32, de vorm van de afbeelding.
Het coderingsblok heeft een verborgen bovenste laag met 300 neuronen, een centrale laag met 150 neuronen. Het decoderblok is symmetrisch ten opzichte van de encoder. U kunt het netwerk in de onderstaande afbeelding visualiseren. Merk op dat u de waarden van verborgen en centrale lagen kunt wijzigen.
Het bouwen van een autoencoder lijkt sterk op elk ander model voor deep learning.
U bouwt het model door deze stappen te volgen:
- 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 maakt om het model te voeden, dus het is niet nodig om de dataset nog een keer te maken. Je bouwt een autoencoder met vier lagen. U gebruikt de Xavier-initialisatie. Dit is een techniek om de begingewichten gelijk te stellen aan de variantie van zowel de input als de output. Ten slotte gebruik je de elu-activeringsfunctie. U regulariseert de verliesfunctie met L2 regularizer.
Stap 1) Definieer de parameters
De eerste stap houdt in om het aantal neuronen in elke laag, de leersnelheid en de hyperparameter van de regularizer te definiëren.
Daarvoor importeer je 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 autoencoder-architectuur. 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 het leertempo en de L2-hyperparameter definiëren. De waarden worden opgeslagen in learning_rate en l2_reg
from functools import partial## Encodern_hidden_1 = 300n_hidden_2 = 150 # codings## Decodern_hidden_3 = n_hidden_1n_outputs = n_inputslearning_rate = 0.01l2_reg = 0.0001
De Xavier-initialisatietechniek wordt aangeroepen met het object xavier_initializer van de schatter contrib. In dezelfde schatter kunt u de regularizer toevoegen met l2_ regularizer
## Define the Xavier initializationxav_init = tf.contrib.layers.xavier_initializer()## Define the L2 regularizerl2_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 dense_layer inpakken door het object Partial. dense_layer die de ELU-activering, Xavier-initialisatie en L2-regularisatie gebruikt.
## Create the dense layerdense_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 de afbeelding van de architectuur kijkt, zie je dat het netwerk drie lagen stapelt met een uitvoerlaag. In de onderstaande code verbind je de juiste lagen. De eerste laag berekent bijvoorbeeld het puntproduct tussen de ingevoerde matrijskenmerken en de matrices die de 300 gewichten bevatten. Nadat het puntproduct is berekend, gaat de uitvoer naar de Elu-activeringsfunctie. De uitvoer wordt de invoer van de volgende laag, daarom gebruik je het om hidden_2 te berekenen enzovoort. De vermenigvuldiging van de matrices is voor elke laag hetzelfde omdat u dezelfde activeringsfunctie gebruikt. Merk op dat de laatste laag, outputs, geen activeringsfunctie toepast. Het is logisch omdat dit de gereconstrueerde invoer is
## Make the mat mulhidden_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. U gebruikt de Mean Square Error als een verliesfunctie. Als je je de tutorial over lineaire regressie herinnert, weet je dat de MSE wordt berekend met het verschil tussen de voorspelde output en het echte label. Hier is het label de functie omdat het model de invoer probeert te reconstrueren. Daarom wilt u het gemiddelde van de som van het verschil van het kwadraat tussen 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 verlopen te berekenen. De objectieve functie is om het verlies te minimaliseren.
## Optimizeloss = tf.reduce_mean(tf.square(outputs - features))optimizer = tf.train.AdamOptimizer(learning_rate)train = optimizer.minimize(loss)
Nog een instelling voordat je het model gaat trainen. U wilt een batchgrootte van 150 gebruiken, dat wil zeggen, de pijplijn voeden met elke iteratie 150 afbeeldingen. U moet het aantal iteraties handmatig berekenen. Dit is triviaal om te doen:
Als je elke keer 150 afbeeldingen wilt doorgeven en je weet dat er 5000 afbeeldingen in de dataset staan, dan is het aantal iteraties gelijk aan. In python kun je de volgende codes uitvoeren en ervoor zorgen dat de uitvoer 33 is:
BATCH_SIZE = 150### Number of batches : length dataset / batch sizen_batches = horse_x.shape[0] // BATCH_SIZEprint(n_batches)33
Stap 5) Voer het model uit
Train ten slotte het model. Je traint het model met 100 tijdperken. Dat wil zeggen, het model zal 100 keer de afbeeldingen zien met geoptimaliseerde gewichten.
U bent al bekend met de codes om een model in Tensorflow te trainen. Het kleine verschil is om de gegevens door te sluizen 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 (dwz het verlies neemt af). De training duurt 2 tot 5 minuten, afhankelijk van uw machinehardware.
## Set paramsn_epochs = 100## Call Saver to save the model and re-use it later during evaluationsaver = tf.train.Saver()with tf.Session() as sess:sess.run(tf.global_variables_initializer())# initialise iterator with train datasess.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 shownprint("\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.45510 Train MSE: 1672.67620 Train MSE: 1514.70930 Train MSE: 1404.311840 Train MSE: 1425.05850 Train MSE: 1479.063160 Train MSE: 1609.525970 Train MSE: 1482.322380 Train MSE: 1445.703590 Train MSE: 1453.8597Model saved in path: ./model.ckpt
Stap 6) Evalueer het model
Nu u uw model heeft getraind, is het tijd om het te evalueren. U moet de test sert 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'])
OPMERKING: voor een Windows-machine wordt de code test_data = unpickle (r "E: \ cifar-10-batches-py \ test_batch")
U kunt proberen de afbeeldingen 13 af te drukken, wat een paard is
plot_image(test_x[13], shape=[32, 32], cmap = "Greys_r")
Om het model te evalueren, gebruik je de pixelwaarde van deze afbeelding en kijk je of de encoder dezelfde afbeelding kan reconstrueren na 1024 pixels te hebben verkleind. Merk op dat u een functie definieert om het model op verschillende afbeeldingen te evalueren. Het model zou alleen bij paarden beter moeten werken.
De functie heeft twee argumenten:
- df: Importeer de testgegevens
- image_number: geef aan welke afbeelding moet worden geïmporteerd
De functie is onderverdeeld in drie delen:
- Vorm de afbeelding opnieuw naar de juiste afmeting, namelijk 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, 1024x_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 imagewith 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 imageoutputs_val = outputs.eval()print(outputs_val.shape)fig = plt.figure()# Plot realax1 = fig.add_subplot(121)plot_image(x_test_1, shape=[32, 32], cmap = "Greys_r")# Plot estimatedax2 = 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 het gereconstrueerde beeld nummer dertien bekijken
reconstruct_image(df =test_x, image_number = 13)
INFO:tensorflow:Restoring parameters from ./model.ckptModel restored.(1, 1024)
Overzicht
Het primaire doel van een autoencoder is om de invoergegevens te comprimeren en vervolgens te decomprimeren tot een uitvoer die sterk lijkt op de originele gegevens.
De architectuur van een autoencoder symmetrisch met een spillaag genaamd de centrale laag.
U kunt de autoencoder maken met:
- Gedeeltelijk: 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
- dense_layer (): om de matrixvermenigvuldiging te maken
u kunt de verliesfunctie en optimalisatie definiëren met:
loss = tf.reduce_mean(tf.square(outputs - features))optimizer = tf.train.AdamOptimizer(learning_rate)train = optimizer.minimize(loss)
Voer als laatste een sessie uit om het model te trainen.