Ich habe RNN in Python implementiert. Ich habe ["Deep Learning"](http://www.amazon.co.jp/ Deep Learning-Maschinelles Lernen Professional Series-Okaya-Takayuki / dp / 4061529021) als Lehrbuch verwendet.
Struktur dieses Artikels
Einführung
RNN
Berechnung der Vorwärtsausbreitung
Backpropagation-Berechnung
Gewichtsaktualisierung
Ergebnis
Verlust
Vorhersage von Seriendaten
Sin Wellenvorhersage
abschließend
RNN
RNN ist ein rekursives neuronales Netzwerk, das Seriendaten verarbeitet. Beispiele für Seriendaten sind Sprache, Sprache und bewegte Bilder. Das Merkmal solcher Seriendaten ist, dass die Länge der Serie für jede Probe unterschiedlich ist und die Reihenfolge der Elemente in der Serie von Bedeutung ist. RNN ermöglicht es, die Eigenschaften von Seriendaten gut zu handhaben.
Definieren Sie zunächst die Zeichen. Die Indizes jeder Einheit der Eingangsschicht, Zwischenschicht und Ausgangsschicht werden durch $ i, j bzw. k $ dargestellt. Die Eingabe zum Zeitpunkt $ t $, die Eingabe / Ausgabe der Zwischenschicht, die Eingabe / Ausgabe der Ausgabeebene und der Lehrer werden wie folgt ausgedrückt.
Weiterhin werden die Gewichte zwischen der Eingabe-Zwischenschicht, die Gewichte des Rückkopplungspfads zwischen den Zwischen-Zwischenschichten und die Gewichte zwischen den Zwischen-Ausgangsschichten wie folgt ausgedrückt.
Die Struktur des Netzwerks einschließlich der obigen Definition ist in der folgenden Abbildung dargestellt.
Jetzt werde ich die Berechnung der Vorwärtsausbreitung erklären. Eingabe / Ausgabe $ u_j ^ t $ und $ z_j ^ t $ der Einheit $ j $ in der mittleren Ebene sind die Eingabe $ \ boldsymbol x ^ t $ und der Wert der mittleren Ebene zum vorherigen Zeitpunkt $ \ boldsymbol z ^ {t Es kann wie folgt mit -1} $ ausgedrückt werden. $ f $ ist die Aktivierungsfunktion.
\begin{align}
& u_j^t = \sum_i w_{ji}^{(in)}x_i^t + \sum_{j'} w_{jj'}z_{j'}^{t-1} \tag{1} \\
& z_j^t = f(u_j^t) \tag{2}
\end{align}
Wenn jedoch $ t = 1 $ ist, gibt es bisher keine Eingabe, also $ \ boldsymbol z ^ 0 = \ boldsymbol 0 $. Wenn die Gleichungen (1) und (2) zusammengesetzt und in einer Matrix ausgedrückt werden, ist die Ausgabe $ \ boldsymbol z ^ t $ der Zwischenschicht wie folgt.
\boldsymbol z^t = \boldsymbol f(\boldsymbol W^{(in)}\boldsymbol x^t + \boldsymbol W \boldsymbol z^{t-1}) \tag{3}
Die Eingabe / Ausgabe $ v_k ^ t $ und $ y_k ^ t $ der Einheit $ k $ der Ausgabeschicht können wie folgt ausgedrückt werden, indem die Ausgabe $ \ boldsymbol z ^ t $ der Zwischenschicht verwendet wird.
\begin{align}
& v_k^t = \sum_j w_{kj}^{(out)}z_j^t \tag{4} \\
& y_k^t = f^{(out)}(v_k^t) \tag{5}
\end{align}
Wenn die Gleichungen (4) und (5) zusammengesetzt und in einer Matrix ausgedrückt werden, ist die Ausgabe $ \ boldsymbol y ^ t $ wie folgt.
\boldsymbol y^t = \boldsymbol f^{(out)}(\boldsymbol W^{(out)}\boldsymbol z^t) \tag{6}
Der Gradient wird aus dem Fehler in jeder Einheit jeder Schicht durch das Fehlerrückausbreitungsverfahren berechnet. Dieses Mal werde ich die ** BPTT-Methode (Back Propagation durch die Zeit) ** erklären. Bei der BPTT-Methode wird RNN in der Zeitrichtung erweitert, wie in der folgenden Abbildung gezeigt, und die Fehlerrückausbreitung wird berechnet.
** Intermediate-Slope zwischen den Ausgabeebenen **
\begin{align}
\frac{\partial E}{\partial w_{kj}^{(out)}} &= \sum_{t=1}^T \frac{\partial E}{\partial v_k^t} \frac{\partial v_k^t}{\partial w_{kj}^{(out)}} \\
&= \sum_{t=1}^T \frac{\partial E}{\partial y_k^t} \frac{\partial y_k^t}{\partial v_k^t} \frac{\partial v_k^t}{\partial w_{kj}^{(out)}} \\
&= \sum_{t=1}^T \frac{\partial E}{\partial y_k^t} f^{(out)'}(v_k^t)z_j^t \\
&= \sum_{t=1}^T \delta_k^{(out), t} z_j^t \tag{7}
\end{align}
** Zwischensteigung im Rückweg der Zwischenschicht **
\begin{align}
\frac{\partial E}{\partial w_{jj'}} &= \sum_{t=1}^T \frac{\partial E}{\partial u_j^t} \frac{\partial u_j^t}{\partial w_{jj'}} \\
&= \sum_{t=1}^T \biggl(\sum_{k'} \frac{\partial E}{\partial v_{k'}^t} \frac{\partial v_{k'}^t}{\partial z_j^t} \frac{\partial z_j^t}{\partial u_j^t} + \sum_{j''} \frac{\partial E}{\partial u_{j''}^{t+1}} \frac{\partial u_{j''}^{t+1}}{\partial z_j^t} \frac{\partial z_j^t}{\partial u_j^t} \biggr) \frac{\partial u_j^t}{\partial w_{jj'}} \\
&= \sum_{t=1}^T \biggl(\sum_{k'} \frac{\partial E}{\partial v_{k'}^t} \frac{\partial v_{k'}^t}{\partial z_j^t} + \sum_{j''} \frac{\partial E}{\partial u_{j''}^{t+1}} \frac{\partial u_{j''}^{t+1}}{\partial z_j^t} \biggr) \frac{\partial z_j^t}{\partial u_j^t} \frac{\partial u_j^t}{\partial w_{jj'}} \\
&= \sum_{t=1}^T \biggl(\sum_{k'} \delta_{k'}^{(out), t} w_{k'j} + \sum_{j''} \delta_{j''}^{t+1} w_{j''j} \biggr) f'(u_j^t) z_j^{t-1} \\
&= \sum_{t=1}^T \delta_j^t z_j^{t-1} \tag{8}
\end{align}
** Input-Slope zwischen Zwischenschichten **
\begin{align}
\frac{\partial E}{\partial w_{ji}^{(in)}} &= \sum_{t=1}^T \frac{\partial E}{\partial u_j^t} \frac{\partial u_j^t}{\partial w_{ji}^{(in)}} \\
&= \sum_{t=1}^T \delta_j^t x_i^t \tag{9}
\end{align}
Intermediate-In dem Gradienten im Rückweg der Zwischenschicht gibt es beim nächsten Mal einen Term des Fehlers $ \ boldsymbol \ delta ^ {t + 1} $ der Zwischenschicht. Wenn $ t = T $, dann ist $ \ boldsymbol \ delta ^ {T + 1} = \ boldsymbol 0 $. Propagieren Sie den Fehler $ \ delta $ in der Reihenfolge $ t = T, T-1, \ cdots, 2, 1 $ und nehmen Sie jeweils die Summe der Gradienten. Das Gewicht wird anhand der Summe dieses Gradienten aktualisiert.
Aus den Gleichungen (7), (8) und (9) kann der Gradient zwischen jeder Schicht erhalten werden. Aktualisieren Sie mithilfe dieses Verlaufs das Gewicht anhand der folgenden Formel.
w_{new} = w_{old} - \varepsilon \frac{\partial E}{\partial w_{old}} \tag{10}
Sinuswellenvorhersage implementiert. Der Code ist unter [hier] angegeben (https://github.com/shota-takayama/rnn). $ x ^ t = \ sin \ bigl (\ theta + (t -1) \ cdot \ Delta \ theta \ bigr) $ Geben Sie beim nächsten Mal $ x ^ t $ und $ y ^ t = \ ein Sagen Sie $ y ^ t $ voraus, was sin \ bigl (\ theta + t \ cdot \ Delta \ theta \ bigr) $ ist. Bei der Ausgabe von $ y ^ t $ für eine bestimmte Eingabe $ x ^ t $ kann die Vorhersagerichtung nicht nur durch die Eingabe $ x ^ t $ bestimmt werden. Wenn Sie jedoch $ x ^ t $ und $ z ^ {t-1} $ eingeben, können Sie die Informationen der vorherigen Zeit verwenden, um die Vorhersagerichtung zu bestimmen.
Die Trainingsdaten sind eine $ 1 $ -Stichprobe der Seriendaten von $ \ boldsymbol x = (x ^ 1, x ^ 2, \ cdots, x ^ T) $. $ \ theta $ wird durch eine Zufallszahl aus dem Bereich von $ [0, \ pi] $ bestimmt.
\begin{align}
& \{\theta \,|\, 0 \leq \theta \leq \pi\}, \Delta \theta = \frac{\pi}{6} \\
& x^1 = \sin \theta \\
& x^2 = \sin \bigl(\theta + \Delta \theta\bigr) \\
& \cdots \\
& x^t = \sin \bigl(\theta + (t - 1)\cdot \Delta \theta\bigr) \tag{11} \\
& \cdots \\
& x^T = \sin \bigl(\theta + (T - 1)\cdot \Delta \theta\bigr) \\
\end{align}
Die Lernparameter sind wie folgt. Trainingsdaten: $ 7000 $ Probe Lernrate: $ \ varepsilon = 0,05 $ Regularisierungskoeffizient: $ \ lambda = 0,001 $ Epoche: 30 $
Der Verlust während des Lernens ist wie folgt.
Überprüfen Sie anschließend, ob die Vorhersage korrekt war, als die Zeitreihendaten eingegeben wurden. Die Eingabe wird durch $ x $ dargestellt, die Ausgabe wird durch $ y $ dargestellt und die ideale Ausgabe wird durch $ d $ dargestellt.
\begin{align}
& x^1 = \sin\Bigl(\frac{1}{6}\pi\Bigr) \to y^1 = 0.43831960 \ \ (d^1 = 0.86602540) \tag{12} \\
& x^1 = \sin\Bigl(\frac{5}{6}\pi\Bigr) \to y^1 = 0.43831960 \ \ (d^1 = 0.0) \tag{13}
\end{align}
Die Werte von $ y $ stimmen überein, da die Werte von $ x $ gleich sind. Außerdem ist die Vorhersage $ y $ weit von der idealen Ausgabe $ d $ entfernt, da keine Sequenzinformationen vorhanden sind. Daher werde ich auch die Daten der vorherigen Zeit eingeben.
\begin{align}
& \boldsymbol x = (x^1, x^2) = \biggl(\sin\Bigl(\frac{0}{6}\pi\Bigr), \sin\Bigl(\frac{1}{6}\pi\Bigr)\biggr) \to y^2 = 0.84290507 \ \ (d^2 = 0.86602540) \tag{14} \\
& \boldsymbol x = (x^1, x^2) = \biggl(\sin\Bigl(\frac{4}{6}\pi\Bigr), \sin\Bigl(\frac{5}{6}\pi\Bigr)\biggr) \to y^2 = -0.02663726 \ \ (d^2 = 0.0) \tag{15}
\end{align}
Bei Eingabe als Zeitreihendaten werden korrekte Vorhersageergebnisse erhalten. Dies ist möglich, weil RNN eine rekursive Struktur hat, die Zeitreiheninformationen enthält.
Schließlich sagen wir die Sündenwelle voraus. Ein einfacher Algorithmus ist unten gezeigt.
Die folgende Abbildung ist das Ergebnis. Seriendaten mit kurzen blauen und grünen Punkten sind die durch Vorhersage erhaltenen Ergebnisse. Wenn Sie sich die Grafik ansehen, können Sie sehen, dass die Sinuswelle korrekt vorhergesagt werden kann.
Ich konnte RNN implementieren. Als nächstes möchte ich LSTM studieren.
Recommended Posts