RNN-Tutorial (Recurrent Neural Network): TensorFlow-Beispiel

Warum brauchen wir ein Recurrent Neural Network (RNN)?

Mit dem rekurrenten neuronalen Netzwerk (RNN) können Sie Speichereinheiten modellieren, um Daten beizubehalten und kurzfristige Abhängigkeiten zu modellieren. Es wird auch in der Zeitreihenprognose zur Identifizierung von Datenkorrelationen und -mustern verwendet. Es hilft auch, prädiktive Ergebnisse für sequentielle Daten zu erzielen, indem es ein ähnliches Verhalten wie ein menschliches Gehirn liefert.

Die Struktur eines künstlichen neuronalen Netzwerks ist relativ einfach und basiert hauptsächlich auf Matrixmultiplikation. Im ersten Schritt werden die Eingaben mit zunächst zufälligen Gewichten und Bias multipliziert, mit einer Aktivierungsfunktion transformiert und die Ausgabewerte zur Erstellung einer Vorhersage verwendet. Dieser Schritt vermittelt eine Vorstellung davon, wie weit das Netzwerk von der Realität entfernt ist.

Die angewandte Metrik ist der Verlust. Je höher die Verlustfunktion, desto dümmer ist das Modell. Um das Wissen des Netzwerks zu verbessern, ist eine gewisse Optimierung durch Anpassung der Gewichte des Netzes erforderlich. Der stochastische Gradientenabstieg ist die Methode, die verwendet wird, um die Werte der Gewichte in die richtige Richtung zu ändern. Sobald die Anpassung vorgenommen wurde, kann das Netzwerk einen weiteren Datensatz verwenden, um sein neues Wissen zu testen.

Der Fehler ist glücklicherweise geringer als zuvor, aber nicht klein genug. Der Optimierungsschritt wird iterativ durchgeführt, bis der Fehler minimiert ist, dh keine Informationen mehr extrahiert werden können.

Das Problem bei diesem Modelltyp ist, dass er keinen Speicher hat. Dies bedeutet, dass Eingabe und Ausgabe unabhängig sind. Mit anderen Worten, dem Modell ist es egal, was davor war. Es wirft einige Fragen auf, wenn Sie Zeitreihen oder Sätze vorhersagen müssen, da das Netzwerk Informationen über historische Daten oder vergangene Wörter benötigen muss.

Um dieses Problem zu lösen, wurde ein neuer Architekturtyp entwickelt: Recurrent Neural Network (im Folgenden RNN)

Was ist ein wiederkehrendes neuronales Netzwerk (RNN)?

A Rekurrentes neuronales Netz (RNN) ist eine Klasse von Künstliche neuronale Netz bei dem die Verbindung zwischen verschiedenen Knoten einen gerichteten Graphen bildet, um ein zeitlich dynamisches Verhalten zu ergeben. Es hilft, sequentielle Daten zu modellieren, die aus Feedforward-Netzwerken abgeleitet werden. Es funktioniert ähnlich wie das menschliche Gehirn, um prädiktive Ergebnisse zu liefern.

Ein wiederkehrendes neuronales Netzwerk sieht einem herkömmlichen neuronalen Netzwerk ziemlich ähnlich, mit der Ausnahme, dass den Neuronen ein Speicherzustand hinzugefügt wird. Die Berechnung zur Einbeziehung eines Speichers ist einfach.

Stellen Sie sich ein einfaches Modell vor, bei dem nur ein Neuron von einem Datenstapel gespeist wird. In einem herkömmlichen neuronalen Netz erzeugt das Modell die Ausgabe durch Multiplikation der Eingabe mit der Gewichtung und der Aktivierungsfunktion. Bei einem RNN wird diese Ausgabe mehrmals an sich selbst zurückgesendet. Wir nennen Zeitschritt die Zeitspanne, in der die Ausgabe zur Eingabe der nächsten Matrizenmultiplikation wird.

Im Bild unten können Sie beispielsweise sehen, dass das Netzwerk aus einem Neuron besteht. Das Netzwerk berechnet die Matrizenmultiplikation zwischen der Eingabe und dem Gewicht und fügt der Aktivierungsfunktion Nichtlinearität hinzu. Es wird bei t-1 zur Ausgabe. Diese Ausgabe ist die Eingabe der zweiten Matrixmultiplikation.

Rekurrentes neuronales Netz (RNN)
Rekurrentes neuronales Netz (RNN)

Im Folgenden codieren wir ein einfaches RNN in TensorFlow, um den Schritt und auch die Form der Ausgabe zu verstehen.

Das Netzwerk besteht aus:

  • Vier Eingänge
  • Sechs Neuronen
  • 2-malige Schritte

Das Netzwerk verhält sich wie im Bild unten dargestellt.

Rekurrentes neuronales Netz (RNN)

Das Netzwerk wird als „rekurrent“ bezeichnet, da es in jedem aktivierten Quadrat dieselbe Operation ausführt. Das Netzwerk berechnet die Gewichte der Eingaben und der vorherigen Ausgabe, bevor eine Aktivierungsfunktion verwendet wird.

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

Wir können das Netzwerk mit einem Platzhalter für die Daten, die wiederkehrende Phase und die Ausgabe aufbauen.

  1. Definieren Sie den Platzhalter für die Daten
X = tf.placeholder(tf.float32, [None, n_timesteps, n_inputs])

Hier:

  • Keine: Unbekannt und nimmt die Größe des Stapels an
  • n_timesteps: Häufigkeit, mit der das Netzwerk die Ausgabe an das Neuron zurücksendet
  • n_inputs: Anzahl der Eingaben pro Batch
  1. Definieren Sie das wiederkehrende Netzwerk

Wie im Bild oben erwähnt, besteht das Netzwerk aus 6 Neuronen. Das Netzwerk berechnet zwei Skalarprodukte:

  • Geben Sie Daten mit dem ersten Satz von Gewichten ein (d. h. 6: gleich der Anzahl der Neuronen)
  • Vorherige Ausgabe mit einem zweiten Satz von Gewichten (dh 6: entsprechend der Anzahl der Ausgaben)

Beachten Sie, dass beim ersten Feedforward die Werte der vorherigen Ausgabe gleich Nullen sind, da kein Wert verfügbar ist.

Das Objekt zum Erstellen eines RNN ist tf.contrib.rnn.BasicRNNCell mit dem Argument num_units, um die Anzahl der Eingaben zu definieren

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

Nachdem das Netzwerk nun definiert ist, können Sie die Ausgaben und Zustände berechnen

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

Dieses Objekt verwendet eine interne Schleife, um die Matrizen entsprechend oft zu multiplizieren.

Beachten Sie, dass das rekurrente Neuron eine Funktion aller Eingaben der vorherigen Zeitschritte ist. Auf diese Weise baut das Netzwerk sein eigenes Gedächtnis auf. Die Informationen aus der vorherigen Zeit können sich in der Zukunft verbreiten. Das ist die Magie des rekurrenten neuronalen Netzwerks

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

Zur Erläuterung drucken Sie die Werte des vorherigen Zustands aus. Die oben gedruckte Ausgabe zeigt die Ausgabe aus dem letzten Zustand. Drucken Sie nun die gesamte Ausgabe aus. Sie können sehen, dass es sich bei den Zuständen um die vorherige Ausgabe jedes Stapels handelt. Das heißt, die vorherige Ausgabe enthält die Informationen über die gesamte Sequenz.e

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)

Rekurrentes neuronales Netz (RNN)

Die Ausgabe hat die Form (3, 2, 6):

  • 3: Anzahl der Chargen
  • 2: Nummer des Zeitschritts
  • 6: Anzahl der Neuronen

Die Optimierung eines rekurrenten neuronalen Netzwerks ist identisch mit der eines herkömmlichen neuronalen Netzwerks. Im nächsten Teil dieses Tutorials zu rekurrenten neuronalen Netzwerken erfahren Sie ausführlicher, wie Sie die Codeoptimierung durchführen.

Anwendungen von RNN

RNN hat vielfältige Einsatzmöglichkeiten, insbesondere wenn es um die Vorhersage der Zukunft geht. In der Finanzbranche kann RNN bei der Vorhersage von Aktienkursen oder dem Vorzeichen der Börsenrichtung (d. h. positiv oder negativ) hilfreich sein.

RNN ist für ein autonomes Auto nützlich, da es einen Autounfall vermeiden kann, indem es die Flugbahn des Fahrzeugs vorhersagt.

RNN wird häufig in der Textanalyse, Bildunterschrift, Stimmungsanalyse und maschinellen Übersetzung eingesetzt. Beispielsweise kann man eine Filmrezension nutzen, um das Gefühl zu verstehen, das der Zuschauer nach dem Ansehen des Films empfand. Die Automatisierung dieser Aufgabe ist sehr nützlich, wenn die Filmfirma nicht genügend Zeit hat, die Rezensionen zu prüfen, zu kennzeichnen, zu konsolidieren und zu analysieren. Die Maschine kann die Arbeit mit höherer Genauigkeit erledigen.

Einschränkungen von RNN

Theoretisch soll RNN die Informationen aktuell halten. Allerdings ist es ziemlich schwierig, all diese Informationen zu verbreiten, wenn der Zeitschritt zu lang ist. Wenn ein Netzwerk zu viele tiefe Schichten hat, kann es nicht mehr trainiert werden. Dieses Problem heißt: verschwindendes Gradientenproblem. Wenn Sie sich erinnern, aktualisiert das neuronale Netzwerk das Gewicht mithilfe des Gradientenabstiegsalgorithmus. Die Gradienten werden kleiner, wenn das Netzwerk in tiefere Schichten vordringt.

Zusammenfassend lässt sich sagen, dass die Steigungen konstant bleiben, was bedeutet, dass es keinen Raum für Verbesserungen gibt. Das Modell lernt aus einer Änderung des Gradienten; Diese Änderung wirkt sich auf die Ausgabe des Netzwerks aus. Wenn der Unterschied im Gradienten jedoch zu gering ist (d. h. die Gewichte ändern sich ein wenig), kann das Netzwerk nichts lernen und damit auch die Ausgabe. Daher kann ein Netzwerk, das mit einem verschwindenden Gradientenproblem konfrontiert ist, nicht zu einer guten Lösung konvergieren.

Verbesserung LSTM

Um das potenzielle Problem des verschwindenden Gradienten zu überwinden, mit dem RNN konfrontiert ist, verbesserten drei Forscher, Hochreiter, Schmidhuber und Bengio, das RNN mit einer Architektur namens Long Short-Term Memory (LSTM). Kurz gesagt liefert LSMT dem Netzwerk relevante Informationen aus der Vergangenheit bis hin zu jüngeren Zeiten. Die Maschine verwendet eine bessere Architektur, um Informationen auszuwählen und in einen späteren Zeitpunkt zurückzutragen.

Die LSTM-Architektur ist in TensorFlow verfügbar, tf.contrib.rnn.LSTMCell. LSTM liegt außerhalb des Umfangs dieses Tutorials. Sie können sich auf die offizielle Dokumentation für weitere Informationen

RNN in Zeitreihen

In diesem TensorFlow-RNN-Tutorial verwenden Sie ein RNN mit Zeitreihendaten. Zeitreihen hängen von der vorherigen Zeit ab, was bedeutet, dass vergangene Werte relevante Informationen enthalten, aus denen das Netzwerk lernen kann. Die Idee hinter der Zeitreihenvorhersage besteht darin, den zukünftigen Wert einer Reihe abzuschätzen, beispielsweise Aktienkurs, Temperatur, BIP usw.

Die Datenaufbereitung für Keras RNN und Zeitreihen kann etwas knifflig sein. Zunächst besteht das Ziel darin, den nächsten Wert der Reihe vorherzusagen. Das heißt, Sie verwenden die Informationen aus der Vergangenheit, um den Wert bei t + 1 zu schätzen. Das Label entspricht der Eingabesequenz und ist um eine Periode nach vorne verschoben. Zweitens wird die Anzahl der Eingaben auf 1 gesetzt, d. h. eine Beobachtung pro Zeit. Schließlich entspricht der Zeitschritt der Sequenz des numerischen Werts. Wenn Sie beispielsweise den Zeitschritt auf 10 setzen, wird die Eingabesequenz zehnmal hintereinander zurückgegeben.

Schauen Sie sich die Grafik unten an. Wir haben links die Zeitreihendaten und rechts eine fiktive Eingabesequenz dargestellt. Sie erstellen eine Funktion, um für jeden Tag von Januar 2001 bis Dezember 2016 einen Datensatz mit Zufallswert zurückzugeben

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

Ausgang

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 in Zeitreihen

Der rechte Teil des Diagramms zeigt alle Reihen. Sie beginnen 2001 und enden 2019. Es ergibt keinen Sinn, alle Daten in das Netzwerk einzuspeisen. Stattdessen müssen Sie einen Datenstapel mit einer Länge erstellen, die dem Zeitschritt entspricht. Dieser Stapel wird die X-Variable sein. Die Y-Variable ist dieselbe wie X, jedoch um eine Periode verschoben (d. h. Sie möchten t+1 vorhersagen).

Beide Vektoren haben die gleiche Länge. Sie können es im rechten Teil der obigen Grafik sehen. Die Linie stellt die zehn Werte der X-Eingabe dar, während die roten Punkte die zehn Werte der Beschriftung Y darstellen. Beachten Sie, dass die Beschriftung einen Punkt vor X beginnt und einen Punkt danach endet.

Erstellen Sie ein RNN, um Zeitreihen in TensorFlow vorherzusagen

In diesem RNN-Training ist es nun an der Zeit, Ihr erstes RNN zu erstellen, um die obige Reihe vorherzusagen. Sie müssen einige Hyperparameter (die Parameter des Modells, z. B. die Anzahl der Neuronen usw.) für das Modell angeben:

  • Anzahl der Eingänge: 1
  • Zeitschritt (Fenster in Zeitreihen): 10
  • Anzahl der Neuronen: 120
  • Anzahl der Ausgänge: 1

Ihr Netzwerk lernt aus einer Abfolge von 10 Tagen und enthält 120 wiederkehrende Neuronen. Sie füttern das Modell mit einer Eingabe, also einem Tag. Fühlen Sie sich frei, die Werte zu ändern, um zu sehen, ob sich das Modell verbessert hat.

Bevor Sie das Modell erstellen, müssen Sie den Datensatz in einen Zugsatz und einen Testsatz aufteilen. Der vollständige Datensatz umfasst 222 Datenpunkte; Sie verwenden die ersten 201 Punkte zum Trainieren des Modells und die letzten 21 Punkte zum Testen Ihres Modells.

Nachdem Sie einen Zug- und Testsatz definiert haben, müssen Sie ein Objekt erstellen, das die Stapel enthält. In diesen Stapeln gibt es X-Werte und Y-Werte. Denken Sie daran, dass die X-Werte um eine Periode verzögert sind. Daher verwenden Sie die ersten 200 Beobachtungen und der Zeitschritt ist gleich 10. Das X_batches-Objekt sollte 20 Batches der Größe 10*1 enthalten. Das y_batches-Objekt hat die gleiche Form wie das X_batches-Objekt, jedoch mit einem Punkt voraus.

Schritt 1) Erstellen Sie den Zug und testen Sie ihn

Zunächst wandeln Sie die Serie in eine um numpig Array; dann definieren Sie die Fenster (d. h. die Anzahl der Lernvorgänge des Netzwerks), die Anzahl der Eingaben, Ausgaben und die Größe des Trainingssatzes, wie im TensorFlow RNN-Beispiel unten gezeigt.

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

Danach teilen Sie das Array einfach in zwei Datensätze auf.

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

Schritt 2) Erstellen Sie die Funktion, um X_batches und y_batches zurückzugeben

Zur Vereinfachung können Sie eine Funktion erstellen, die zwei verschiedene Arrays zurückgibt, eines für X_batches und eines für y_batches.

Schreiben wir eine RNN-TensorFlow-Funktion, um die Stapel zu erstellen.

Beachten Sie, dass die X-Batches um eine Periode verzögert sind (wir nehmen den Wert t-1). Die Ausgabe der Funktion sollte drei Dimensionen haben. Die erste Dimension entspricht der Anzahl der Batches, die zweite der Größe der Fenster und die letzte der Anzahl der Eingaben.

Der schwierige Teil besteht darin, die Datenpunkte richtig auszuwählen. Für die X-Datenpunkte wählen Sie die Beobachtungen von t = 1 bis t = 200 aus, während Sie für den Y-Datenpunkt die Beobachtungen von t = 2 bis 201 zurückgeben. Sobald Sie die richtigen Datenpunkte haben, ist die Umformung einfach die Serie.

Um das Objekt mit den Stapeln zu erstellen, müssen Sie den Datensatz in zehn Stapel gleicher Länge (z. B. 20) aufteilen. Sie können die Reshape-Methode verwenden und -1 übergeben, sodass die Serie der Stapelgröße ähnelt. Der Wert 20 ist die Anzahl der Beobachtungen pro Stapel und 1 ist die Anzahl der Eingaben.

Sie müssen den gleichen Schritt ausführen, jedoch für das Etikett.

Beachten Sie, dass Sie die Daten entsprechend der Anzahl der Prognosen verschieben müssen. Wenn Sie beispielsweise eine Prognose für einen Tag im Voraus erstellen möchten, verschieben Sie die Reihe um 1. Wenn Sie eine Prognose für zwei Tage erstellen möchten, verschieben Sie die Daten um 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

Nachdem die Funktion nun definiert ist, können Sie sie aufrufen, um die Stapel zu erstellen, wie im folgenden RNN-Beispiel gezeigt.

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

Sie können die Form ausdrucken, um sicherzustellen, dass die Abmessungen korrekt sind.

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

Sie müssen den Testsatz mit nur einem Datenstapel und 20 Beobachtungen erstellen.

Beachten Sie, dass Sie Tage für Tage prognostizieren. Dies bedeutet, dass der zweite vorhergesagte Wert auf dem wahren Wert des ersten Tages (t+1) des Testdatensatzes basiert. Tatsächlich wird der wahre Wert bekannt sein.

Wenn Sie t+2 (also zwei Tage im Voraus) vorhersagen möchten, müssen Sie den vorhergesagten Wert t+1 verwenden; Wenn Sie t+3 (drei Tage im Voraus) vorhersagen möchten, müssen Sie die vorhergesagten Werte t+1 und t+2 verwenden. Es macht Sinn, dass es schwierig ist, eine genaue Vorhersage für t+n Tage im Voraus zu treffen.

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)

Okay, Ihre Batchgröße ist bereit, Sie können die RNN-Architektur erstellen. Denken Sie daran, Sie haben 120 rekurrierende Neuronen.

Schritt 3) Erstellen Sie das Modell

Um das Modell zu erstellen, müssen Sie drei Teile definieren:

  1. Die Variable mit den Tensoren
  2. Das RNN
  3. Der Verlust und die Optimierung

Schritt 3.1) Variablen

Sie müssen die X- und Y-Variablen mit der entsprechenden Form angeben. Dieser Schritt ist trivial. Der Tensor hat die gleiche Dimension wie die Objekte X_batches und y_batches.

Beispielsweise ist der Tensor X ein Platzhalter (sehen Sie sich das Tutorial zur Einführung in an). Tensorflow um Ihre Gedanken über die Variablendeklaration aufzufrischen) hat drei Dimensionen:

  • Hinweis: Größe der Charge
  • n_windows: Länge der Fenster. D. h. die Häufigkeit, mit der das Modell nach hinten blickt
  • n_input: Anzahl der Eingaben

Das Ergebnis ist:

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

Schritt 3.2) Erstellen Sie das RNN

Im zweiten Teil dieses RNN TensorFlow-Beispiels müssen Sie die Architektur des Netzwerks definieren. Wie zuvor verwenden Sie das Objekt BasicRNNCell und dynamic_rnn aus dem TensorFlow-Schätzer.

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

Der nächste Teil ist etwas kniffliger, ermöglicht aber eine schnellere Berechnung. Sie müssen die Laufausgabe in eine dichte Ebene umwandeln und sie dann erneut konvertieren, damit sie dieselbe Dimension wie die Eingabe hat.

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

Schritt 3.3) Erstellen Sie den Verlust und die Optimierung

Die Modelloptimierung hängt von der Aufgabe ab, die Sie ausführen. Im vorherigen Tutorial zu CNNIhr Ziel war es, Bilder zu klassifizieren. In diesem RNN-Tutorial ist das Ziel etwas anders. Sie werden gebeten, eine Vorhersage für eine kontinuierliche Variable im Vergleich zu einer Klasse zu treffen.

Dieser Unterschied ist wichtig, da er das Optimierungsproblem verändert. Das Optimierungsproblem für eine kontinuierliche Variable besteht darin, den mittleren quadratischen Fehler zu minimieren. Um diese Metriken in TF zu erstellen, können Sie Folgendes verwenden:

  • tf.reduce_sum(tf.square(outputs – y))

Der Rest des RNN-Codes ist derselbe wie zuvor; Sie verwenden einen Adam-Optimierer, um den Verlust zu reduzieren (d. h. MSE):

  • tf.train.AdamOptimizer(learning_rate=learning_rate)
  • optimierer.minimize(Verlust)

Das war's, Sie können alles zusammenpacken und Ihr Modell ist bereit für das Training.

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

Sie trainieren das Modell anhand von 1500 Epochen und drucken den Verlust alle 150 Iterationen aus. Sobald das Modell trainiert ist, bewerten Sie das Modell anhand des Testsatzes und erstellen ein Objekt mit den Vorhersagen, wie im folgenden Beispiel für ein rekurrentes neuronales Netzwerk gezeigt.

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

In diesem RNN Deep Learning-Tutorial können Sie schließlich den tatsächlichen Wert der Reihe mit dem vorhergesagten Wert grafisch darstellen. Wenn Ihr Modell korrigiert wird, sollten die vorhergesagten Werte über die tatsächlichen Werte gesetzt werden.

Wie Sie sehen, besteht bei diesem Modell noch Verbesserungspotenzial. Sie können die Hyperparameter wie die Fenster, die Batchgröße oder die Anzahl der rekurrierenden Neuronen ändern.

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()
Prognose vs. Ist

Prognose vs. Ist

Zusammenfassung

Ein rekurrentes neuronales Netzwerk ist eine robuste Architektur für die Verarbeitung von Zeitreihen oder Textanalysen. Die Ausgabe des vorherigen Zustands ist eine Rückmeldung, um das Gedächtnis des Netzwerks über die Zeit oder Wortfolgen hinweg zu bewahren.

In TensorFlow können Sie die folgenden Codes verwenden, um ein TensorFlow Recurrent Neural Network für Zeitreihen zu trainieren:

Parameter des Modells

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

Definieren Sie das Modell

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

Konstruieren Sie die Optimierung

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)                                          

Trainiere das Modell

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