RNN (Recurrent Neural Network) Handledning: TensorFlow Exempel

⚡ Smart sammanfattning

Återkommande neurala nätverk lägger till ett minnestillstånd till vanliga neuroner och matar varje utdata tillbaka som nästa indata så att modellen kan lära sig av ordningen. Den här genomgången bygger ett minnestillstånd i TensorFlow och prognostiserar en tidsserie.

  • 🔘 Minnesstatus: Varje återkommande neuron tar emot den tidigare utsignalen tillsammans med ny insignal, vilket är det som ger nätverket dess tidsmässiga medvetenhet.
  • ☑️ Utdataform: En körning av leksaksnätverket returnerar en (3, 2, 6) tensor: batcher, tidssteg och neuroner i den ordningen.
  • Batchningsregel: Tidsserieingångar omformas till tre dimensioner och etikettmatrisen är samma serie förskjuten en period framåt.
  • 🧪 Modellskelett: Platshållare, en BasicRNNCell insvept i dynamic_rnn, en tät projektion, sedan medelkvadratfel med en Adam-optimerare.
  • 🛠️ Träningspass: 1 500 epoker på 120 återkommande neuroner minskar förlusten från 502 893 till ungefär 1 385.
  • 📉 Känd gräns: Långa sekvenser utlöser problemet med försvinnande gradienter, vilket LSTM och gated-varianter utformades för att lösa.

RNN Återkommande neuralt nätverk

Varför behöver vi ett återkommande neuralt nätverk (RNN)?

Recurrent Neural Network (RNN) låter dig modellera minnesenheter för att bevara data och modellera kortsiktiga beroenden. Det används också i tidsserieprognoser för identifiering av datakorrelationer och mönster. Det hjälper också till att producera prediktiva resultat för sekventiell data genom att leverera liknande beteende som en mänsklig hjärna.

Strukturen för en Artificiellt neuralt nätverk är relativt enkelt och handlar huvudsakligen om matrismultiplikation. Under det första steget multipliceras ingångarna med initialt slumpmässiga vikter och bias, transformeras med en aktiveringsfunktion och utdatavärdena används för att göra en förutsägelse. Detta steg ger en uppfattning om hur långt nätverket är från verkligheten.

Det mått som används är förlusten. Ju högre förlustfunktion, desto dummare är modellen. För att förbättra kunskapen om nätverket krävs viss optimering genom att justera nätets vikter. Den stokastiska gradientnedgången är metoden som används för att ändra vikternas värden i rätt riktning. När justeringen är gjord kan nätverket använda ytterligare en sats data för att testa sin nya kunskap.

Felet är lyckligtvis lägre än tidigare, men inte tillräckligt litet. Optimeringssteget görs iterativt tills felet minimeras, dvs. ingen mer information kan utläsas.tracted.

Problemet med denna typ av modell är att den inte har något minne. Det betyder att ingången och utgången är oberoende. Modellen bryr sig med andra ord inte om vad som kom innan. Det väcker vissa frågor när du behöver förutsäga tidsserier eller meningar eftersom nätverket behöver ha information om historiska data eller tidigare ord.

För att lösa detta problem har en ny typ av arkitektur utvecklats: Recurrent Neural Network (RNN härefter)

Vad är ett återkommande neuralt nätverk (RNN)?

Ett återkommande neuralt nätverk (RNN) är en klass av artificiella neurala nätverk där kopplingen mellan olika noder bildar en riktad graf för att ge ett temporalt dynamiskt beteende. Det hjälper till att modellera sekventiell data som härrör från feedforward-nätverk. Det fungerar på liknande sätt som mänskliga hjärnor för att leverera prediktiva resultat.

Ett återkommande neuralt nätverk ser ganska likt ett traditionellt neuralt nätverk förutom att ett minnestillstånd läggs till neuronerna. Beräkningen för att inkludera ett minne är enkel.

Tänk dig en enkel modell med endast en neuron som matas av en databatch. I ett traditionellt neuralt nätverk producerar modellen utdata genom att multiplicera indata med vikten och aktiveringsfunktionen. Med ett RNN skickas denna utdata tillbaka till sig själv ett antal gånger. Vi kallar det. tidssteg den tid som utdata blir indata för nästa matrismultiplikation.

På bilden nedan kan du till exempel se att nätverket består av en neuron. Nätverket beräknar matrismultiplikationen mellan ingången och vikten och lägger till icke-linjäritet med aktiveringsfunktionen. Det blir utgången vid t-1. Denna utsignal är ingången för den andra matrismultiplikationen.

Enskild återkommande neuron som skickar sin utgång vid t-1 tillbaka som ingång för nästa multiplikation

Återkommande neurala nätverk (RNN)

Nedan kodar vi en enkel RNN i TensorFlow för att förstå steget och även formen på utdata.

Nätverket består av:

  • Fyra ingångar
  • Sex neuroner
  • 2-gångssteg

Nätverket kommer att fortsätta som bilden nedan visar.

Utrullad RNN med fyra ingångar, sex neuroner och två tidssteg

Nätverket kallas "återkommande" eftersom det utför samma operation i varje aktiveringsruta. Nätverket beräknade vikterna av ingångarna och den tidigare utsignalen innan för att använda en aktiveringsfunktion.

Versionsnotering: Koden i den här handledningen riktar sig mot TensorFlow 1.x graf-API. På TensorFlow 2.x körs samma skript fortfarande efter import tensorflow.compat.v1 as tf plus tf.disable_v2_behavior(), eftersom platshållare, sessioner och rnn_cell-modulen nu finns under tf.compat.v1Den idiomatiska 2.x-ekvivalenten är 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
    ])

Vi kan bygga nätverket med en platshållare för data, det återkommande steget och utdata.

Definiera platshållaren för data

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

Här:

  • Ingen: Okänd och kommer att ta storleken på batchen
  • n_timesteps: Antal gånger nätverket kommer att skicka utdata tillbaka till neuronen
  • n_inputs: Antal input per batch

Definiera det återkommande nätverket

Som nämnts i bilden ovan består nätverket av 6 neuroner. Nätverket kommer att beräkna produkt med två punkter:

  • Indata med den första uppsättningen vikter (dvs 6: lika med antalet neuroner)
  • Föregående utdata med en andra uppsättning vikter (dvs. 6: motsvarande antalet utdata)

Observera att, under den första feedforwarden, är värdena för föregående utdata lika med nollor eftersom vi inte har något tillgängligt värde.

Objektet för att bygga ett RNN är tf.contrib.rnn.BasicRNNCell med argumentet num_units för att definiera antalet indata

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

Nu när nätverket är definierat kan du beräkna utdata och tillstånd

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

Detta objekt använder en intern loop för att multiplicera matriserna ett lämpligt antal gånger.

Observera att den återkommande neuronen är en funktion av alla insignaler från föregående tidssteg. Det är så nätverket bygger sitt eget minne. Informationen från föregående tidpunkt kan fortplanta sig i framtida tid. Detta är magin med det återkommande neurala nätverket.

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

För att förklara detta skriver du ut värdena för det föregående tillståndet. Utdata som skrivs ut ovan visar utdata från det senaste tillståndet. Skriv nu ut all utdata, du kan se att tillstånden är den föregående utdatan för varje batch. Det vill säga, den föregående utdatan innehåller information om hela sekvensen.

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)

Den kommenterade vyn nedan delar upp samma utskrivna tensor batch för batch.

Annoterad RNN-utgångstensor som märker de tre batcherna, de sex neuronutgångarna och (3, 2, 6)-formen

Utgången har formen av (3, 2, 6):

  • 3: Antal partier
  • 2: Tidsstegets nummer
  • 6: Antal neuroner

Optimeringen av ett återkommande neuralt nätverk är identiskt med ett traditionellt neuralt nätverk. Du kommer att se mer i detalj hur du kodar optimering i nästa del av denna självstudie för återkommande neurala nätverk.

Tillämpningar av RNN

RNN har flera användningsområden, särskilt när det gäller att förutsäga framtiden. Inom finansbranschen kan RNN vara till hjälp för att förutsäga aktiekurser eller tecken på börsriktningen (dvs. positiv eller negativ).

RNN är användbart för en autonom bil eftersom det kan undvika en bilolycka genom att förutse fordonets bana.

RNN används flitigt inom textanalys, bildtextning, sentimentanalys och maskinöversättning. Till exempel kan man använda en filmrecension för att förstå känslan åskådaren upplevde efter att ha sett filmen. Att automatisera denna uppgift är mycket användbart när filmbolaget inte har tillräckligt med tid att granska, märka, konsolidera och analysera recensionerna. Maskinen kan göra jobbet med högre noggrannhet.

Begränsningar för RNN

I teorin är RNN tänkt att bära informationen upp till tider. Det är dock ganska utmanande att sprida all denna information när tidssteget är för långt. När ett nätverk har för många djupa lager blir det oträningsbart. Detta problem kallas: försvinnande gradientproblem. Om du kommer ihåg uppdaterar det neurala nätverket vikten med algoritmen för gradientnedstigning. Gradienterna blir mindre när nätverket går ner till lägre lager.

Sammanfattningsvis förblir gradienterna konstanta, vilket innebär att det inte finns utrymme för förbättring. Modellen lär sig av en förändring i gradienten; denna förändring påverkar nätverkets utdata. Men om skillnaden i gradienten är för liten (dvs. vikterna ändras lite) kan nätverket inte lära sig någonting och därmed inte utdata. Därför kan ett nätverk som står inför ett problem med försvinnande gradienter inte konvergera mot en bra lösning.

Förbättring LSTM

För att övervinna det potentiella problemet med försvinnande gradienter som RNN står inför, förbättrade tre forskare, Hochreiter, Schmidhuber och Bengio, RNN med en arkitektur som kallas Long Short-Term Memory (LSTM). Kortfattat förser LSTM nätverket med relevant information från det förflutna till en senare tid. Maskinen använder en bättre arkitektur för att välja och föra information tillbaka till en senare tidpunkt.

LSTM-arkitekturen finns tillgänglig i TensorFlow, tf.contrib.rnn.LSTMCell. LSTM omfattas inte av handledningen. Du kan hänvisa till den officiella dokumentation för mer information

På TensorFlow 2.x nås den cellen som tf.compat.v1.nn.rnn_cell.LSTMCell, medan ny kod normalt använder tf.keras.layers.LSTM eller den tändare-grindade tf.keras.layers.GRU, vilket uppnår jämförbar noggrannhet med färre parametrar.

RNN i tidsserier

I den här handledningen för TensorFlow RNN kommer du att använda ett RNN med tidsseriedata. Tidsserier är beroende av tidigare tid, vilket innebär att tidigare värden inkluderar relevant information som nätverket kan lära sig av. Idén bakom tidsserieprognoser är att uppskatta det framtida värdet av en serie, låt oss säga aktiekurs, temperatur, BNP och så vidare.

Dataförberedelsen för Keras RNN och tidsserier kan vara lite knepig. Först och främst är målet att förutsäga nästa värde i serien, vilket innebär att du kommer att använda den tidigare informationen för att uppskatta värdet till t + 1. Etiketten är lika med inmatningssekvensen och flyttas en period framåt. För det andra sätts antalet inmatningar till 1, dvs en observation per gång. Slutligen är tidssteget lika med sekvensen av det numeriska värdet. Om du till exempel ställer in tidssteget till 10 kommer inmatningssekvensen tillbaka tio gånger i följd.

Titta på grafen nedan, vi har representerat tidsseriedata till vänster och en fiktiv inmatningssekvens till höger. Du skapar en funktion för att returnera en datauppsättning med slumpmässigt värde för varje dag från januari 2001 till december 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)

Produktion

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

Genererade tidsserier till vänster och en tiostegsträningsinstans med förskjutna mål till höger

Den högra delen av grafen visar alla serier. Den startade från 2001 och slutar 2019. Det är meningslöst att mata in all data i nätverket, istället behöver du skapa en databatch med en längd som är lika med tidssteget. Denna batch kommer att vara X-variabeln. Y-variabeln är densamma som X men förskjuten med en period (dvs. du vill prognostisera t+1).

Båda vektorerna har samma längd. Du kan se det i den högra delen av grafen ovan. Linjen representerar de tio värdena för X-inmatningen, medan de röda prickarna är de tio värdena för etiketten, Y. Observera att etiketten börjar en period före X och slutar en period efter.

Bygg ett RNN för att förutsäga tidsserier i TensorFlow

Nu i denna RNN-utbildning är det dags att bygga ditt första RNN för att förutsäga serien ovan. Du måste ange några hyperparametrar (modellens parametrar, dvs antal neuroner, etc.) för modellen:

  • Antal ingångar: 1
  • Tidssteg (fönster i tidsserier): 10
  • Antal neuroner: 120
  • Antal utdata: 1

Ditt nätverk kommer att lära sig från en sekvens på 10 dagar och innehålla 120 återkommande neuroner. Du matar modellen med en inmatning, dvs. en dag. Du kan gärna ändra värdena för att se om modellen förbättrades.

Innan du konstruerar modellen måste du dela upp datamängden i en tåguppsättning och en testuppsättning. Hela datamängden har 222 datapunkter; du kommer att använda de första 201 punkterna för att träna modellen och de sista 21 punkterna för att testa din modell.

När du har definierat ett tåg och en testuppsättning måste du skapa ett objekt som innehåller batcherna. I dessa batchar har du X-värden och Y-värden. Kom ihåg att X-värdena är fördröjda med en period. Därför använder du de första 200 observationerna och tidssteget är lika med 10. X_batches-objektet ska innehålla 20 batchar av storleken 10*1. y_batches har samma form som X_batches-objektet men med en period före.

Steg 1) Skapa tåget och testa

Först och främst konverterar du serien till en numpy array; sedan definierar du fönstren (dvs. antalet gånger nätverket kommer att lära sig av), antalet ingångar, utdata och storleken på tågsetet som visas i TensorFlow RNN-exemplet nedan.

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

Efter det delar du helt enkelt upp arrayen i två datamängder.

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

Steg 2) Skapa funktionen för att returnera X_batches och y_batches

För att göra det enklare kan du skapa en funktion som returnerar två olika arrayer, en för X_batches och en för y_batches.

Låt oss skriva en RNN TensorFlow-funktion för att konstruera satserna.

Observera att X-satserna är fördröjda med en period (vi tar värdet t-1). Funktionens utdata ska ha tre dimensioner. De första måtten motsvarar antalet partier, den andra storleken på fönstren och den sista är antalet inmatade.

Det knepiga är att välja datapunkterna korrekt. För X-datapunkterna väljer du observationerna från t = 1 till t =200, medan för Y-datapunkten returnerar du observationerna från t = 2 till 201. När du väl har rätt datapunkter är det enkelt att omforma serien.

För att konstruera objektet med satserna måste du dela upp datasetet i tio satser av samma längd (dvs. 20). Du kan använda omformningsmetoden och skicka -1 så att serien liknar batchstorleken. Värdet 20 är antalet observationer per batch och 1 är antalet indata.

Du måste göra samma steg utom för etiketten.

Observera att du måste förskjuta data till det antal gånger du vill prognostisera. Om du till exempel vill förutspå en tid framåt, förskjuter du serien med 1. Om du vill prognostisera två dagar, förskjuter du data med 2.

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

Nu när funktionen är definierad kan du anropa den för att skapa batcherna som visas i nedanstående RNN-exempel.

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

Du kan skriva ut formen för att se till att måtten är korrekta.

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

Du behöver skapa testsetet med endast en batch data och 20 observationer.

Observera att du prognostiserar dagar efter dagar betyder att det andra förutsagda värdet kommer att baseras på det sanna värdet för den första dagen (t+1) i testdatauppsättningen. Faktum är att det verkliga värdet kommer att vara känt.

Om du vill prognostisera t+2 (dvs två dagar framåt), måste du använda det förutsagda värdet t+1; om du ska förutsäga t+3 (tre dagar framåt), måste du använda det förutsagda värdet t+1 och t+2. Det är logiskt att det är svårt att förutsäga exakt t+n dagar framåt.

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)

Okej, din batchstorlek är klar, du kan bygga RNN-arkitekturen. Kom ihåg att du har 120 återkommande neuroner.

Steg 3) Bygg modellen

För att skapa modellen måste du definiera tre delar:

  1. Variabeln med tensorerna
  2. RNN
  3. Förlusten och optimeringen

Steg 3.1) variabler

Du måste ange X- och y-variablerna med lämplig form. Detta steg är trivialt. Tensorn har samma dimension som objekten X_batches och y_batches.

Till exempel är tensorn X en platshållare (se handledningen på Introduktion till TensorFlow för att fräscha upp ditt sinne om variabeldeklaration) har tre dimensioner:

  • Obs: satsens storlek
  • n_windows: Fönstrens längd, dvs. hur många gånger modellen tittar bakåt
  • n_input: Antal ingångar

Resultatet är:

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

Steg 3.2) Skapa RNN

I den andra delen av detta RNN TensorFlow-exempel måste du definiera nätverkets arkitektur. Som tidigare använder du objektet BasicRNNCell och dynamic_rnn från TensorFlow estimator.

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

Nästa del är lite knepigare men möjliggör snabbare beräkning. Du måste omvandla körutdata till ett tätt lager och sedan konvertera det igen för att ha samma dimension som indata.

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

Steg 3.3) Skapa förlusten och optimering

Modelloptimeringen beror på vilken uppgift du utför. I den föregående handledningen om CNN, ditt mål var att klassificera bilder, i den här RNN-handledningen är målet något annorlunda. Du ombeds att göra en förutsägelse på en kontinuerlig variabel jämfört med en klass.

Denna skillnad är viktig eftersom den kommer att förändra optimeringsproblemet. Optimeringsproblemet för en kontinuerlig variabel är att minimera medelkvadratfelet. För att konstruera dessa mätvärden i TF kan du använda:

tf.reduce_sum(tf.square(utgångar – y))

Resten av RNN-koden är densamma som tidigare; du använder en Adam-optimerare för att minska förlusten (dvs. MSE):

tf.train.AdamOptimizer(learning_rate=learning_rate)

optimizer.minimize(förlust)

Det är allt, du kan packa ihop allt och din modell är redo att träna.

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

Du kommer att träna modellen med 1500 epoker och skriva ut förlusten var 150:e iteration. När modellen är tränad utvärderar du modellen på testsetet och skapar ett objekt som innehåller förutsägelserna som visas i exemplet nedan för återkommande neurala nätverk.

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

Äntligen i denna RNN Deep Learning-handledning kan du plotta det faktiska värdet av serien med det förutsagda värdet. Om din modell är korrigerad bör de förutsagda värdena läggas ovanpå de faktiska värdena.

Som du kan se finns det utrymme för förbättringar i modellen. Det är upp till dig att ändra hyperparametrar som fönster, batchstorlek eller antalet återkommande neuroner.

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

Prognos kontra faktisk plott med gröna faktiska punkter och röda predikterade punkter

Prognos kontra faktisk

Vanliga frågor

Börja med ett fönster som täcker en hel cykel av mönstret och finjustera det sedan. Längre fönster fångar mer kontext men saktar ner träningen och förvärrar gradientavklingningen. Tio steg fungerar för den dagliga serien här; veckovis säsongsvariation kräver vanligtvis mer.

Ja, med en shim. Ersätt importen med tensorflow.compat.v1 och anropa disable_v2_behavior(), eftersom platshållare, sessioner och rnn_cell flyttades under compat-namnrymden. Färskt TensorFlow projekt bör använda tf.keras.layers.SimpleRNN istället.

AI-assistenter föreslår fönsterstorlekar, avvikelser i punktform före en körning och utkastar kod för datainläsning från ett schema. De komprimerar trial-and-error-loopen som dominerar återkommande modellarbete, även om de slutliga hyperparametervalen fortfarande behöver valideras på utelämnad data.

Copilot hanterar repetitiv scaffolding bra: sessionsblock, flödesordböcker och periodisk förlustutskrift. Tensorformer och etikettförskjutning är fortfarande den riskabla delen, så bekräfta alltid batchdimensionerna själv innan du litar på en genererad loop.

Återkommande lager förväntar sig (batch, tidssteg, funktion). Omformningen till (-1, fönster, indata) anger för ramverket hur många sekvenser som finns, hur långt tillbaka varje sekvens ser ut och hur många värden som anländer per steg. En saknad dimension ger upphov till ett rangfel.

LSTM använder tre grindar plus ett separat celltillstånd; GRU slår samman glöm- och ingångsgrindarna och tar bort celltillståndet. GRU tränas snabbare med färre parametrar, medan LSTM ofta ligger i framkant vid mycket långa beroenden.

Kontinuerliga prognoser minimerar medelkvadratfelet, vilket den här genomgången gör med reduce_sum av kvadrerade residualer. Sekvensklassificering, såsom sentimentetiketter eller bilduppgifter som täcks i CNN handledning, använder korsentropi istället.

Transformatorer dominerar språkarbete eftersom uppmärksamhet parallelliseras över en sekvens. Återkommande modeller är fortfarande konkurrenskraftiga för strömmande signaler, korta univariata prognoser och enheter med lågt minne, där bearbetning ett steg i taget är en fördel snarare än en flaskhals.

Sammanfatta detta inlägg med: