RNN (Recurrent Neural Network) -opetusohjelma: TensorFlow-esimerkki

⚡ Älykäs yhteenveto

Rekurrentit neuroverkot lisäävät muistitilan tavallisiin neuroneihin ja syöttävät jokaisen tulosteen takaisin seuraavana syötteenä, jotta malli voi oppia järjestyksestä. Tämä läpikäynti rakentaa sellaisen TensorFlow'ssa ja ennustaa aikasarjan.

  • 🔘 Muistin tila: Jokainen toistuva neuroni vastaanottaa edellisen tuotoksen uuden syötteen rinnalla, mikä antaa verkolle sen ajallisen tietoisuuden.
  • ☑️ Lähtömuoto: Leluverkon suoritus palauttaa (3, 2, 6)-tensorin: erät, aika-askeleet ja neuronit tässä järjestyksessä.
  • ✅ Erälaskentasääntö: Aikasarjasyötteet muotoillaan uudelleen kolmiulotteisiksi ja otsikkotaulukko on sama sarja siirrettynä yhden jakson eteenpäin.
  • 🧪 Mallin runko: Paikkamerkit, dynamic_rnn-muuttujaan kääritty BasicRNNCell, tiheä projektio ja sitten keskimääräinen neliövirhe Adam-optimoijalla.
  • 🛠️ Harjoitusajo: 1 500 epookkia 120 toistuvalla neuronilla ajaa menetyksen 502 893:sta noin 1 385:een.
  • 📉 Tunnettu raja: Pitkät sekvenssit laukaisevat katoavan gradientin ongelman, jonka ratkaisemiseksi LSTM ja portitetut variantit suunniteltiin.

RNN Recurrent Neuroverkko

Miksi tarvitsemme toistuvan hermoverkon (RNN)?

Recurrent Neural Network (RNN) mahdollistaa muistiyksiköiden mallintamisen pysyviä tietoja varten ja lyhytaikaisten riippuvuuksien mallintamisen. Sitä käytetään myös aikasarjaennusteissa tietojen korrelaatioiden ja kuvioiden tunnistamiseen. Se auttaa myös tuottamaan ennustavia tuloksia peräkkäisille tiedoille toimittamalla samanlaista käyttäytymistä kuin ihmisen aivot.

Rakenne an Keinotekoinen hermoverkko on suhteellisen yksinkertainen ja koskee pääasiassa matriisien kertolaskua. Ensimmäisessä vaiheessa syötteet kerrotaan aluksi satunnaisilla painoilla ja harhoilla, muunnetaan aktivointifunktiolla ja lähtöarvoja käytetään ennusteen tekemiseen. Tämä vaihe antaa kuvan siitä, kuinka kaukana verkko on todellisuudesta.

Käytetty mittari on tappio. Mitä suurempi häviöfunktio, sitä typerämpi malli on. Verkon tuntemuksen parantamiseksi tarvitaan jonkin verran optimointia säätämällä verkon painoja. Stokastinen gradienttilasku on menetelmä, jota käytetään painojen arvojen muuttamiseksi oikeaan suuntaan. Kun säätö on tehty, verkko voi testata uutta tietoaan toisella tietoerällä.

Virhe onneksi pienempi kuin ennen, mutta ei kuitenkaan tarpeeksi pieni. Optimointivaihetta tehdään iteratiivisesti, kunnes virhe on minimoitu eli tietoa ei voida enää hakea.tracTED.

Tämän tyyppisen mallin ongelmana on, että siinä ei ole muistia. Se tarkoittaa, että tulo ja lähtö ovat riippumattomia. Toisin sanoen malli ei välitä siitä, mitä oli ennen. Se herättää kysymyksiä, kun sinun täytyy ennustaa aikasarjoja tai lauseita, koska verkossa on oltava tietoa historiallisista tiedoista tai menneistä sanoista.

Tämän ongelman ratkaisemiseksi on kehitetty uudenlainen arkkitehtuuri: Recurrent Neural network (RNN, jäljempänä)

Mikä on toistuva hermoverkko (RNN)?

Rekurrentti neuroverkko (RNN) on keinotekoisten neuroverkkojen luokka, jossa eri solmujen välinen yhteys muodostaa suunnatun graafin, joka antaa ajallisen dynaamisen käyttäytymisen. Se auttaa mallintamaan eteenpäin syötetyistä verkoista johdettua peräkkäistä dataa. Se toimii samalla tavalla kuin ihmisaivot ennustavien tulosten tuottamiseksi.

Toistuva hermoverkko näyttää melko samanlaiselta kuin perinteinen hermoverkko, paitsi että neuroneille lisätään muistitila. Muistin lisääminen on yksinkertaista.

Kuvittele yksinkertainen malli, jossa vain yksi neuroni syöttää dataerää. Perinteisessä neuroverkossa malli tuottaa tulosteen kertomalla syötteen painolla ja aktivointifunktiolla. RNN:ssä tämä tuloste lähetetään takaisin itselleen tietyn määrän kertoja. Kutsumme sitä aika askel aika, jonka kuluessa tulosteesta tulee seuraavan matriisikertolaskun syöte.

Esimerkiksi alla olevassa kuvassa näet, että verkko koostuu yhdestä neuronista. Verkko laskee syötteen ja painon väliset matriisikertoimet ja lisää epälineaarisuuden aktivointifunktiolla. Siitä tulee lähtö t-1:ssä. Tämä lähtö on toisen matriisikertolaskun tulo.

Yksittäinen toistuva neuroni lähettää lähtönsä t-1:ssä takaisin seuraavan kertolaskun syötteenä

Toistuva hermoverkko (RNN)

Alla koodaamme yksinkertaisen RNN:n TensorFlow'ssa ymmärtääksemme vaiheen ja myös lähdön muodon.

Verkko koostuu:

  • Neljä tuloa
  • Kuusi neuronia
  • 2-kertaiset askeleet

Verkko toimii alla olevan kuvan mukaisesti.

Rullaamaton RNN, jossa on neljä tuloa, kuusi neuronia ja kaksi aika-askelta

Verkkoa kutsutaan "toistuvaksi", koska se suorittaa saman toiminnon jokaisessa aktivointiruudussa. Verkko laski tulojen ja edellisen lähdön painot ennen aktivointitoiminnon käyttöä.

Versiohuomautus: Tämän opetusohjelman koodi kohdistuu TensorFlow 1.x -graafi-APIin. TensorFlow 2.x:ssä sama komentosarja suoritetaan edelleen import tensorflow.compat.v1 as tf plus tf.disable_v2_behavior(), koska paikkamerkit, istunnot ja rnn_cell-moduuli sijaitsevat nyt -kohdassa tf.compat.v1Idiomaattinen 2.x-vastine on tf.keras.layers.SimpleRNN.

import numpy as np
import tensorflow as tf
n_inputs = 4
n_neurons = 6
n_timesteps = 2
The data is a sequence of a number from 0 to 9 and divided into three batches of data.
## Data 
X_batch = np.array([
        [[0, 1, 2, 5], [9, 8, 7, 4]], # Batch 1
        [[3, 4, 5, 2], [0, 0, 0, 0]], # Batch 2
        [[6, 7, 8, 5], [6, 5, 4, 2]], # Batch 3
    ])

Voimme rakentaa verkon käyttämällä paikkamerkkiä datalle, toistuvalle vaiheelle ja ulostulolle.

Määritä tiedoille paikkamerkki

X = tf.placeholder(tf.float32, [None, n_timesteps, n_inputs])

Tässä:

  • Ei mitään: Tuntematon ja kestää erän koon
  • n_timesteps: Kuinka monta kertaa verkko lähettää ulostulon takaisin neuroniin
  • n_inputs: Syötteiden lukumäärä erää kohti

Määritä toistuva verkko

Kuten yllä olevassa kuvassa mainittiin, verkko koostuu kuudesta neuronista. Verkko laskee kahden pisteen tuotteen:

  • Syötä tiedot ensimmäisellä painosarjalla (eli 6: yhtä suuri kuin neuronien lukumäärä)
  • Edellinen tuloste toisella painotusjoukolla (eli 6: vastaa tulosteiden lukumäärää)

Huomaa, että ensimmäisen myötäkytkennän aikana edellisen lähdön arvot ovat nollia, koska arvoja ei ole saatavilla.

RNN:n luomisobjekti on tf.contrib.rnn.BasicRNNCell argumentilla num_units, joka määrittää syötteiden määrän

basic_cell = tf.contrib.rnn.BasicRNNCell(num_units=n_neurons)

Nyt kun verkko on määritetty, voit laskea lähdöt ja tilat

outputs, states = tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32)

Tämä objekti käyttää sisäistä silmukkaa kertomaan matriisit sopivan määrän kertoja.

Huomaa, että rekurrenttineuroni on funktio kaikista edellisten aika-askeleiden syötteistä. Näin verkko rakentaa oman muistinsa. Edellisen ajankohdan tieto voi levitä tulevaisuudessa. Tämä on rekurrenttineuraaliverkon taika.

## Define the shape of the tensor
X = tf.placeholder(tf.float32, [None, n_timesteps, n_inputs])
## Define the network
basic_cell = tf.contrib.rnn.BasicRNNCell(num_units=n_neurons)
outputs, states = tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32)
init = tf.global_variables_initializer()
init = tf.global_variables_initializer()
with tf.Session() as sess:
    init.run()
    outputs_val = outputs.eval(feed_dict={X: X_batch})
print(states.eval(feed_dict={X: X_batch}))
[[ 0.38941205 -0.9980438   0.99750966  0.7892596   0.9978241   0.9999997 ]
 [ 0.61096436  0.7255889   0.82977575 -0.88226104  0.29261455 -0.15597084]
 [ 0.62091285 -0.87023467  0.99729395 -0.58261937  0.9811445   0.99969864]]

Selvennyksen vuoksi tulostat edellisen tilan arvot. Yllä tulostettu tuloste näyttää edellisen tilan tulosteen. Nyt tulosta kaikki tulosteet, voit huomata, että tilat ovat kunkin erän edellisiä tulosteita. Eli edellinen tuloste sisältää tiedot koko sekvenssistä.

print(outputs_val)    
print(outputs_val.shape)    
[[[-0.75934666 -0.99537754  0.9735819  -0.9722234  -0.14234993
   -0.9984044 ]
  [ 0.99975264 -0.9983206   0.9999993  -1.         -0.9997506
   -1.        ]]

 [[ 0.97486496 -0.98773265  0.9969686  -0.99950117 -0.7092863
   -0.99998885]
  [ 0.9326837   0.2673438   0.2808514  -0.7535883  -0.43337247
    0.5700631 ]]

 [[ 0.99628735 -0.9998728   0.99999213 -0.99999976 -0.9884324
   -1.        ]
  [ 0.99962527 -0.9467421   0.9997403  -0.99999714 -0.99929446
   -0.9999795 ]]]
(3, 2, 6)

Alla oleva annotoitu näkymä pilkkoo saman tulostetun tensorin erä erältä.

Annotoitu RNN-lähtötensori, joka merkitsee kolme erää, kuusi neuronilähtöä ja (3, 2, 6) -muodon

Tulosteen muoto on (3, 2, 6):

  • 3: Erien lukumäärä
  • 2: Aikavaiheen numero
  • 6: Hermosolujen lukumäärä

Toistuvan hermoverkon optimointi on identtinen perinteisen hermoverkon kanssa. Näet yksityiskohtaisemmin kuinka optimoida koodi tämän toistuvan hermoverkon opetusohjelman seuraavassa osassa.

RNN:n sovellukset

RNN:llä on useita käyttötarkoituksia, varsinkin kun on kyse tulevaisuuden ennustamisesta. Rahoitusalalla RNN:stä voi olla apua osakekurssien tai osakemarkkinoiden suunnan (eli positiivisen tai negatiivisen) merkkien ennustamisessa.

RNN on hyödyllinen autonomiselle autolle, koska se voi välttää auto-onnettomuuden ennakoimalla ajoneuvon liikeradan.

RNN:tä käytetään laajalti tekstianalyysissä, kuvien tekstityksissä, tunneanalyysissä ja konekäännöksissä. Esimerkiksi elokuva-arvostelun avulla voidaan ymmärtää tunnetta, jonka katsoja koki elokuvan katsomisen jälkeen. Tämän tehtävän automatisointi on erittäin hyödyllistä, kun elokuvayhtiöllä ei ole tarpeeksi aikaa arvioida, merkitä, yhdistää ja analysoida arvosteluja. Kone pystyy suorittamaan työn korkeammalla tarkkuudella.

RNN:n rajoitukset

Teoriassa RNN:n oletetaan kuljettavan tietoa aikojaan. On kuitenkin melko haastavaa levittää kaikkea tätä tietoa, kun aikavaihe on liian pitkä. Kun verkossa on liian monta syvää kerrosta, siitä tulee kouluttamaton. Tätä ongelmaa kutsutaan: häviävä kaltevuusongelma. Jos muistat, hermoverkko päivittää painon gradientin laskeutumisalgoritmin avulla. Gradientit pienenevät, kun verkko etenee alemmille tasoille.

Yhteenvetona voidaan todeta, että gradientit pysyvät vakioina, mikä tarkoittaa, että parantamiselle ei ole tilaa. Malli oppii gradientin muutoksesta; tämä muutos vaikuttaa verkon tuotokseen. Jos gradientin ero on kuitenkin liian pieni (eli painot muuttuvat vähän), verkko ei voi oppia mitään, joten tuotoskin muuttuu. Siksi verkko, joka kohtaa häviävän gradientin ongelman, ei voi konvergoitua kohti hyvää ratkaisua.

LSTM:n parannus

Kolme tutkijaa, Hochreiter, Schmidhuber ja Bengio, paransivat RNN:ää arkkitehtuurilla nimeltä Long Short-Term Memory (LSTM), jotta ratkaisisi RNN:n kohtaaman mahdollisen katoavan gradientin ongelman. Lyhyesti sanottuna LSTM tarjoaa verkolle olennaista tietoa menneisyydestä lähiaikoihin. Laite käyttää parempaa arkkitehtuuria tiedon valitsemiseen ja siirtämiseen takaisin myöhempään aikaan.

LSTM-arkkitehtuuri on saatavilla TensorFlow'ssa, tf.contrib.rnn.LSTMCell. LSTM ei kuulu tutoriaalin piiriin. Voit katsoa virallisen dokumentointi lisätietoja

TensorFlow 2.x:ssä kyseinen solu saavutetaan muodossa tf.compat.v1.nn.rnn_cell.LSTMCell, kun taas uusi koodi normaalisti käyttää tf.keras.layers.LSTM tai sytytinportilla varustettu tf.keras.layers.GRU, joka saavuttaa vertailukelpoisen tarkkuuden vähemmillä parametreilla.

RNN aikasarjassa

Tässä TensorFlow RNN -tutoriaalissa käytät RNN:ää aikasarjadatan kanssa. Aikasarjat ovat riippuvaisia ​​aikaisemmasta ajasta, mikä tarkoittaa, että menneet arvot sisältävät olennaista tietoa, josta verkko voi oppia. Aikasarjaennusteen ideana on arvioida sarjan tuleva arvo, esimerkiksi osakekurssi, lämpötila, BKT ja niin edelleen.

Keras RNN:n ja aikasarjojen tietojen valmistelu voi olla hieman hankalaa. Ensinnäkin tavoitteena on ennustaa sarjan seuraava arvo, mikä tarkoittaa, että käytät aiempia tietoja arvon estimoimiseen kohdassa t + 1. Tunniste on yhtä suuri kuin syöttösekvenssi ja siirretty jakso eteenpäin. Toiseksi syötteiden määräksi asetetaan 1, eli yksi havainto kerrallaan. Lopuksi aikaaskel on yhtä suuri kuin numeerisen arvon sekvenssi. Jos esimerkiksi asetat aikaaskeleeksi 10, syöttösekvenssi palauttaa kymmenen kertaa peräkkäin.

Katso alla olevaa kaaviota, olemme esittäneet aikasarjadataa vasemmalla ja kuvitteellista syöttösekvenssiä oikealla. Luot funktion, joka palauttaa tietojoukon satunnaisella arvolla jokaiselle päivälle tammikuusta 2001 joulukuuhun 2016

# To plot pretty figures
%matplotlib inline
import matplotlib
import matplotlib.pyplot as plt
import pandas as pd
def create_ts(start = '2001', n = 201, freq = 'M'):
    rng = pd.date_range(start=start, periods=n, freq=freq)
    ts = pd.Series(np.random.uniform(-18, 18, size=len(rng)), rng).cumsum()
    return ts
ts= create_ts(start = '2001', n = 192, freq = 'M')
ts.tail(5)

ulostulo

2016-08-31    -93.459631
2016-09-30    -95.264791
2016-10-31    -95.551935
2016-11-30   -105.879611
2016-12-31   -123.729319
Freq: M, dtype: float64
ts = create_ts(start = '2001', n = 222)

# Left
plt.figure(figsize=(11,4))
plt.subplot(121)
plt.plot(ts.index, ts)
plt.plot(ts.index[90:100], ts[90:100], "b-", linewidth=3, label="A training instance")
plt.title("A time series (generated)", fontsize=14)

# Right
plt.subplot(122)
plt.title("A training instance", fontsize=14)
plt.plot(ts.index[90:100], ts[90:100], "b-", markersize=8, label="instance")
plt.plot(ts.index[91:101], ts[91:101], "bo", markersize=10, label="target", markerfacecolor='red')
plt.legend(loc="upper left")
plt.xlabel("Time")

plt.show()

Vasemmalla generoitu aikasarja ja oikealla kymmenen askeleen harjoitusinstanssi siirretyillä tavoitteilla

Kaavion oikea puoli näyttää kaikki aikasarjat. Se alkoi vuodesta 2001 ja päättyy vuoteen 2019. Kaikkien verkkoon syötettyjen tietojen syöttäminen ei ole järkevää, vaan sinun on luotava erä tietoja, joiden pituus on yhtä suuri kuin aika-askel. Tämä erä on X-muuttuja. Y-muuttuja on sama kuin X, mutta siirretty yhdellä jaksolla (eli haluat ennustaa ajan t+1).

Molemmilla vektoreilla on sama pituus. Näet sen yllä olevan kaavion oikealla puolella. Viiva edustaa X-syötteen kymmentä arvoa, kun taas punaiset pisteet ovat tunnisteen Y kymmentä arvoa. Huomaa, että tarra alkaa yhden pisteen X:n edellä ja päättyy yhden pisteen jälkeen.

Rakenna RNN ennustaaksesi aikasarjan TensorFlow'ssa

Nyt tässä RNN-koulutuksessa on aika rakentaa ensimmäinen RNN ennustaaksesi yllä olevan sarjan. Sinun on määritettävä mallille joitain hyperparametreja (mallin parametrit, eli neuronien lukumäärä jne.):

  • Tulojen määrä: 1
  • Aikaaskel (ikkunat aikasarjassa): 10
  • Hermosolujen lukumäärä: 120
  • Tulosteiden määrä: 1

Verkkosi oppii 10 päivän sekvenssistä ja sisältää 120 toistuvaa neuronia. Syötät mallille yhden syötteen, eli yhden päivän. Voit vapaasti muuttaa arvoja nähdäksesi, paraniko malli.

Ennen mallin rakentamista sinun on jaettava datajoukko kahteen osaan: junajoukkoon ja testijoukkoon. Täydessä datajoukossa on 222 datapistettä; käytät ensimmäistä 201 pistettä mallin kouluttamiseen ja viimeisiä 21 pistettä mallin testaamiseen.

Kun olet määritellyt junan ja testijoukon, sinun on luotava objekti, joka sisältää erät. Näissä erissä on X- ja Y-arvot. Muista, että X-arvot ovat yhden jaksoa jäljessä. Siksi käytät ensimmäisiä 200 havaintoa ja aika-askel on 10. X_batches-objektin tulisi sisältää 20 erää, joiden koko on 10*1. y_batches-objektilla on sama muoto kuin X_batches-objektilla, mutta yksi jakso edellä.

Vaihe 1) Luo juna ja testaa

Ensinnäkin muutat sarjan a nuhjuinen joukko; sitten määrität ikkunat (eli kuinka monta kertaa verkko oppii), syötteiden, lähdön ja junajoukon koon alla olevan TensorFlow RNN -esimerkin mukaisesti.

series = np.array(ts)
n_windows = 20   
n_input =  1
n_output = 1
size_train = 201

Sen jälkeen jaat taulukon kahdeksi tietojoukoksi.

## Split data
train = series[:size_train]
test = series[size_train:]
print(train.shape, test.shape)
(201,) (21,)

Vaihe 2) Luo funktio palauttamaan X_batches ja y_batches

Helpottaaksesi voit luoda funktion, joka palauttaa kaksi erilaista taulukkoa, yhden X_batchesille ja toisen y_batchesille.

Kirjoitetaan RNN TensorFlow -funktio eräiden muodostamiseksi.

Huomaa, että X erät ovat yhden jakson viiveellä (otamme arvon t-1). Funktion tulosteen tulee olla kolmiulotteinen. Ensimmäiset mitat vastaavat erien määrää, toinen ikkunoiden kokoa ja viimeinen syötteiden lukumäärää.

Hankala osa on valita datapisteet oikein. X-datapisteille valitset havainnot välillä t = 1 - t =200, kun taas Y-datapisteelle palautat havainnot arvosta t = 2 arvoon 201. Kun sinulla on oikeat datapisteet, on helppo muotoilla uudelleen. sarja.

Jotta voit rakentaa objektin erien kanssa, sinun on jaettava tietojoukko kymmeneen yhtä pitkäksi eräksi (eli 20). Voit käyttää uudelleenmuotoilumenetelmää ja ohittaa -1, jotta sarja on samanlainen kuin eräkoko. Arvo 20 on havaintojen määrä erää kohti ja 1 on syötteiden lukumäärä.

Sinun on tehtävä sama vaihe, mutta etikettiä varten.

Huomaa, että sinun on siirrettävä dataa ennusteiden määrän mukaan. Jos esimerkiksi haluat ennustaa yhden ajan eteenpäin, siirrä sarjaa yhdellä. Jos haluat ennustaa kaksi päivää eteenpäin, siirrä dataa kahdella.

x_data = train[:size_train-1]: Select all the training instance minus one day
X_batches = x_data.reshape(-1, windows, input): create the right shape for the batch e.g (10, 20, 1)
def create_batches(df, windows, input, output):
    ## Create X         
        x_data = train[:size_train-1] # Select the data
        X_batches = x_data.reshape(-1, windows, input)  # Reshape the data 
    ## Create y
        y_data = train[n_output:size_train]
        y_batches = y_data.reshape(-1, windows, output)
        return X_batches, y_batches

Nyt kun funktio on määritetty, voit kutsua sitä luodaksesi erät alla olevan RNN-esimerkin mukaisesti.

X_batches, y_batches = create_batches(df = train,
                                      windows = n_windows,
                                      input = n_input,
                                      output = n_output)

Voit tulostaa muodon varmistaaksesi, että mitat ovat oikein.

print(X_batches.shape, y_batches.shape)
(10, 20, 1) (10, 20, 1)

Sinun on luotava testisarja, jossa on vain yksi tietoerä ja 20 havaintoa.

Huomaa, että ennustat päivistä toiseen, se tarkoittaa, että toinen ennustettu arvo perustuu testitietojoukon ensimmäisen päivän todelliseen arvoon (t+1). Itse asiassa todellinen arvo tiedetään.

Jos haluat ennustaa t+2 (eli kaksi päivää eteenpäin), sinun on käytettävä ennustettua arvoa t+1; jos aiot ennustaa t+3 (kolme päivää eteenpäin), sinun on käytettävä ennustettua arvoa t+1 ja t+2. On järkevää, että on vaikea ennustaa tarkasti t+n päivää eteenpäin.

X_test, y_test = create_batches(df = test, windows = 20,input = 1, output = 1)
print(X_test.shape, y_test.shape)
(10, 20, 1) (10, 20, 1)

Selvä, eräkokosi on valmis, voit rakentaa RNN-arkkitehtuurin. Muista, että sinulla on 120 toistuvaa neuronia.

Vaihe 3) Rakenna malli

Mallin luomiseksi sinun on määritettävä kolme osaa:

  1. Muuttuja tensoreiden kanssa
  2. RNN
  3. Häviö ja optimointi

Vaihe 3.1) Muuttujat

Sinun on määritettävä X- ja y-muuttujat sopivalla muodolla. Tämä vaihe on triviaali. Tensorilla on sama ulottuvuus kuin objekteilla X_batches ja y_batches.

Esimerkiksi tensori X on paikkamerkki (katso tutoriaali aiheesta TensorFlow-johdanto virkistääksesi mieltäsi muuttujamäärityksestä) on kolme ulottuvuutta:

  • Huomautus: erän koko
  • n_windows: Ikkunoiden pituus eli kuinka monta kertaa malli katsoo taaksepäin
  • n_input: Tulon määrä

Tulos on:

tf.placeholder(tf.float32, [None, n_windows, n_input])
## 1. Construct the tensors
X = tf.placeholder(tf.float32, [None, n_windows, n_input])   
y = tf.placeholder(tf.float32, [None, n_windows, n_output])

Vaihe 3.2) Luo RNN

Tämän RNN TensorFlow -esimerkin toisessa osassa sinun on määritettävä verkon arkkitehtuuri. Kuten ennenkin, käytät TensorFlow-estimaattorin objektia BasicRNNCell ja dynamic_rnn.

## 2. create the model
basic_cell = tf.contrib.rnn.BasicRNNCell(num_units=r_neuron, activation=tf.nn.relu)   
rnn_output, states = tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32)   

Seuraava osa on hieman hankalampi, mutta mahdollistaa nopeamman laskennan. Sinun on muutettava ajon tulos tiheäksi kerrokseksi ja muutettava se sitten uudelleen niin, että sillä on sama mitta kuin tulolla.

stacked_rnn_output = tf.reshape(rnn_output, [-1, r_neuron])          
stacked_outputs = tf.layers.dense(stacked_rnn_output, n_output)       
outputs = tf.reshape(stacked_outputs, [-1, n_windows, n_output])  

Vaihe 3.3) Luo menetys ja optimointi

Mallin optimointi riippuu suoritettavasta tehtävästä. Edellisessä opetusohjelmassa aiheesta CNN, tavoitteesi oli luokitella kuvia, tässä RNN-tutoriaalissa tavoite on hieman erilainen. Sinua pyydetään tekemään ennuste jatkuvalle muuttujalle verrattuna luokkaan.

Tämä ero on tärkeä, koska se muuttaa optimointiongelman. Jatkuvan muuttujan optimointiongelma on minimoida keskineliövirhe. Näiden mittareiden muodostamiseksi TF:ssä voit käyttää:

tf.reduce_sum(tf.square(ulostulot – y))

Loppuosa RNN-koodista on sama kuin ennen; käytät Adam-optimointiohjelmaa häviön vähentämiseksi (eli MSE):

tf.train.AdamOptimizer(learning_rate=oppimisnopeus)

optimoija.minimize(tappio)

Siinä kaikki, voit pakata kaiken yhteen ja mallisi on valmis harjoitteluun.

tf.reset_default_graph()
r_neuron = 120    

## 1. Construct the tensors
X = tf.placeholder(tf.float32, [None, n_windows, n_input])   
y = tf.placeholder(tf.float32, [None, n_windows, n_output])

## 2. create the model
basic_cell = tf.contrib.rnn.BasicRNNCell(num_units=r_neuron, activation=tf.nn.relu)   
rnn_output, states = tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32)              

stacked_rnn_output = tf.reshape(rnn_output, [-1, r_neuron])          
stacked_outputs = tf.layers.dense(stacked_rnn_output, n_output)       
outputs = tf.reshape(stacked_outputs, [-1, n_windows, n_output])   

## 3. Loss + optimization
learning_rate = 0.001  
 
loss = tf.reduce_sum(tf.square(outputs - y))    
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)         
training_op = optimizer.minimize(loss)                                          

init = tf.global_variables_initializer() 

Harjoittelet mallia käyttämällä 1500 jaksoa ja tulostat häviön joka 150. iteraatio. Kun malli on koulutettu, arvioit mallin testijoukossa ja luot objektin, joka sisältää ennusteet alla olevan Toistuvan hermoverkon esimerkin mukaisesti.

iteration = 1500 

with tf.Session() as sess:
    init.run()
    for iters in range(iteration):
        sess.run(training_op, feed_dict={X: X_batches, y: y_batches})
        if iters % 150 == 0:
            mse = loss.eval(feed_dict={X: X_batches, y: y_batches})
            print(iters, "\tMSE:", mse)
    
    y_pred = sess.run(outputs, feed_dict={X: X_test})
0 	MSE: 502893.34
150 	MSE: 13839.129
300 	MSE: 3964.835
450 	MSE: 2619.885
600 	MSE: 2418.772
750 	MSE: 2110.5923
900 	MSE: 1887.9644
1050 	MSE: 1747.1377
1200 	MSE: 1556.3398
1350 	MSE: 1384.6113

Viimeinkin tässä RNN Deep Learning -opetusohjelmassa voit piirtää sarjan todellisen arvon ennustetulla arvolla. Jos malliasi korjataan, ennustetut arvot tulee laittaa todellisten arvojen päälle.

Kuten näet, mallissa on parantamisen varaa. Voit muuttaa hyperparametreja, kuten ikkunoita, erän kokoa tai toistuvien neuronien määrää.

plt.title("Forecast vs Actual", fontsize=14)
plt.plot(pd.Series(np.ravel(y_test)), "bo", markersize=8, label="Actual", color='green')
plt.plot(pd.Series(np.ravel(y_pred)), "r.", markersize=8, label="Forecast", color='red')
plt.legend(loc="lower left")
plt.xlabel("Time")

plt.show()

Ennusteen ja todellisen tilan kuvaaja, jossa todelliset pisteet ovat vihreät ja ennustetut pisteet punaiset

Ennuste vs todellinen

UKK

Aloita ikkunalla, joka kattaa yhden täyden kuvion syklin, ja hienosäädä sitä sitten. Pidemmät ikkunat tallentavat enemmän kontekstia, mutta hidastavat koulutusta ja pahentavat gradientin hajoamista. Kymmenen askelta toimii tässä päivittäisissä sarjoissa; viikoittainen kausivaihtelu vaatii yleensä enemmän.

Kyllä, shim-välilehden kanssa. Korvaa import-komento tensorflow.compat.v1-komennolla ja kutsu disable_v2_behavior()-funktiota, koska paikkamerkit, istunnot ja rnn_cell siirtyivät compat-nimiavaruuden alle. Tuore TensorFlow projektien tulisi käyttää sen sijaan tf.keras.layers.SimpleRNN:ää.

Tekoälyavustajat ehdottavat ikkunakokoja, havaitsevat muotojen epäsuhtaisuuden ennen suoritusta ja luonnostelevat datan latauskoodia skeemasta. Ne tiivistävät toistuvaa mallinnusta hallitsevan yritys- ja erehdyssilmukan, vaikka lopulliset hyperparametrivalinnat vaativat vielä validoinnin pimitetyllä datalla.

Copilot käsittelee toistuvat scaffolding-tehtävät hyvin: istuntolohkot, syötesanakirjat ja periodisesti hävikkitulostuksen. Tensorimuodot ja otsikon siirtymä ovat edelleen riskialttiita osia, joten varmista aina erän mitat itse ennen kuin luotat luotettuun silmukkaan.

Toistuvat tasot odottavat (erä, aika-askel, ominaisuus). Muotoilu muuttamalla (-1, ikkunat, syöte) kertoo kehykselle, kuinka monta sekvenssiä on olemassa, kuinka kauas taaksepäin kukin niistä katsoo ja kuinka monta arvoa saapuu per askel. Puuttuva ulottuvuus aiheuttaa järjestysvirheen.

LSTM käyttää kolmea porttia ja erillistä solutilaa; GRU yhdistää unohdus- ja syöttöportit ja poistaa solutilan. GRU harjoittelee nopeammin vähemmillä parametreilla, kun taas LSTM usein päihittää erittäin pitkiä riippuvuuksia.

Jatkuvat ennusteet minimoivat keskineliövirheen, kuten tämä läpikäynti tekee neliöjäännösten reduce_sum-funktiolla. Sekvenssien luokittelu, kuten mielipidetunnisteet tai kuvatehtävät, joita käsitellään tässä osiossa CNN opetusohjelmassa käytetään ristientropiaa.

Muuntajat hallitsevat kielityötä, koska huomio rinnastuu sekvenssin läpi. Rekurrenttimallit pysyvät kilpailukykyisinä suoratoistettavien signaalien, lyhyiden yksimuuttujaennusteiden ja vähän muistia käyttävien laitteiden osalta, joissa yhden askeleen kerrallaan käsittely on etu eikä pullonkaula.

Tiivistä tämä viesti seuraavasti: