Autoenkooderi TensorFlow'ssa esimerkin kanssa

Mikä on Autoencoder in Deep Learning?

An Automaattinen kooderi on työkalu tiedon koodauksen tehokkaaseen oppimiseen ilman valvontaa. Se on eräänlainen keinotekoinen hermoverkko, joka auttaa sinua oppimaan datajoukkojen esitystavan ulottuvuuden vähentämiseksi kouluttamalla hermoverkkoa jättämään huomioimatta signaalikohinan. Se on loistava työkalu syötteen uudelleenluomiseen.

Yksinkertaisesti sanottuna kone ottaa, sanotaanko kuvan, ja voi tuottaa siihen läheisesti liittyvän kuvan. Tällaisen hermoverkon syöttö on leimaamaton, mikä tarkoittaa, että verkko pystyy oppimaan ilman valvontaa. Tarkemmin sanottuna verkko koodaa tulon keskittymään vain kriittisimpään ominaisuuteen. Tämä on yksi syistä, miksi autoencoder on suosittu ulottuvuuden vähentämisessä. Lisäksi autoenkoodereita voidaan käyttää tuottamiseen generatiivisia oppimismalleja. Esimerkiksi hermoverkkoa voidaan kouluttaa kasvojoukolla ja sen jälkeen tuottaa uusia kasvoja.

Kuinka TensorFlow Autoencoder toimii?

Autoenkooderin tarkoitus on tuottaa likiarvo syötteestä keskittymällä vain oleellisiin ominaisuuksiin. Saatat ajatella, miksi et vain opettele kopioimaan ja liittämään syöte tulosteen tuottamiseksi. Itse asiassa automaattinen kooderi on joukko rajoitteita, jotka pakottavat verkon oppimaan uusia tapoja esittää dataa, toisin kuin pelkkä tulosteen kopioiminen.

Tyypillinen autoenkooderi määritellään syötteellä, sisäisellä esityksellä ja lähdöllä (sisääntulon likiarvo). Oppiminen tapahtuu sisäiseen esitykseen liitetyissä kerroksissa. Itse asiassa on olemassa kaksi päälohkoa kerroksia, jotka näyttävät perinteiseltä hermoverkolta. Pieni ero on siinä, että tulosteen sisältävän kerroksen on oltava yhtä suuri kuin tulo. Alla olevassa kuvassa alkuperäinen syöte menee ensimmäiseen lohkoon, jota kutsutaan nimellä kooderi. Tämä sisäinen esitys pakkaa (pienentää) syötteen kokoa. Toisessa lohkossa tapahtuu tulon rekonstruktio. Tämä on dekoodausvaihe.

Autoencoderin toiminta
Autoencoderin toiminta

Autoencoderin toiminta

Malli päivittää painot minimoimalla häviöfunktion. Mallia rangaistaan, jos rekonstruktiotulos poikkeaa tulosta.

Kuvittele konkreettisesti kuva, jonka koko on 50 × 50 (eli 250 pikseliä) ja hermoverkko, jossa on vain yksi piilotettu kerros, joka koostuu sadasta neuronista. Oppiminen tapahtuu ominaisuuskartalla, joka on kaksi kertaa syötettä pienempi. Se tarkoittaa, että verkon on löydettävä tapa rekonstruoida 250 pikseliä vain 100:aa hermosolujen vektorilla.

Pinottu automaattinen kooderi esimerkki

Tässä Autoencoder-opetusohjelmassa opit käyttämään pinottua automaattista kooderia. Arkkitehtuuri on samanlainen kuin perinteinen hermoverkko. Syöte menee piilotettuun kerrokseen pakattavaksi tai pienentääkseen sen kokoa ja saavuttaa sitten rekonstruktiotasot. Tavoitteena on tuottaa tulostekuva, joka on yhtä lähellä alkuperäistä. Mallin on opittava tapa saavuttaa tehtävänsä rajoitusten alaisena, eli pienemmällä ulottuvuudella.

Nykyään automaattiset kooderit ovat käytössä Deep Learning käytetään pääasiassa kuvan vaimentamiseen. Kuvittele kuva, jossa on naarmuja; ihminen pystyy silti tunnistamaan sisällön. Kohinanpoiston ideana on lisätä kuvaan kohinaa, joka pakottaa verkon oppimaan datan takana olevan kuvion.

Toinen hyödyllinen Autoencoder Deep Learning -perhe on variaatioautoenkooderi. Tämäntyyppinen verkko voi luoda uusia kuvia. Kuvittele, että koulutat verkostoa miehen kuvan kanssa; tällainen verkosto voi tuottaa uusia kasvoja.

Autoenkooderin rakentaminen TensorFlow'n avulla

Tässä opetusohjelmassa opit rakentamaan pinotun automaattisen enkooderin kuvan rekonstruoimiseksi.

Käytät CIFAR-10-tietojoukko joka sisältää 60000 32×32 värikuvaa. Autoencoder-tietojoukko on jo jaettu 50000 10000 kuvaan koulutusta varten ja XNUMX XNUMX kuvaan testausta varten. Luokkia on enintään kymmenen:

  • Lentokone
  • Auto
  • Lintu
  • Kissa
  • Hirvi
  • Koira
  • Sammakko
  • Hevonen
  • Lähettää
  • kuorma-auto

Lataa kuvat tästä URL-osoitteesta https://www.cs.toronto.edu/~kriz/cifar.html ja pura ne. Kansio for-10-batches-py sisältää viisi tietoerää, joissa kussakin on 10000 XNUMX kuvaa satunnaisessa järjestyksessä.

Ennen kuin rakennat ja koulutat malliasi, sinun on käytettävä jonkin verran tietojenkäsittelyä. Toimit seuraavasti:

  1. Tuo tiedot
  2. Muunna tiedot mustavalkomuotoon
  3. Liitä kaikki erät
  4. Luo harjoitustietojoukko
  5. Rakenna kuvan visualisoija

Kuvan esikäsittely

Vaihe 1) Tuo tiedot

Virallisen verkkosivuston mukaan voit ladata tiedot seuraavalla koodilla. Autoencoder-koodi lataa tiedot sanakirjaan, jossa on tiedot ja etiketti. Huomaa, että koodi on funktio.

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

Vaihe 2) Muunna tiedot mustavalkomuotoon

Yksinkertaisuuden vuoksi voit muuntaa tiedot harmaasävyiksi. Eli vain yksi ulottuvuus verrattuna kolmeen värikuvaan. Suurin osa hermoverkosta toimii vain yhden ulottuvuuden tulolla.

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

Vaihe 3) Liitä kaikki erät

Nyt kun molemmat funktiot on luotu ja tietojoukko ladattu, voit kirjoittaa silmukan tietojen lisäämiseksi muistiin. Jos tarkistat huolellisesti, tiedot sisältävä purkaustiedosto on nimeltään data_batch_ numerolla 1-5. Voit kiertää tiedostot ja liittää sen tietoihin.

Kun tämä vaihe on tehty, muutat väritiedot harmaasävymuotoon. Kuten näet, datan muoto on 50000 ja 1024. 32*32 pikseliä on nyt litistetty vuoteen 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)

Huomautus: Vaihda './cifar-10-batches-py/data_batch_' tiedostosi todelliseen sijaintiin. Esimerkiksi varten Windows koneeseen, polku voisi olla tiedostonimi = 'E:\cifar-10-batches-py\data_batch_' + str(i)

Vaihe 4) Luo harjoitustietojoukko

Jotta harjoittelu olisi nopeampaa ja helpompaa, koulutat mallin vain hevoskuviin. Hevoset ovat etikettitiedoissa seitsemäs luokka. Kuten CIFAR-10-tietojoukon dokumentaatiossa mainittiin, jokainen luokka sisältää 5000 kuvaa. Voit tulostaa tietojen muodon varmistaaksesi, että siinä on 5.000 1024 kuvaa, joissa on XNUMX saraketta alla olevan kuvan mukaisesti TensorFlow Autoenkooderin esimerkkivaihe.

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

Vaihe 5) Rakenna kuvan visualisointityökalu

Lopuksi rakennat funktion kuvien piirtämiseksi. Tarvitset tätä toimintoa rekonstruoidun kuvan tulostamiseen autoenkooderista.

Helppo tapa tulostaa kuvia on käyttää matplotlib-kirjaston objektia imshow. Huomaa, että sinun on muutettava tietojen muoto 1024:stä 32*32:ksi (eli kuvan muotoon).

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

Funktiolla on 3 argumenttia:

  • Kuva: syöttö
  • Muoto: luettelo, kuvan koko
  • Cmap:valitse värikartta. Oletuksena harmaa

Voit yrittää piirtää tietojoukon ensimmäisen kuvan. Sinun pitäisi nähdä mies hevosen selässä.

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

Rakenna Image Visualizer

Aseta Dataset Estimator

Selvä, nyt kun tietojoukko on valmis käytettäväksi, voit aloittaa Tensorflow:n käytön. Ennen mallin rakentamista käytetään Tensorflow:n Dataset estimaattoria syöttämään verkkoa.

Rakennat tietojoukon TensorFlow-estimaattorilla. Mieli virkistämiseksi sinun on käytettävä:

  • from_tensor_slices
  • toistaa
  • erä

Täysi koodi tietojoukon rakentamiseksi on:

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

Huomaa, että x on paikkamerkki, jolla on seuraava muoto:

  • [None,n_inputs]: Aseta arvoon Ei mitään, koska verkkoon syötettävien kuvien määrä on yhtä suuri kuin eräkoko.

Lisätietoja on opetusohjelmassa osoitteessa lineaarinen regressio.

Tämän jälkeen sinun on luotava iteraattori. Ilman tätä koodiriviä tietoja ei kulje liukuhihnan läpi.

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

Nyt kun liukuhihna on valmis, voit tarkistaa, onko ensimmäinen kuva sama kuin ennen (eli mies hevosen selässä).

Asetat eräkooksi 1, koska haluat syöttää tietojoukon vain yhdellä kuvalla. Tietojen mitat näet komennolla print(sess.run(features).shape). Se on yhtä suuri kuin (1, 1024). 1 tarkoittaa, että vain yksi kuva, jossa on 1024, syötetään. Jos erän kooksi on asetettu kaksi, kaksi kuvaa kulkee liukuhihnan läpi. (Älä muuta eräkokoa. Muuten se antaa virheilmoituksen. Vain yksi kuva kerrallaan voi mennä funktioon 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)

Aseta Dataset Estimator

Rakenna verkko

On aika rakentaa verkko. Harjoittelet pinottua autoenkooderia, eli verkkoa, jossa on useita piilotettuja kerroksia.

Verkossasi on yksi syöttötaso, jossa on 1024 pistettä, eli 32×32, kuvan muoto.

Enkooderilohkossa on yksi ylin piilotettu kerros, jossa on 300 neuronia, ja keskuskerros, jossa on 150 neuronia. Dekooderilohko on symmetrinen kooderiin nähden. Voit visualisoida verkon alla olevasta kuvasta. Huomaa, että voit muuttaa piilotettujen ja keskitasojen arvoja.

Rakenna verkko
Verkon rakentaminen Autoencoderille

Autoenkooderin rakentaminen on hyvin samanlaista kuin mikä tahansa muu syväoppimismalli.

Rakennat mallin seuraavasti:

  1. Määritä parametrit
  2. Määritä kerrokset
  3. Määrittele arkkitehtuuri
  4. Määrittele optimointi
  5. Suorita malli
  6. Arvioi malli

Edellisessä osiossa opit luomaan liukuhihnan mallin syöttämiseksi, joten tietojoukkoa ei tarvitse luoda uudelleen. Rakennat automaattisen kooderin, jossa on neljä kerrosta. Käytät Xavier-alustusta. Tämä on tekniikka, jolla asetetaan alkuperäiset painot yhtä suureksi kuin tulon ja lähdön varianssi. Lopuksi käytät elu-aktivointitoimintoa. Säädät häviöfunktion L2-regulaattorilla.

Vaihe 1) Määritä parametrit

Ensimmäinen vaihe tarkoittaa, että määritetään kunkin kerroksen neuronien lukumäärä, oppimisnopeus ja regularisaattorin hyperparametri.

Ennen sitä tuot funktion osittain. Se on parempi tapa määritellä tiheiden kerrosten parametrit. Alla oleva koodi määrittelee autoencoder-arkkitehtuurin arvot. Kuten edellä mainittiin, autoenkooderissa on kaksi kerrosta, 300 neuronia ensimmäisissä kerroksissa ja 150 toisissa kerroksissa. Niiden arvot tallennetaan kansioon n_hidden_1 ja n_hidden_2.

Sinun on määritettävä oppimisnopeus ja L2-hyperparametri. Arvot tallennetaan kohteisiin learning_rate ja 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

Xavier-alustustekniikkaa kutsutaan objektilla xavier_initializer estimaattorin contribista. Samassa estimaattorissa voit lisätä regularisaattorin parametrilla 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)

Vaihe 2) Määritä kerrokset

Kaikki tiheiden kerrosten parametrit on asetettu; voit pakata kaiken muuttujaan dense_layer käyttämällä objektin osittaista. dense_layer, joka käyttää ELU-aktivointia, Xavier-alustusta ja L2-regulointia.

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

Vaihe 3) Määrittele arkkitehtuuri

Jos katsot kuvaa arkkitehtuurista, huomaat, että verkko pinoaa kolme kerrosta tuloskerroksen kanssa. Alla olevassa koodissa yhdistät sopivat kerrokset. Esimerkiksi ensimmäinen kerros laskee pistetulon syötematriisiominaisuuksien ja 300 painoa sisältävien matriisien välillä. Kun pistetulo on laskettu, tulos siirtyy Elu-aktivointitoimintoon. Tulosta tulee seuraavan kerroksen syöte, minkä vuoksi käytät sitä piilotetun_2:n ja niin edelleen laskemiseen. Matriisien kertolasku on sama jokaiselle tasolle, koska käytät samaa aktivointifunktiota. Huomaa, että viimeinen kerros, lähdöt, ei käytä aktivointitoimintoa. Se on järkevää, koska tämä on rekonstruoitu syöte

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

Vaihe 4) Määrittele optimointi

Viimeinen vaihe on optimoijan rakentaminen. Käytät Mean Square Error -virhettä tappiofunktiona. Jos muistat lineaarisen regression opetusohjelman, tiedät, että MSE lasketaan ennustetun lähdön ja todellisen nimiön välisen eron perusteella. Tässä tunniste on ominaisuus, koska malli yrittää rekonstruoida syötteen. Siksi haluat ennustetun lähdön ja tulon välisen neliön erotuksen keskiarvon. TensorFlow'lla voit koodata häviöfunktion seuraavasti:

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

Sitten sinun on optimoitava häviötoiminto. Käytät Adam Optimizer -työkalua gradientien laskemiseen. Tavoitteena on minimoida tappio.

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

Vielä yksi asetus ennen mallin harjoittelua. Haluat käyttää eräkokoa 150, eli syöttää liukuhihnaan 150 kuvaa jokaisessa iteraatiossa. Sinun on laskettava iteraatioiden määrä manuaalisesti. Tämä on triviaalia tehdä:

Jos haluat välittää 150 kuvaa joka kerta ja tiedät, että tietojoukossa on 5000 kuvaa, iteraatioiden määrä on yhtä suuri kuin . Pythonissa voit suorittaa seuraavat koodit ja varmistaa, että tulos on 33:

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

Vaihe 5) Suorita malli

Viimeisenä mutta ei vähäisimpänä, kouluta malli. Harjoittelet mallia 100 jaksolla. Toisin sanoen malli näkee 100-kertaisesti kuvat optimoiduilla painoilla.

Tunnet jo koodit mallin kouluttamiseksi Tensorflowissa. Pieni ero on se, että tiedot putkitetaan ennen harjoituksen suorittamista. Tällä tavalla malli harjoittelee nopeammin.

Olet kiinnostunut tulostamaan häviön kymmenen aikakauden jälkeen nähdäksesi, onko malli oppimassa jotain (eli häviö vähenee). Harjoittelu kestää 2-5 minuuttia koneen laitteistosta riippuen.

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

Vaihe 6) Arvioi malli

Nyt kun mallisi on koulutettu, on aika arvioida se. Sinun on tuotava testisarja tiedostosta /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'])

HUOMAUTUS: A Windows koneessa koodiksi tulee test_data = unpickle(r”E:\cifar-10-batches-py\test_batch”)

Voit yrittää tulostaa kuvat 13, joka on hevonen

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

Arvioi malli

Mallin arvioimiseksi käytät tämän kuvan pikseliarvoa ja katsot, pystyykö enkooderi rekonstruoimaan saman kuvan kutistettuaan 1024 pikseliä. Huomaa, että määrität funktion mallin arvioimiseksi eri kuvissa. Mallin pitäisi toimia paremmin vain hevosilla.

Funktiolla on kaksi argumenttia:

  • df: Tuo testitiedot
  • kuvan_numero: ilmoittaa tuotava kuva

Toiminto on jaettu kolmeen osaan:

  1. Muotoile kuva uudelleen oikeaan mittaan, eli 1, 1024
  2. Syötä malliin näkymätön kuva, koodaa/dekoodaa kuva
  3. Tulosta todellinen ja rekonstruoitu kuva
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()

Nyt kun arviointifunktio on määritetty, voit tarkastella rekonstruoitua kuvaa numero kolmetoista

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

Arvioi malli

Yhteenveto

  • Autoenkooderin ensisijainen tarkoitus on pakata syötetiedot ja purkaa se sitten ulostuloksi, joka muistuttaa läheisesti alkuperäistä dataa.
  • Autoenkooderin arkkitehtuuri, joka on symmetrinen pivot-kerroksen kanssa, nimeltään keskuskerros.
  • Voit luoda automaattisen kooderin käyttämällä:
  • Osittainen: luodaksesi tiheät kerrokset tyypillisellä asetuksella:

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

    tiheä_kerros(): matriisin kertolasku

  • Voit määrittää häviöfunktion ja optimoinnin seuraavilla tavoilla:
  • loss = tf.reduce_mean(tf.square(outputs - features))
    optimizer = tf.train.AdamOptimizer(learning_rate)
    train  = optimizer.minimize(loss)
    
  • Suorita viimeinen istunto mallin kouluttamiseksi.