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.

Funzionamento del codificatore automatico
Funzionamento del codificatore automatico

Funzionamento del codificatore automatico

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:

  1. Importa i dati
  2. Converti i dati in formato bianco e nero
  3. Aggiungi tutti i batch
  4. Costruire il set di dati di addestramento
  5. 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")

Costruisci un visualizzatore di immagini

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)

Imposta la stima del set di dati

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.

Costruisci la rete
Costruire la rete per Autoencoder

Costruire un codificatore automatico è molto simile a qualsiasi altro modello di deep learning.

Costruirai il modello seguendo questi passaggi:

  1. Definire i parametri
  2. Definire gli strati
  3. Definire l'architettura
  4. Definire l'ottimizzazione
  5. Esegui il modello
  6. 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")

Valuta il modello

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:

  1. Rimodellare l'immagine alla dimensione corretta, ovvero 1, 1024
  2. Alimenta il modello con l'immagine invisibile, codifica/decodifica l'immagine
  3. 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)

Valuta il modello

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

  • È possibile definire la funzione di perdita e l'ottimizzazione con:
  • loss = tf.reduce_mean(tf.square(outputs - features))
    optimizer = tf.train.AdamOptimizer(learning_rate)
    train  = optimizer.minimize(loss)
    
  • Ultima esecuzione di una sessione per addestrare il modello.