Codificatore automatico in TensorFlow con esempio
⚡ Riepilogo intelligente
Gli autoencoder comprimono un input in una rappresentazione interna più piccola e poi la ricostruiscono, apprendendo le caratteristiche più importanti senza etichette. Questa procedura illustra come sovrapporre quattro layer densi in TensorFlow e ricostruire immagini di cavalli dal dataset CIFAR-10.

Cos'è il codificatore automatico nel deep learning?
An Codificatore automatico è uno strumento per imparare la codifica dei dati in modo efficiente in un senza sorveglianza modo. È un tipo di rete neurale artificiale che ti 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, ad esempio, un'immagine ed è in grado di produrre un'immagine molto simile. 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 sulle caratteristiche più importanti. Questo è uno dei motivi per cui gli autoencoder sono popolari 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 un insieme di volti e quindi essere in grado di 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 autoencoder tipico è definito da 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 lo strato contenente l'output deve essere uguale all'input. Nel diagramma sottostante, l'input originale entra nel primo blocco chiamato encoder. 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.
In concreto, immaginiamo un'immagine di dimensioni 50×50 (ovvero 2,500 pixel) e una rete neurale con un solo strato nascosto composto da cento neuroni. L'apprendimento avviene su una mappa di caratteristiche che è venticinque volte più piccola dell'input. Ciò significa che la rete deve trovare un modo per ricostruire 2,500 pixel con un vettore di soli 100 neuroni.
Esempio di codifica automatica in pila
In questo tutorial sugli autoencoder, imparerai come utilizzare un autoencoder a strati. L'architettura è simile a quella di una rete neurale tradizionale. L'input passa attraverso uno strato nascosto per essere compresso, ovvero per ridurne le dimensioni, e poi raggiunge gli strati di ricostruzione. L'obiettivo è produrre un'immagine di output il più simile possibile all'originale. Il modello deve apprendere un modo per svolgere il suo compito rispettando una serie di vincoli, ovvero con una dimensionalità inferiore.
Oggi, gli autoencoder nel Deep Learning vengono utilizzati principalmente per ridurre il rumore nelle immagini. Immaginate un'immagine graffiata: un essere umano è comunque in grado di riconoscerne il contenuto. L'idea alla base degli autoencoder per la riduzione del rumore è quella di aggiungere rumore all'immagine per costringere la rete a imparare lo schema sottostante ai dati.
L'altra utile famiglia di Autoencoder Deep Learning Si tratta di un autoencoder variazionale. Questo tipo di rete può generare nuove immagini. Immagina di addestrare una rete con l'immagine di un uomo; una rete di questo tipo può produrre nuovi volti.
La tabella seguente mette a confronto l'autoencoder a strati costruito in questo tutorial con le altre famiglie che probabilmente incontrerete, in modo che il vincolo aggiunto da ciascuno di essi sia facile da confrontare.
| Tipo di autoencoder | Vincolo aggiunto | Utilizzo tipico |
|---|---|---|
| Incompleto / impilato | Strato di codifica più stretto dell'input | Riduzione della dimensionalità, feature extracproduzione |
| denoising | Rumore aggiunto all'input, target pulito | Pulizia di immagini e segnali |
| scarso | Penalità sul numero di unità attive | Caratteristiche interpretabili basate su parti |
| Variazionale | Il livello di codifica apprende una distribuzione di probabilità | Generazione di nuovi campioni |
Come costruire un codificatore automatico con TensorFlow
In questo tutorial imparerai come costruire un codificatore automatico in pila per ricostruire un'immagine.
Utilizzerai il dataset CIFAR-10, che contiene 60000 immagini a colori di dimensioni 32×32 pixel. Il dataset dell'autoencoder è già suddiviso in 50000 immagini per l'addestramento e 10000 per il test. Sono presenti fino a dieci classi:
- Aereo
- automobile
- Uccello
- Gatto
- Cervo
- Cane
- Rana
- cavallo
- Nave
- Camion
È necessario scaricare le immagini da Pagina del dataset CIFAR-10 e decomprimi l'archivio. La cartella cifar-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
Nota sulla versione: Il codice di questo tutorial è pensato per TensorFlow 1.x. In TensorFlow 2 il modulo tf.contrib non esiste più e i placeholder, le sessioni e l'iteratore inizializzabile si trovano in tf.compat.v1. Chiamare tf.compat.v1.disable_v2_behavior() dopo l'importazione è il modo più rapido per eseguire gli elenchi senza modifiche.
Pre-elaborazione delle immagini
Passaggio 1) Importa i dati
Secondo il sito web ufficiale, è possibile caricare i dati con il seguente codice. Il codice dell'Autoencoder caricherà i dati in un dizionario contenente i dati e l'etichetta. Si noti 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 dataset caricato, puoi scrivere un ciclo per aggiungere i dati in memoria. Se controlli attentamente, il file decompresso contenente i dati si chiama data_batch_ seguito da un numero da 1 a 5. Puoi quindi iterare sui file e aggiungere i dati al dataset.
Una volta completato questo passaggio, i dati relativi al colore vengono convertiti in un formato in scala di grigi. Come si può notare, la forma dei dati è 50000 e 1024. I 32*32 pixel vengono ora appiattiti a 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)
Nota: Cambia './cifar-10-batches-py/data_batch_' con la posizione effettiva del tuo file. Ad esempio per un 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ù rapido e semplice, addestrerai un modello solo sulle immagini dei cavalli. I cavalli hanno l'etichetta 7 nei dati di etichetta. Come indicato nella documentazione del dataset CIFAR-10, ogni classe contiene 5000 immagini. Puoi stampare la struttura dei dati per confermare che ci sono 5,000 immagini con 1024 colonne, come mostrato nell'esempio di TensorFlow Autoencoder riportato di seguito.
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 la funzione imshow() della libreria Matplotlib. Tieni presente che è necessario convertire la dimensione 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'input
- Forma: elenco, la dimensione dell'immagine
- Cmap: scegli la mappa dei colori. Di default, 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")
La chiamata restituisce l'anteprima in scala di grigi qui sotto e conferma che il ridimensionamento da 1024 valori a un'immagine 32×32 è corretto.
Imposta la stima del set di dati
Bene, ora che il dataset è pronto per l'uso, puoi iniziare a utilizzare TensorFlow. Prima di costruire il modello, usa il Dataset Estimator 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 della forma [None, n_inputs]. La prima dimensione è impostata su None perché il numero di immagini fornite alla rete è uguale alla dimensione del batch, che viene decisa solo in fase di esecuzione. Per i dettagli, fare riferimento al tutorial su regressione lineare con TensorFlow.
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).
Hai impostato la dimensione del batch a 1 perché vuoi alimentare il dataset con una sola immagine. Puoi visualizzare la dimensione dei dati con print(sess.run(features).shape). È uguale a (1, 1024). L'1 significa che viene alimentata una singola immagine con 1024 valori ogni volta. Se la dimensione del batch è impostata a due, due immagini passeranno attraverso la pipeline. Non modificare la dimensione del batch, altrimenti verrà generato un errore, perché solo un'immagine alla volta può essere inviata 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)
La pipeline restituisce lo stesso rider che è stato tracciato direttamente dalla matrice NumPy, il che dimostra che il placeholder, l'iteratore e la dimensione del batch sono collegati correttamente.
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 encoder avrà un livello nascosto superiore con 300 neuroni e un livello centrale con 150 neuroni. Il blocco decoder è simmetrico all'encoder. È possibile visualizzare la rete nel diagramma sottostante. Si noti che è possibile modificare i valori dei livelli nascosti e centrale.
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 dataset. Costruirai un autoencoder con quattro strati. Utilizzerai l'inizializzazione Xavier. Questa è una tecnica per impostare i pesi iniziali in base alla varianza sia dell'input che dell'output. Infine, utilizzerai la funzione di attivazione ELU. Regolarizzerai la funzione di perdita con un regolarizzatore L2.
Passaggio 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ò, si importa la funzione parziale. È un metodo migliore per definire i parametri dei layer densi. Il codice seguente definisce i valori dell'architettura dell'autoencoder. Come indicato in precedenza, l'encoder ha due layer, con 300 neuroni nel primo layer e 150 nel secondo. I loro valori sono memorizzati in n_hidden_1 e n_hidden_2.
È necessario definire il tasso 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 Xavier viene richiamata tramite l'oggetto xavier_initializer del modulo estimator contrib. Nello stesso estimator è 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)
Nota sulla versione: La funzione tf.contrib è stata rimossa in TensorFlow 2. I sostituti diretti sono tf.keras.initializers.GlorotUniform() al posto di xavier_initializer() e tf.keras.regularizers.l2() al posto di l2_regularizer().
Passaggio 2) Definire i livelli
Tutti i parametri dei layer densi sono stati impostati; è possibile racchiudere tutto nella variabile dense_layer utilizzando l'oggetto parziale. dense_layer utilizza quindi l'attivazione ELU, l'inizializzazione Xavier e la regolarizzazione L2 ad ogni chiamata.
## Create the dense layer
dense_layer = partial(tf.layers.dense,
activation=tf.nn.elu,
kernel_initializer=xav_init,
kernel_regularizer=l2_regularizer)
Fase 3) Definire l'architettura
Osservando lo schema dell'architettura, si nota che la rete è composta da tre strati sovrapposti, incluso uno strato di output. Nel codice seguente, vengono collegati gli strati appropriati. Ad esempio, il primo strato calcola il prodotto scalare tra la matrice di input contenente le caratteristiche e la matrice con i 300 pesi. Dopo il calcolo del prodotto scalare, l'output viene inviato alla funzione di attivazione ELU. L'output diventa l'input dello strato successivo, ed è per questo che viene utilizzato per calcolare hidden_2 e così via. La moltiplicazione tra matrici è la stessa per ogni strato perché si utilizza la stessa funzione di attivazione. Si noti che l'ultimo strato, quello di output, non applica una funzione di attivazione. Ciò è logico, poiché si tratta dell'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)
Passaggio 4) Definire l'ottimizzazione
L'ultimo passaggio consiste nella costruzione dell'ottimizzatore. Come funzione di perdita si utilizza l'Errore Quadratico Medio (MSE). Come ricorderete il tutorial sulla regressione lineare, sapete che l'MSE viene calcolato come differenza tra l'output previsto e l'etichetta reale. In questo caso, l'etichetta è la caratteristica, poiché il modello cerca di ricostruire l'input. Pertanto, si desidera calcolare la media della somma dei quadrati delle differenze tra l'output previsto e l'input. Con TensorFlow, è possibile implementare la funzione di perdita nel seguente modo:
loss = tf.reduce_mean(tf.square(outputs - features))
Successivamente, è necessario ottimizzare la funzione di perdita. Si utilizza l'ottimizzatore Adam 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 5000 diviso 150. Python È possibile eseguire i seguenti codici e assicurarsi 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
Passaggio 5) Eseguire il modello
Infine, ma non meno importante, addestra il modello. Addestrerai il modello con 100 epoche. Ciò significa che il modello visualizzerà le immagini 100 volte durante l'ottimizzazione dei pesi.
Hai già familiarità con i codici per addestrare un modello in TensorFlow. La piccola differenza consiste nel reindirizzare i dati prima di avviare l'addestramento. In questo modo, il modello si addestra 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
Passaggio 6) Valutare il modello
Ora che il modello è stato addestrato, è 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 una Windows macchina, il codice diventa test_data = unpickle(r”E:\cifar-10-batches-py\test_batch”)
Puoi provare a stampare l'immagine 13, che raffigura un cavallo.
plot_image(test_x[13], shape=[32, 32], cmap = "Greys_r")
Il grafico conferma che il batch di test è stato caricato correttamente e che l'immagine 13 appartiene alla classe su cui è stato addestrato il modello.
Per valutare il modello, utilizzerai il valore dei pixel di questa immagine e verificherai se l'encoder è in grado di ricostruire la stessa immagine dopo averla ridotta a 1024 pixel. Tieni presente che devi definire una funzione per valutare il modello su immagini diverse. Il modello dovrebbe funzionare meglio solo con i cavalli.
La funzione accetta due argomenti:
- df: Importa i dati di test
- image_number: indica 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 è stata 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)
La figura mostra l'immagine di test originale a sinistra e l'output dell'autoencoder a destra, in modo da poter valutare facilmente la perdita di dettagli fini dopo la compressione da 1024 a 150.




