Codificatore automatico in TensorFlow con esempio
Cos'è il codificatore automatico nel deep learning?
An Codificatore automatico è uno strumento per apprendere la codifica dei dati in modo efficiente e senza supervisione. È un tipo di rete neurale artificiale che aiuta ad apprendere la rappresentazione dei set di dati per la riduzione della dimensionalità addestrando la rete neurale a ignorare il rumore del segnale. È un ottimo strumento per ricreare un input.
In parole semplici, la macchina prende, diciamo un'immagine, e può produrre un'immagine strettamente correlata. L'input in questo tipo di rete neurale non è etichettato, il che significa che la rete è in grado di apprendere senza supervisione. Più precisamente, l'input viene codificato dalla rete per concentrarsi solo sulla caratteristica più critica. Questo è uno dei motivi per cui il codificatore automatico è popolare per la riduzione della dimensionalità. Inoltre, gli autoencoder possono essere utilizzati per produrre modelli di apprendimento generativo. Ad esempio, la rete neurale può essere addestrata con una serie di volti e quindi può produrre nuovi volti.
Come funziona il codificatore automatico TensorFlow?
Lo scopo di un autoencoder è produrre un'approssimazione dell'input concentrandosi solo sulle caratteristiche essenziali. Potresti pensare perché non semplicemente imparare a copiare e incollare l'input per produrre l'output. In effetti, un autocodificatore è un insieme di vincoli che costringono la rete ad apprendere nuovi modi per rappresentare i dati, diversi dalla semplice copia dell’output.
Un tipico autoencoder è definito con un input, una rappresentazione interna e un output (un'approssimazione dell'input). L'apprendimento avviene negli strati collegati alla rappresentazione interna. In effetti, ci sono due blocchi principali di strati che assomigliano a una rete neurale tradizionale. La leggera differenza è che il livello contenente l'output deve essere uguale all'input. Nell'immagine seguente, l'input originale va nel primo blocco chiamato the codificatore. Questa rappresentazione interna comprime (riduce) la dimensione dell'input. Nel secondo blocco avviene la ricostruzione dell'input. Questa è la fase di decodifica.
Il modello aggiornerà i pesi minimizzando la funzione di perdita. Il modello viene penalizzato se l'output della ricostruzione è diverso dall'input.
Concretamente, immagina un'immagine con una dimensione di 50×50 (cioè 250 pixel) e una rete neurale con un solo strato nascosto composto da cento neuroni. L'apprendimento avviene su una mappa delle caratteristiche che è due volte più piccola dell'input. Ciò significa che la rete deve trovare un modo per ricostruire 250 pixel con un solo vettore di neuroni pari a 100.
Esempio di codifica automatica in pila
In questo tutorial Autoencoder, imparerai come usare un autoencoder impilato. L'architettura è simile a una rete neurale tradizionale. L'input va a un livello nascosto per essere compresso, o ridurne le dimensioni, e poi raggiunge i livelli di ricostruzione. L'obiettivo è produrre un'immagine di output il più possibile simile all'originale. Il modello deve imparare un modo per raggiungere il suo compito sotto un insieme di vincoli, ovvero con una dimensione inferiore.
Al giorno d'oggi, gli autoencoder in Deep Learning vengono utilizzati principalmente per eliminare il rumore da un'immagine. Immagina un'immagine con graffi; un essere umano è ancora in grado di riconoscere il contenuto. L'idea di eliminare il rumore dal codificatore automatico è quella di aggiungere rumore all'immagine per forzare la rete ad apprendere lo schema dietro i dati.
L'altra famiglia utile di Autoencoder Deep Learning è l'autoencoder variazionale. Questo tipo di rete può generare nuove immagini. Immagina di formare una rete con l'immagine di un uomo; una tale rete può produrre nuovi volti.
Come costruire un codificatore automatico con TensorFlow
In questo tutorial imparerai come costruire un codificatore automatico in pila per ricostruire un'immagine.
Userai il Set di dati CIFAR-10 che contiene 60000 immagini a colori 32×32. Il set di dati dell'Autoencoder è già suddiviso tra 50000 immagini per l'addestramento e 10000 per il test. Ci sono fino a dieci classi:
- Aereo
- automobile
- Uccello
- Gatto
- Cervo
- Cane
- Rana
- cavallo
- Nave
- Camion
Devi scaricare le immagini in questo URL https://www.cs.toronto.edu/~kriz/cifar.html e decomprimerlo. La cartella for-10-batches-py contiene cinque batch di dati con 10000 immagini ciascuno in ordine casuale.
Prima di creare e addestrare il modello, è necessario applicare alcune elaborazioni dei dati. Procederai come segue:
- Importa i dati
- Converti i dati in formato bianco e nero
- Aggiungi tutti i batch
- Costruire il set di dati di addestramento
- Costruisci un visualizzatore di immagini
Pre-elaborazione delle immagini
Passaggio 1) Importa i dati
Secondo il sito web ufficiale, puoi caricare i dati con il seguente codice. Il codice Autoencoder caricherà i dati in un dizionario con il dati e le etichetta. Tieni presente che il codice è una funzione.
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
Passaggio 2) Converti i dati in formato bianco e nero
Per semplicità, convertirai i dati in scala di grigi. Cioè con una sola dimensione contro tre per l'immagine a colori. La maggior parte della rete neurale funziona solo con input di una sola dimensione.
def grayscale(im): return im.reshape(im.shape[0], 3, 32, 32).mean(1).reshape(im.shape[0], -1)
Passaggio 3) Aggiungi tutti i batch
Ora che entrambe le funzioni sono state create e il set di dati è stato caricato, è possibile scrivere un ciclo per aggiungere i dati in memoria. Se controlli attentamente, il file decompresso con i dati si chiama data_batch_ con un numero da 1 a 5. Puoi eseguire il loop sui file e aggiungerlo ai dati.
Al termine di questo passaggio, i dati dei colori vengono convertiti in un formato in scala di grigi. Come puoi vedere, la forma dei dati è 50000 e 1024. I pixel 32*32 sono ora appiattiti a 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)
Nota: modifica './cifar-10-batches-py/data_batch_' nella posizione effettiva del file. Ad esempio per Windows macchina, il percorso potrebbe essere filename = 'E:\cifar-10-batches-py\data_batch_' + str(i)
Passaggio 4) Costruire il set di dati di addestramento
Per rendere l'addestramento più semplice e veloce, addestrerai un modello solo sulle immagini del cavallo. I cavalli sono la settima classe nei dati dell'etichetta. Come menzionato nella documentazione del dataset CIFAR-10, ogni classe contiene 5000 immagini. È possibile stampare la forma dei dati per confermare che ci sono 5.000 immagini con 1024 colonne come mostrato di seguito TensorFlow Passaggio di esempio del codificatore automatico.
horse_i = np.where(y == 7)[0] horse_x = x[horse_i] print(np.shape(horse_x)) (5000, 1024)
Passaggio 5) Costruisci un visualizzatore di immagini
Infine, costruisci una funzione per tracciare le immagini. Avrai bisogno di questa funzione per stampare l'immagine ricostruita dall'autoencoder.
Un modo semplice per stampare immagini è utilizzare l'oggetto imshow dalla libreria matplotlib. Tieni presente che devi convertire la forma dei dati da 1024 a 32*32 (ovvero il formato di un'immagine).
# 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")
La funzione accetta 3 argomenti:
- Immagine: l'ingresso
- Forma: elenco, la dimensione dell'immagine
- cmap:scegli la mappa dei colori. Per impostazione predefinita, grigio
Puoi provare a tracciare la prima immagine nel set di dati. Dovresti vedere un uomo a cavallo.
plot_image(horse_x[1], shape=[32, 32], cmap = "Greys_r")
Imposta la stima del set di dati
Va bene, ora che il set di dati è pronto per l'uso, puoi iniziare a utilizzare Tensorflow. Prima di costruire il modello, utilizziamo lo stimatore Dataset di Tensorflow per alimentare la rete.
Costruirai un set di dati con lo stimatore TensorFlow. Per rinfrescare la tua mente, devi usare:
- from_tensor_slices
- ripetere
- partita
Il codice completo per creare il set di dati è:
dataset = tf.data.Dataset.from_tensor_slices(x).repeat().batch(batch_size)
Nota che x è un segnaposto con la seguente forma:
- [Nessuno,n_inputs]: impostare su Nessuno perché il numero di immagini inviate alla rete è uguale alla dimensione del batch.
per i dettagli, fare riferimento al tutorial su regressione lineare.
Successivamente, è necessario creare l'iteratore. Senza questa riga di codice, nessun dato passerà attraverso la pipeline.
iter = dataset.make_initializable_iterator() # create the iteratorfeatures = iter.get_next()
Ora che la pipeline è pronta, puoi verificare se la prima immagine è la stessa di prima (cioè un uomo a cavallo).
Imposti la dimensione del batch su 1 perché vuoi alimentare il dataset con una sola immagine. Puoi vedere la dimensione dei dati con print(sess.run(features).shape). È uguale a (1, 1024). 1 significa che viene alimentata una sola immagine con 1024 ciascuno. Se la dimensione del batch è impostata su due, allora due immagini passeranno attraverso la pipeline. (Non modificare la dimensione del batch. Altrimenti, verrà generato un errore. Solo un'immagine alla volta può andare alla funzione 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)
Costruisci la rete
È tempo di costruire la rete. Addestrerai un codificatore automatico impilato, ovvero una rete con più livelli nascosti.
La tua rete avrà un livello di input con 1024 punti, ovvero 32×32, la forma dell'immagine.
Il blocco codificatore avrà uno strato nascosto superiore con 300 neuroni, uno strato centrale con 150 neuroni. Il blocco del decodificatore è simmetrico rispetto all'encoder. Puoi visualizzare la rete nell'immagine qui sotto. Tieni presente che puoi modificare i valori dei livelli nascosti e centrali.
Costruire un codificatore automatico è molto simile a qualsiasi altro modello di deep learning.
Costruirai il modello seguendo questi passaggi:
- Definire i parametri
- Definire gli strati
- Definire l'architettura
- Definire l'ottimizzazione
- Esegui il modello
- Valuta il modello
Nella sezione precedente, hai imparato come creare una pipeline per alimentare il modello, quindi non è necessario creare nuovamente il set di dati. Costruirai un codificatore automatico con quattro livelli. Si utilizza l'inizializzazione Xavier. Questa è una tecnica per impostare i pesi iniziali uguali alla varianza sia dell'input che dell'output. Infine, si utilizza la funzione di attivazione elu. Si regolarizza la funzione di perdita con il regolarizzatore L2.
Passo 1) Definire i parametri
Il primo passo implica definire il numero di neuroni in ogni strato, la velocità di apprendimento e l'iperparametro del regolarizzatore.
Prima di ciò, importi parzialmente la funzione. È un metodo migliore per definire i parametri degli strati densi. Il codice seguente definisce i valori dell'architettura dell'autoencoder. Come elencato in precedenza, l'autoencoder ha due strati, con 300 neuroni nei primi strati e 150 nei secondi strati. I loro valori sono memorizzati in n_hidden_1 e n_hidden_2.
È necessario definire la velocità di apprendimento e l'iperparametro L2. I valori sono memorizzati in learning_rate e 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
La tecnica di inizializzazione di Xavier viene richiamata con l'oggetto xavier_initializer dall'estimator contrib. Nello stesso stimatore è possibile aggiungere il regolarizzatore con 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)
Passo 2) Definire gli strati
Sono stati impostati tutti i parametri degli strati densi; puoi comprimere tutto nella variabile dense_layer utilizzando l'oggetto partial. dense_layer che utilizza l'attivazione ELU, l'inizializzazione Xavier e la regolarizzazione L2.
## Create the dense layer dense_layer = partial(tf.layers.dense, activation=tf.nn.elu, kernel_initializer=xav_init, kernel_regularizer=l2_regularizer)
Passo 3) Definire l'architettura
Se guardi l'immagine dell'architettura, noti che la rete impila tre livelli con un livello di output. Nel codice sottostante, colleghi i livelli appropriati. Ad esempio, il primo livello calcola il prodotto scalare tra le caratteristiche della matrice di input e le matrici contenenti i 300 pesi. Dopo che il prodotto scalare è stato calcolato, l'output va alla funzione di attivazione Elu. L'output diventa l'input del livello successivo, ecco perché lo usi per calcolare hidden_2 e così via. La moltiplicazione delle matrici è la stessa per ogni livello perché usi la stessa funzione di attivazione. Nota che l'ultimo livello, output, non applica una funzione di attivazione. Ha senso perché questo è l'input ricostruito
## 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)
Passo 4) Definire l'ottimizzazione
L'ultimo passo è costruire l'ottimizzatore. Si utilizza l'errore quadratico medio come funzione di perdita. Se ricordi il tutorial sulla regressione lineare, sai che l'MSE viene calcolato con la differenza tra l'output previsto e l'etichetta reale. In questo caso l'etichetta è la caratteristica perché il modello tenta di ricostruire l'input. Pertanto, si desidera la media della somma della differenza del quadrato tra l'output e l'input previsti. Con TensorFlow, puoi codificare la funzione di perdita come segue:
loss = tf.reduce_mean(tf.square(outputs - features))
Quindi, è necessario ottimizzare la funzione di perdita. Utilizzi Adam Optimizer per calcolare i gradienti. La funzione obiettivo è minimizzare la perdita.
## Optimize loss = tf.reduce_mean(tf.square(outputs - features)) optimizer = tf.train.AdamOptimizer(learning_rate) train = optimizer.minimize(loss)
Un'altra impostazione prima di addestrare il modello. Si desidera utilizzare una dimensione batch pari a 150, ovvero alimentare la pipeline con 150 immagini per ogni iterazione. È necessario calcolare manualmente il numero di iterazioni. Questo è banale da fare:
Se vuoi passare 150 immagini ogni volta e sai che ci sono 5000 immagini nel dataset, il numero di iterazioni è uguale a . In python puoi eseguire i seguenti codici e assicurarti che l'output sia 33:
BATCH_SIZE = 150 ### Number of batches : length dataset / batch size n_batches = horse_x.shape[0] // BATCH_SIZE print(n_batches) 33
Passo 5) Esegui il modello
Ultimo ma non meno importante, addestra il modello. Stai addestrando il modello con 100 epoche. Cioè, il modello vedrà 100 volte le immagini con pesi ottimizzati.
Hai già familiarità con i codici per addestrare un modello in Tensorflow. La leggera differenza consiste nel convogliare i dati prima di eseguire la formazione. In questo modo il modello si allena più velocemente.
Ti interessa stampare la perdita dopo dieci epoche per vedere se il modello sta imparando qualcosa (ad esempio, la perdita sta diminuendo). La formazione dura da 2 a 5 minuti, a seconda dell'hardware della macchina.
## 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
Passo 6) Valuta il modello
Ora che hai addestrato il tuo modello, è il momento di valutarlo. È necessario importare il set di test dal file /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'])
NOTA: Per un Windows macchina, il codice diventa test_data = unpickle(r”E:\cifar-10-batches-py\test_batch”)
Puoi provare a stampare le immagini 13, che è un cavallo
plot_image(test_x[13], shape=[32, 32], cmap = "Greys_r")
Per valutare il modello, utilizzerai il valore dei pixel di questa immagine e vedrai se il codificatore può ricostruire la stessa immagine dopo aver ridotto 1024 pixel. Tieni presente che definisci una funzione per valutare il modello su immagini diverse. Il modello dovrebbe funzionare meglio solo sui cavalli.
La funzione accetta due argomenti:
- df: importa i dati del test
- numero_immagine: indicare quale immagine importare
La funzione è divisa in tre parti:
- Rimodellare l'immagine alla dimensione corretta, ovvero 1, 1024
- Alimenta il modello con l'immagine invisibile, codifica/decodifica l'immagine
- Stampa l'immagine reale e ricostruita
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()
Ora che la funzione di valutazione è definita, potete dare un'occhiata all'immagine ricostruita numero tredici
reconstruct_image(df =test_x, image_number = 13)
INFO:tensorflow:Restoring parameters from ./model.ckpt Model restored. (1, 1024)
Sintesi
- Lo scopo principale di un codificatore automatico è comprimere i dati di input e quindi decomprimerli in un output che assomigli molto ai dati originali.
- L'architettura di un autoencoder è simmetrica con uno strato pivot denominato strato centrale.
- È possibile creare il codificatore automatico utilizzando:
Parziale: per creare gli strati densi con l'impostazione tipica:
tf.layers.dense, activation=tf.nn.elu, kernel_initializer=xav_init, kernel_regularizer=l2_regularizer
strato_denso(): per effettuare la moltiplicazione di matrici
loss = tf.reduce_mean(tf.square(outputs - features)) optimizer = tf.train.AdamOptimizer(learning_rate) train = optimizer.minimize(loss)