Samouczek RNN ​​(rekurencyjna sieć neuronowa): przykład TensorFlow

Dlaczego potrzebujemy rekurencyjnej sieci neuronowej (RNN)?

Rekurencyjna sieć neuronowa (RNN) umożliwia modelowanie jednostek pamięci w celu utrwalania danych i modelowania zależności krótkoterminowych. Jest również stosowany w prognozowaniu szeregów czasowych w celu identyfikacji korelacji i wzorców danych. Pomaga także w uzyskiwaniu wyników predykcyjnych dla danych sekwencyjnych, zapewniając podobne zachowanie jak ludzki mózg.

Struktura sztucznej sieci neuronowej jest stosunkowo prosta i opiera się głównie na mnożeniu macierzy. W pierwszym etapie dane wejściowe są mnożone przez początkowo losowe wagi i obciążenie, przekształcane za pomocą funkcji aktywacji, a wartości wyjściowe są wykorzystywane do przewidywania. Ten krok daje wyobrażenie o tym, jak daleko sieć znajduje się od rzeczywistości.

Zastosowaną metryką jest strata. Im wyższa funkcja straty, tym głupszy model. Aby poprawić wiedzę o sieci, konieczna jest pewna optymalizacja poprzez dostosowanie wag sieci. Metoda stochastycznego spadku gradientu jest stosowana w celu zmiany wartości wag w odpowiednim kierunku. Po dokonaniu dostosowania sieć może użyć kolejnej partii danych do przetestowania swojej nowej wiedzy.

Błąd na szczęście jest mniejszy niż wcześniej, ale nie wystarczająco mały. Etap optymalizacji jest wykonywany iteracyjnie, aż błąd zostanie zminimalizowany, tj. nie będzie można wydobyć więcej informacji.

Problem z tego typu modelem polega na tym, że nie ma on żadnej pamięci. Oznacza to, że wejście i wyjście są niezależne. Innymi słowy, model nie przejmuje się tym, co było wcześniej. Rodzi się pytanie, kiedy trzeba przewidzieć szeregi czasowe lub zdania, ponieważ sieć potrzebuje informacji o danych historycznych lub przeszłych słowach.

Aby przezwyciężyć ten problem, opracowano nowy typ architektury: rekurencyjną sieć neuronową (RNN)

Co to jest rekurencyjna sieć neuronowa (RNN)?

A Powtarzalna sieć neuronowa (RNN) jest klasą Sztuczna sieć neuronowa w którym połączenie między różnymi węzłami tworzy ukierunkowany graf zapewniający tymczasowe zachowanie dynamiczne. Pomaga modelować dane sekwencyjne pochodzące z sieci wyprzedzających. Działa podobnie do ludzkiego mózgu, dostarczając przewidywalne wyniki.

Rekurencyjna sieć neuronowa wygląda całkiem podobnie do tradycyjnej sieci neuronowej, z tą różnicą, że do neuronów dodawany jest stan pamięci. Obliczenia uwzględniające pamięć są proste.

Wyobraź sobie prosty model z tylko jednym neuronem zasilanym partią danych. W tradycyjnej sieci neuronowej model generuje wynik poprzez pomnożenie danych wejściowych przez wagę i funkcję aktywacji. W przypadku RNN dane wyjściowe są wysyłane z powrotem do siebie przez określoną ilość czasu. Nazywamy krok czasu czas, przez jaki wynik staje się wejściem następnego mnożenia macierzy.

Na przykład na poniższym obrazku widać, że sieć składa się z jednego neuronu. Sieć oblicza mnożenie macierzy między wejściem a wagą i dodaje nieliniowość za pomocą funkcji aktywacji. Staje się wyjściem w t-1. Wynik ten jest wejściem drugiego mnożenia macierzy.

Powtarzalna sieć neuronowa (RNN)
Powtarzalna sieć neuronowa (RNN)

Poniżej kodujemy prosty RNN w TensorFlow, aby zrozumieć krok i kształt wyniku.

Sieć składa się z:

  • Cztery wejścia
  • Sześć neuronów
  • 2-krotne kroki

Sieć będzie działać w sposób przedstawiony na poniższym obrazku.

Powtarzalna sieć neuronowa (RNN)

Sieć nazywa się „rekurencyjną”, ponieważ wykonuje tę samą operację w każdym kwadracie aktywacji. Sieć obliczała wagi danych wejściowych i poprzedniego wyjścia przed użyciem funkcji aktywacji.

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

Możemy zbudować sieć z symbolem zastępczym danych, etapem cyklicznym i wynikiem.

  1. Zdefiniuj symbol zastępczy danych
X = tf.placeholder(tf.float32, [None, n_timesteps, n_inputs])

Tutaj:

  • Brak: nieznany i będzie odpowiadał wielkości partii
  • n_timesteps: Ile razy sieć będzie wysyłać dane wyjściowe z powrotem do neuronu
  • n_inputs: Liczba wejść na partię
  1. Zdefiniuj sieć rekurencyjną

Jak widać na powyższym obrazku, sieć składa się z 6 neuronów. Sieć obliczy iloczyn dwukropkowy:

  • Dane wejściowe z pierwszym zestawem wag (tj. 6: równa liczbie neuronów)
  • Poprzednie wyjście z drugim zestawem wag (tj. 6: odpowiadający numerowi wyjścia)

Należy zauważyć, że podczas pierwszego sprzężenia zwrotnego wartości poprzedniego wyjścia są równe zerom, ponieważ nie mamy dostępnej żadnej wartości.

Obiektem do zbudowania RNN jest tf.contrib.rnn.BasicRNNCell z argumentem num_units definiującym liczbę wejść

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

Teraz, gdy sieć jest zdefiniowana, możesz obliczyć wyjścia i stany

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

Obiekt ten wykorzystuje pętlę wewnętrzną do mnożenia macierzy odpowiednią liczbę razy.

Należy zauważyć, że neuron rekurencyjny jest funkcją wszystkich danych wejściowych poprzednich kroków czasowych. W ten sposób sieć buduje własną pamięć. Informacje z poprzedniego czasu mogą być propagowane w przyszłości. Na tym polega magia sieci neuronowej Recurrent

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

Dla celów poglądowych wypisujesz wartości poprzedniego stanu. Wydrukowane powyżej wyjście pokazuje wyjście z ostatniego stanu. Teraz wydrukuj wszystkie dane wyjściowe, możesz zauważyć, że stany są poprzednimi wynikami każdej partii. Oznacza to, że poprzednie wyjście zawiera informację o całej sekwencji

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)

Powtarzalna sieć neuronowa (RNN)

Wynik ma postać (3, 2, 6):

  • 3: Liczba partii
  • 2: Numer kroku czasowego
  • 6: Liczba neuronów

Optymalizacja rekurencyjnej sieci neuronowej jest identyczna jak w przypadku tradycyjnej sieci neuronowej. Bardziej szczegółowo, jak optymalizować kod, zobaczysz w następnej części tego samouczka dotyczącego rekurencyjnej sieci neuronowej.

Zastosowania RNN

RNN ma wiele zastosowań, szczególnie jeśli chodzi o przewidywanie przyszłości. W branży finansowej RNN może być pomocny w przewidywaniu cen akcji lub oznak kierunku rynku akcji (tj. pozytywnego lub negatywnego).

RNN jest przydatny w samochodzie autonomicznym, ponieważ może uniknąć wypadku samochodowego, przewidując trajektorię pojazdu.

RNN jest szeroko stosowany w analizie tekstu, podpisach obrazów, analizie nastrojów i tłumaczeniu maszynowym. Recenzję filmu można na przykład wykorzystać do zrozumienia uczuć, jakie odczuwa widz po obejrzeniu filmu. Automatyzacja tego zadania jest bardzo przydatna, gdy wytwórnia filmowa nie ma wystarczająco dużo czasu na przeglądanie, oznaczanie, konsolidowanie i analizowanie recenzji. Maszyna może wykonać pracę z większą dokładnością.

Ograniczenia RNN

Teoretycznie RNN ma przenosić informacje do czasu. Jednak propagowanie wszystkich tych informacji, gdy krok czasowy jest zbyt długi, jest dość trudne. Kiedy sieć ma zbyt wiele głębokich warstw, staje się niemożliwa do nauczenia. Problem ten nazywa się: znikający problem z gradientem. Jeśli pamiętasz, sieć neuronowa aktualizuje wagę za pomocą algorytmu gradientu opadania. Gradienty stają się mniejsze, gdy sieć przechodzi do niższych warstw.

Podsumowując, gradienty pozostają stałe, co oznacza, że ​​nie ma miejsca na poprawę. Model uczy się na podstawie zmiany gradientu; zmiana ta wpływa na wydajność sieci. Jeśli jednak różnica w gradiencie jest zbyt mała (tj. wagi zmieniają się nieznacznie), sieć nie może się niczego nauczyć, a co za tym idzie, nie może uzyskać wyniku. Dlatego sieć borykająca się z problemem zanikającego gradientu nie może znaleźć dobrego rozwiązania.

Ulepszenie LSTM

Aby przezwyciężyć potencjalny problem zanikającego gradientu, z którym zmaga się RNN, trzej badacze, Hochreiter, Schmidhuber i Bengio, udoskonalili RNN za pomocą architektury zwanej Long Short-Term Memory (LSTM). Krótko mówiąc, LSMT dostarcza sieci istotne informacje z przeszłości do bardziej współczesnych czasów. Maszyna wykorzystuje lepszą architekturę do wybierania i przenoszenia informacji z powrotem do późniejszego czasu.

Architektura LSTM jest dostępna w TensorFlow, tf.contrib.rnn.LSTMCell. LSTM nie jest objęty zakresem tego samouczka. Możesz zapoznać się z oficjalnym dokumentacja dalszych informacji

RNN w szeregach czasowych

W tym samouczku TensorFlow RNN będziesz używać RNN z danymi szeregów czasowych. Szeregi czasowe zależą od poprzedniego czasu, co oznacza, że ​​przeszłe wartości zawierają istotne informacje, z których sieć może się uczyć. Ideą przewidywania szeregów czasowych jest oszacowanie przyszłej wartości szeregu, powiedzmy, ceny akcji, temperatury, PKB i tak dalej.

Przygotowanie danych dla Keras RNN i szeregów czasowych może być trochę trudne. Przede wszystkim celem jest przewidzenie następnej wartości szeregu, co oznacza, że ​​użyjesz informacji z przeszłości, aby oszacować wartość w t + 1. Etykieta jest równa sekwencji wejściowej i przesunięta o jeden okres do przodu. Po drugie, liczba danych wejściowych jest ustawiona na 1, tj. jedna obserwacja na czas. Na koniec, krok czasowy jest równy sekwencji wartości liczbowej. Na przykład, jeśli ustawisz krok czasowy na 10, sekwencja wejściowa zwróci dziesięć kolejnych razy.

Spójrz na poniższy wykres. Po lewej stronie przedstawiliśmy dane szeregów czasowych, a po prawej fikcyjną sekwencję wejściową. Tworzysz funkcję zwracającą zbiór danych z losową wartością dla każdego dnia od stycznia 2001 r. do grudnia 2016 r.

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

Wydajność

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

RNN w szeregach czasowych

Prawa część wykresu pokazuje wszystkie serie. Rozpoczyna się od 2001 r. i kończy w 2019 r. Nie ma sensu wprowadzać wszystkich danych do sieci, zamiast tego należy utworzyć partię danych o długości równej krokowi czasowemu. Ta partia będzie zmienną X. Zmienna Y jest taka sama jak X, ale przesunięta o jeden okres (tj. chcesz prognozować t+1).

Obydwa wektory mają tę samą długość. Widać to w prawej części powyższego wykresu. Linia reprezentuje dziesięć wartości wejścia X, podczas gdy czerwone kropki to dziesięć wartości etykiety Y. Należy pamiętać, że etykieta zaczyna się jeden okres przed X i kończy jeden okres po.

Zbuduj RNN, aby przewidzieć szeregi czasowe w TensorFlow

Teraz, w trakcie tego szkolenia RNN, nadszedł czas na zbudowanie pierwszego RNN, który będzie przewidywał powyższą serię. Należy określić pewne hiperparametry (parametry modelu, tj. liczbę neuronów itp.) dla modelu:

  • Liczba wejść: 1
  • Krok czasowy (okna w szeregu czasowym): 10
  • Liczba neuronów: 120
  • Liczba wyjść: 1

Twoja sieć będzie uczyć się na podstawie sekwencji 10 dni i będzie zawierać 120 powtarzających się neuronów. Zasilasz model jednym wejściem, czyli jednym dniem. Możesz zmienić wartości, aby sprawdzić, czy model uległ poprawie.

Przed zbudowaniem modelu należy podzielić zbiór danych na zbiór pociągowy i zbiór testowy. Pełny zbiór danych zawiera 222 punkty danych; wykorzystasz pierwsze 201 punktów do wytrenowania modelu, a ostatnie 21 punktów do przetestowania modelu.

Po zdefiniowaniu zestawu pociągowego i testowego należy utworzyć obiekt zawierający partie. W tych partiach masz wartości X i wartości Y. Pamiętaj, że wartości X są opóźnione o jeden okres. Dlatego wykorzystujesz pierwsze 200 obserwacji, a krok czasu jest równy 10. Obiekt X_batches powinien zawierać 20 partii o rozmiarze 10*1. Obiekt y_batches ma taki sam kształt jak obiekt X_batches, ale jest o jeden okres do przodu.

Krok 1) Utwórz pociąg i przetestuj

Przede wszystkim konwertujesz serię na a tępy tablica; następnie definiujesz okna (czyli liczbę czasów, w których sieć będzie się uczyć), liczbę danych wejściowych, wyjściowych i rozmiar zestawu treningowego, jak pokazano w poniższym przykładzie TensorFlow RNN.

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

Następnie wystarczy podzielić tablicę na dwa zbiory danych.

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

Krok 2) Utwórz funkcję zwracającą X_batches i y_batches

Aby to ułatwić, możesz utworzyć funkcję zwracającą dwie różne tablice, jedną dla X_batches i jedną dla y_batches.

Napiszmy funkcję RNN TensorFlow, aby skonstruować partie.

Należy zauważyć, że partie X są opóźnione o jeden okres (bierzemy wartość t-1). Wyjście funkcji powinno mieć trzy wymiary. Pierwszy wymiar jest równy liczbie partii, drugi rozmiarowi okien, a ostatni liczbie danych wejściowych.

Trudną częścią jest prawidłowe wybranie punktów danych. Dla punktów danych X wybierasz obserwacje od t = 1 do t = 200, natomiast dla punktu danych Y zwracasz obserwacje od t = 2 do 201. Gdy masz już prawidłowe punkty danych, zmiana kształtu jest prosta Serie.

Aby skonstruować obiekt z partii, należy podzielić zbiór danych na dziesięć partii o równej długości (tj. 20). Możesz użyć metody reshape i przekazać -1, aby seria była podobna do wielkości partii. Wartość 20 to liczba obserwacji na partię, a 1 to liczba danych wejściowych.

Musisz wykonać ten sam krok, ale dla etykiety.

Należy pamiętać, że należy przesunąć dane o liczbę razy, które chcesz prognozować. Na przykład, jeśli chcesz prognozować jeden timeahead, przesuń serię o 1. Jeśli chcesz prognozować dwa dni, przesuń dane o 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

Teraz, gdy funkcja jest zdefiniowana, możesz ją wywołać, aby utworzyć partie, jak pokazano w poniższym przykładzie RNN.

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

Możesz wydrukować kształt, aby upewnić się, że wymiary są prawidłowe.

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

Musisz utworzyć zbiór testowy zawierający tylko jedną partię danych i 20 obserwacji.

Należy pamiętać, że prognozujesz dni po dniach, co oznacza, że ​​druga przewidywana wartość będzie oparta na prawdziwej wartości z pierwszego dnia (t+1) testowego zbioru danych. Tak naprawdę, prawdziwa wartość będzie znana.

Jeśli chcesz prognozować t+2 (tj. dwa dni do przodu), musisz użyć przewidywanej wartości t+1; jeśli zamierzasz przewidzieć t+3 (trzy dni do przodu), musisz użyć przewidywanej wartości t+1 i t+2. Ma to sens, że trudno jest dokładnie przewidzieć t+n dni do przodu.

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)

Dobrze, rozmiar Twojej partii jest gotowy, możesz zbudować architekturę RNN. Pamiętaj, masz 120 neuronów rekurencyjnych.

Krok 3) Zbuduj model

Aby utworzyć model, należy zdefiniować trzy części:

  1. Zmienna z tensorami
  2. RNN
  3. Strata i optymalizacja

Krok 3.1) Zmienne

Musisz określić zmienne X i Y o odpowiednim kształcie. Ten krok jest banalny. Tensor ma ten sam wymiar co obiekty X_batches i y_batches.

Na przykład tensor X jest symbolem zastępczym (sprawdź samouczek dotyczący wprowadzenia do Tensorflow aby odświeżyć zdanie na temat deklaracji zmiennej) ma trzy wymiary:

  • Uwaga: wielkość partii
  • n_windows: Długość okien, tzn. liczba razy, w których model przegląda się wstecz
  • n_input: Liczba wejść

Wynik to:

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

Krok 3.2) Utwórz RNN

W drugiej części tego przykładu RNN TensorFlow musisz zdefiniować architekturę sieci. Tak jak poprzednio, używasz obiektu BasicRNNCell i dynamic_rnn z estymatora TensorFlow.

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

Następna część jest nieco trudniejsza, ale umożliwia szybsze obliczenia. Musisz przekształcić wynik uruchomienia w gęstą warstwę, a następnie przekonwertować go ponownie, aby miał ten sam wymiar co dane wejściowe.

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

Krok 3.3) Utwórz stratę i optymalizację

Optymalizacja modelu zależy od wykonywanego zadania. W poprzednim tutorialu dot CNNTwoim celem było sklasyfikowanie obrazów. W tym samouczku RNN cel jest nieco inny. Zostaniesz poproszony o prognozę zmiennej ciągłej w porównaniu z klasą.

Różnica ta jest istotna, ponieważ zmieni problem optymalizacji. Problem optymalizacji zmiennej ciągłej polega na minimalizacji błędu średniokwadratowego. Aby skonstruować te metryki w TF, możesz użyć:

  • tf.reduce_sum(tf.square(wyjścia – y))

Pozostała część kodu RNN jest taka sama jak poprzednio; używasz optymalizatora Adama, aby zmniejszyć straty (tj. MSE):

  • tf.train.AdamOptimizer(learning_rate=learning_rate)
  • optymalizator.minimize(strata)

To tyle, możesz wszystko spakować w jedną całość i Twój model jest gotowy do treningu.

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

Będziesz trenował model przy użyciu 1500 epok i drukował stratę co 150 iteracji. Po wyszkoleniu modelu oceniasz go na zestawie testowym i tworzysz obiekt zawierający przewidywania, jak pokazano w poniższym przykładzie rekurencyjnej sieci neuronowej.

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

Wreszcie, w tym samouczku dotyczącym głębokiego uczenia się RNN, możesz wykreślić rzeczywistą wartość szeregu z wartością przewidywaną. Jeśli model zostanie poprawiony, wartości przewidywane należy nałożyć na wartości rzeczywiste.

Jak widać, model ma pole do poprawy. To od Ciebie zależy, czy zmienisz hiperparametry, takie jak okna, rozmiar partii czy liczbę neuronów rekurencyjnych.

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()
Prognoza vs faktyczna

Prognoza vs faktyczna

Podsumowanie

Rekurencyjna sieć neuronowa to solidna architektura do radzenia sobie z analizą szeregów czasowych lub tekstów. Wyjście poprzedniego stanu jest sprzężeniem zwrotnym, aby zachować pamięć sieci w czasie lub sekwencji słów.

W TensorFlow możesz użyć następujących kodów do trenowania rekurencyjnej sieci neuronowej TensorFlow dla szeregów czasowych:

Parametry modelu

n_windows = 20   
n_input =  1
n_output = 1
size_train = 201

Zdefiniuj model

X = tf.placeholder(tf.float32, [None, n_windows, n_input])   
y = tf.placeholder(tf.float32, [None, n_windows, n_output])

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

Konstruowanie optymalizacji

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)                                          

Trenuj model

init = tf.global_variables_initializer() 
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})