Autoencoder în TensorFlow cu Exemplu

Ce este Autoencoder în Deep Learning?

An Autocoder este un instrument de învățare eficientă a codificării datelor într-o manieră nesupravegheată. Este un tip de rețea neuronală artificială care vă ajută să învățați reprezentarea seturilor de date pentru reducerea dimensionalității prin antrenarea rețelei neuronale să ignore zgomotul semnalului. Este un instrument excelent pentru a recrea o intrare.

Cu cuvinte simple, aparatul preia, să spunem o imagine, și poate produce o imagine strâns legată. Intrarea în acest tip de rețea neuronală este neetichetată, ceea ce înseamnă că rețeaua este capabilă să învețe fără supraveghere. Mai precis, intrarea este codificată de rețea pentru a se concentra doar pe cea mai critică caracteristică. Acesta este unul dintre motivele pentru care codificatorul automat este popular pentru reducerea dimensionalității. În plus, autoencodere pot fi folosite pentru a produce modele de învățare generativă. De exemplu, rețeaua neuronală poate fi antrenată cu un set de fețe și apoi poate produce fețe noi.

Cum funcționează TensorFlow Autoencoder?

Scopul unui autoencoder este de a produce o aproximare a intrării concentrându-se doar pe caracteristicile esențiale. Vă puteți gândi de ce să nu învățați pur și simplu cum să copiați și să lipiți intrarea pentru a produce rezultatul. De fapt, un autoencoder este un set de constrângeri care forțează rețeaua să învețe noi moduri de a reprezenta datele, diferite de simpla copiere a ieșirii.

Un autoencoder tipic este definit cu o intrare, o reprezentare internă și o ieșire (o aproximare a intrării). Învățarea are loc în straturile atașate reprezentării interne. De fapt, există două blocuri principale de straturi care arată ca o rețea neuronală tradițională. Ușoară diferență este că stratul care conține ieșirea trebuie să fie egal cu intrarea. În imaginea de mai jos, intrarea originală intră în primul bloc numit encoder. Această reprezentare internă comprimă (reduce) dimensiunea intrării. În al doilea bloc are loc reconstrucția intrării. Aceasta este faza de decodare.

Funcționarea autoencoderului
Funcționarea autoencoderului

Funcționarea autoencoderului

Modelul va actualiza greutățile reducând la minimum funcția de pierdere. Modelul este penalizat dacă rezultatul de reconstrucție este diferit de intrare.

Concret, imaginați-vă o imagine cu o dimensiune de 50×50 (adică, 250 de pixeli) și o rețea neuronală cu un singur strat ascuns compus din o sută de neuroni. Învățarea se face pe o hartă de caracteristici care este de două ori mai mică decât intrarea. Înseamnă că rețeaua trebuie să găsească o modalitate de a reconstrui 250 de pixeli cu doar un vector de neuroni egal cu 100.

Exemplu de codificare automată stivuită

În acest tutorial Autoencoder, veți învăța cum să utilizați un autoencoder stivuit. Arhitectura este similară cu o rețea neuronală tradițională. Intrarea merge la un strat ascuns pentru a fi comprimat sau pentru a-i reduce dimensiunea, apoi ajunge la straturile de reconstrucție. Obiectivul este de a produce o imagine de ieșire cât mai apropiată de originală. Modelul trebuie să învețe o modalitate de a-și îndeplini sarcina sub un set de constrângeri, adică cu o dimensiune inferioară.

În zilele noastre, Autoencoders în Invatare profunda sunt utilizate în principal pentru dezgomotul unei imagini. Imaginați-vă o imagine cu zgârieturi; un om este încă capabil să recunoască conținutul. Ideea dezgomotului autoencoderului este de a adăuga zgomot imaginii pentru a forța rețeaua să învețe modelul din spatele datelor.

Cealaltă familie utilă de Autoencoder Deep Learning este autoencoderul variațional. Acest tip de rețea poate genera imagini noi. Imaginează-ți că antrenezi o rețea cu imaginea unui bărbat; o astfel de rețea poate produce fețe noi.

Cum să construiți un codificator automat cu TensorFlow

În acest tutorial, veți învăța cum să construiți un autoencoder stivuit pentru a reconstrui o imagine.

Veți folosi Set de date CIFAR-10 care conține 60000 de imagini color 32×32. Setul de date Autoencoder este deja împărțit între 50000 de imagini pentru antrenament și 10000 pentru testare. Există până la zece clase:

  • Avion
  • Auto
  • Pasăre
  • Pisica
  • Cerb
  • Câine
  • Broască
  • Cal
  • Navă
  • Camion

Trebuie să descărcați imaginile de la această adresă URL https://www.cs.toronto.edu/~kriz/cifar.html și să o dezarhivați. Dosarul for-10-batches-py conține cinci loturi de date cu 10000 de imagini fiecare într-o ordine aleatorie.

Înainte de a vă construi și antrena modelul, trebuie să aplicați o anumită prelucrare a datelor. Veți proceda după cum urmează:

  1. Importă datele
  2. Convertiți datele în format alb-negru
  3. Adăugați toate loturile
  4. Construiți setul de date de antrenament
  5. Construiți un vizualizator de imagine

Preprocesarea imaginii

Pasul 1) Importați datele

Conform site-ului oficial, puteți încărca datele cu următorul cod. Codul Autoencoder va încărca datele într-un dicționar cu de date si etichetă. Rețineți că codul este o funcție.

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

Pasul 2) Convertiți datele în format alb-negru

Pentru simplitate, veți converti datele în tonuri de gri. Adică, cu o singură dimensiune față de trei pentru imaginea în culori. Majoritatea rețelei neuronale funcționează doar cu o intrare de dimensiune.

def grayscale(im):
    return im.reshape(im.shape[0], 3, 32, 32).mean(1).reshape(im.shape[0], -1)

Pasul 3) Adăugați toate loturile

Acum că ambele funcții sunt create și setul de date încărcat, puteți scrie o buclă pentru a adăuga datele în memorie. Dacă verificați cu atenție, fișierul de dezarhivare cu datele se numește data_batch_ cu un număr de la 1 la 5. Puteți să treceți peste fișiere și să îl adăugați la date.

Când acest pas este finalizat, convertiți datele de culori într-un format de scară de gri. După cum puteți vedea, forma datelor este 50000 și 1024. Cei 32*32 pixeli sunt acum aplatizați în 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)

Notă: Schimbați „./cifar-10-batches-py/data_batch_” la locația reală a fișierului dvs. De exemplu pentru Windows mașină, calea ar putea fi nume de fișier = „E:\cifar-10-batches-py\data_batch_” + str(i)

Pasul 4) Construiți setul de date de antrenament

Pentru a face antrenamentul mai rapid și mai ușor, veți antrena un model numai pe imaginile cailor. Caii sunt clasa a șaptea în datele de pe etichetă. După cum se menționează în documentația setului de date CIFAR-10, fiecare clasă conține 5000 de imagini. Puteți imprima forma datelor pentru a confirma că există 5.000 de imagini cu 1024 de coloane, așa cum se arată în mai jos TensorFlow Exemplu de pas al codificatorului automat.

horse_i = np.where(y == 7)[0]
horse_x = x[horse_i]
print(np.shape(horse_x)) 
(5000, 1024)

Pasul 5) Construiți un vizualizator de imagine

În cele din urmă, construiți o funcție pentru a reprezenta imaginile. Veți avea nevoie de această funcție pentru a imprima imaginea reconstruită din autoencoder.

O modalitate ușoară de a imprima imagini este să utilizați obiectul imshow din biblioteca matplotlib. Rețineți că trebuie să convertiți forma datelor de la 1024 la 32*32 (adică formatul unei imagini).

# 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")   

Funcția ia 3 argumente:

  • Imagine: Intrarea
  • Modela: lista, dimensiunea imaginii
  • Cmap:alege harta culorilor. Implicit, gri

Puteți încerca să trasați prima imagine din setul de date. Ar trebui să vezi un bărbat pe cal.

plot_image(horse_x[1], shape=[32, 32], cmap = "Greys_r")

Construiți un vizualizator de imagine

Setați estimatorul setului de date

În regulă, acum că setul de date este gata de utilizare, puteți începe să utilizați Tensorflow. Înainte de a construi modelul, să folosim estimatorul de set de date al Tensorflow pentru a alimenta rețeaua.

Veți construi un set de date cu estimatorul TensorFlow. Pentru a vă împrospăta mintea, trebuie să utilizați:

  • din_slice_tensor
  • repeta
  • lot

Codul complet pentru construirea setului de date este:

dataset = tf.data.Dataset.from_tensor_slices(x).repeat().batch(batch_size)

Rețineți că, x este un substituent cu următoarea formă:

  • [None,n_inputs]: Setați la None, deoarece numărul de fluxuri de imagini în rețea este egal cu dimensiunea lotului.

pentru detalii, consultați tutorialul de pe regresie liniara.

După aceea, trebuie să creați iteratorul. Fără această linie de cod, nicio dată nu va trece prin conductă.

iter = dataset.make_initializable_iterator() # create the iteratorfeatures = iter.get_next()

Acum că conducta este gata, puteți verifica dacă prima imagine este aceeași ca înainte (adică, un bărbat pe cal).

Setați dimensiunea lotului la 1 deoarece doriți să alimentați setul de date doar cu o singură imagine. Puteți vedea dimensiunea datelor cu print(sess.run(features).shape). Este egal cu (1, 1024). 1 înseamnă că o singură imagine cu 1024 este alimentată fiecare. Dacă dimensiunea lotului este setată la două, atunci două imagini vor trece prin conductă. (Nu modificați dimensiunea lotului. În caz contrar, va genera o eroare. Doar o imagine la un moment dat poate merge la funcția 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)

Setați estimatorul setului de date

Construiește rețeaua

Este timpul să construim rețeaua. Veți antrena un autoencoder stivuit, adică o rețea cu mai multe straturi ascunse.

Rețeaua dvs. va avea un singur strat de intrare cu 1024 de puncte, adică 32×32, forma imaginii.

Blocul codificator va avea un strat ascuns superior cu 300 de neuroni, un strat central cu 150 de neuroni. Blocul decodor este simetric față de encoder. Puteți vizualiza rețeaua în imaginea de mai jos. Rețineți că puteți modifica valorile straturilor ascunse și centrale.

Construiți rețeaua
Construirea rețelei pentru Autoencoder

Construirea unui autoencoder este foarte asemănătoare cu orice alt model de deep learning.

Veți construi modelul urmând acești pași:

  1. Definiți parametrii
  2. Definiți straturile
  3. Definiți arhitectura
  4. Definiți optimizarea
  5. Rulați modelul
  6. Evaluați modelul

În secțiunea anterioară, ați învățat cum să creați o conductă pentru a alimenta modelul, deci nu este nevoie să creați încă o dată setul de date. Veți construi un autoencoder cu patru straturi. Folosești inițializarea Xavier. Aceasta este o tehnică pentru a seta ponderile inițiale egale cu varianța atât a intrării, cât și a ieșirii. În cele din urmă, utilizați funcția de activare elu. Regularizați funcția de pierdere cu regulatorul L2.

Pas 1) Definiți parametrii

Primul pas presupune definirea numărului de neuroni din fiecare strat, a ratei de învățare și a hiperparametrului regulatorului.

Înainte de aceasta, importați parțial funcția. Este o metodă mai bună de a defini parametrii straturilor dense. Codul de mai jos definește valorile arhitecturii autoencoder. După cum s-a enumerat mai înainte, autoencoderul are două straturi, cu 300 de neuroni în primele straturi și 150 în al doilea. Valorile lor sunt stocate în n_hidden_1 și n_hidden_2.

Trebuie să definiți rata de învățare și hiperparametrul L2. Valorile sunt stocate în learning_rate și 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

Tehnica de inițializare Xavier este apelată cu obiectul xavier_initializer din contribuția estimatorului. În același estimator, puteți adăuga regulatorul cu 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)

Pas 2) Definiți straturile

Toți parametrii straturilor dense au fost setați; puteți împacheta totul în variabila dense_layer utilizând obiectul parțial. dense_layer care utilizează activarea ELU, inițializarea Xavier și regularizarea L2.

## Create the dense layer
dense_layer = partial(tf.layers.dense,
                         activation=tf.nn.elu,
                         kernel_initializer=xav_init,
                         kernel_regularizer=l2_regularizer)

Pas 3) Definiți arhitectura

Dacă te uiți la imaginea arhitecturii, observi că rețeaua stivuiește trei straturi cu un strat de ieșire. În codul de mai jos, conectați straturile corespunzătoare. De exemplu, primul strat calculează produsul punctual dintre caracteristicile matricei de intrare și matricele care conțin cele 300 de ponderi. După ce produsul punctual este calculat, rezultatul trece la funcția de activare Elu. Ieșirea devine intrarea următorului strat, de aceea îl folosiți pentru a calcula hidden_2 și așa mai departe. Înmulțirea matricelor este aceeași pentru fiecare strat deoarece utilizați aceeași funcție de activare. Rețineți că ultimul strat, ieșirile, nu aplică o funcție de activare. Are sens, deoarece aceasta este intrarea reconstruită

## 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)

Pas 4) Definiți optimizarea

Ultimul pas este construirea optimizatorului. Utilizați eroarea pătrată medie ca funcție de pierdere. Dacă vă amintiți tutorialul despre regresia liniară, știți că MSE este calculată cu diferența dintre rezultatul prezis și eticheta reală. Aici, eticheta este caracteristica deoarece modelul încearcă să reconstruiască intrarea. Prin urmare, doriți media sumei diferenței pătratului dintre ieșirea și intrarea prezisă. Cu TensorFlow, puteți codifica funcția de pierdere după cum urmează:

loss = tf.reduce_mean(tf.square(outputs - features))

Apoi, trebuie să optimizați funcția de pierdere. Utilizați Adam Optimizer pentru a calcula gradienții. Funcția obiectivă este de a minimiza pierderea.

## Optimize
loss = tf.reduce_mean(tf.square(outputs - features))
optimizer = tf.train.AdamOptimizer(learning_rate)
train  = optimizer.minimize(loss)

Încă o setare înainte de antrenamentul modelului. Doriți să utilizați o dimensiune de lot de 150, adică să alimentați conducta cu 150 de imagini la fiecare iterație. Trebuie să calculați manual numărul de iterații. Acest lucru este banal de făcut:

Dacă doriți să treceți 150 de imagini de fiecare dată și știți că există 5000 de imagini în setul de date, numărul de iterații este egal cu . În python puteți rula următoarele coduri și vă asigurați că rezultatul este 33:

BATCH_SIZE = 150
### Number of batches :  length dataset / batch size
n_batches = horse_x.shape[0] // BATCH_SIZE
print(n_batches)
33

Pas 5) Rulați modelul

Nu în ultimul rând, antrenează modelul. Antrenezi modelul cu 100 de epoci. Adică, modelul va vedea de 100 de ori imaginile la greutăți optimizate.

Sunteți deja familiarizat cu codurile pentru a antrena un model în Tensorflow. Ușoară diferență este să canalizați datele înainte de a rula antrenamentul. În acest fel, modelul se antrenează mai repede.

Sunteți interesat să imprimați pierderea după zece epoci pentru a vedea dacă modelul învață ceva (adică pierderea este în scădere). Antrenamentul durează între 2 și 5 minute, în funcție de hardware-ul mașinii dvs.

## 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

Pas 6) Evaluați modelul

Acum că ai pregătit modelul, este timpul să-l evaluezi. Trebuie să importați setul de testare din fișierul /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'])

NOTĂ: Pentru o Windows mașină, codul devine test_data = unpickle(r”E:\cifar-10-batches-py\test_batch”)

Puteți încerca să imprimați imaginile 13, care este un cal

plot_image(test_x[13], shape=[32, 32], cmap = "Greys_r")

Evaluați modelul

Pentru a evalua modelul, veți folosi valoarea pixelului acestei imagini și veți vedea dacă codificatorul poate reconstrui aceeași imagine după micșorarea cu 1024 de pixeli. Rețineți că definiți o funcție pentru a evalua modelul pe diferite imagini. Modelul ar trebui să funcționeze mai bine doar la cai.

Funcția ia două argumente:

  • df: importați datele de testare
  • imagine_number: indicați ce imagine să importați

Funcția este împărțită în trei părți:

  1. Reforma imaginea la dimensiunea corectă, adică 1, 1024
  2. Alimentați modelul cu imaginea nevăzută, codificați/decodificați imaginea
  3. Tipăriți imaginea reală și reconstruită
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()

Acum că funcția de evaluare este definită, puteți vedea imaginea reconstruită numărul treisprezece

reconstruct_image(df =test_x, image_number = 13)
INFO:tensorflow:Restoring parameters from ./model.ckpt
Model restored.
(1, 1024)

Evaluați modelul

Rezumat

  • Scopul principal al unui autoencoder este de a comprima datele de intrare și apoi de a le decomprima într-o ieșire care arată îndeaproape ca datele originale.
  • Arhitectura unui autoencoder simetric cu un strat pivot numit stratul central.
  • Puteți crea codificatorul automat folosind:
  • Parțial: pentru a crea straturile dense cu setarea tipică:

      	tf.layers.dense,                         
      	activation=tf.nn.elu,                         
      	kernel_initializer=xav_init,                         
      	kernel_regularizer=l2_regularizer

    strat_dens(): pentru a face înmulțirea matricei

  • Puteți defini funcția de pierdere și optimizare cu:
  • loss = tf.reduce_mean(tf.square(outputs - features))
    optimizer = tf.train.AdamOptimizer(learning_rate)
    train  = optimizer.minimize(loss)
    
  • Ultimul rulează o sesiune pentru a antrena modelul.