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.
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.
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.
- 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ę
- 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)
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()
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:
- Zmienna z tensorami
- RNN
- 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()
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})