Implémentation RNN en python

introduction

J'ai implémenté RNN en python. J'ai utilisé ["Deep Learning"](http://www.amazon.co.jp/ Deep Learning-Machine Learning Professional Series-Okaya-Takayuki / dp / 4061529021) comme manuel.

Structure de cet article

RNN

RNN est un réseau neuronal récursif qui gère les données en série. Des exemples de données de série comprennent la voix, la langue et les images en mouvement. La caractéristique de ces données en série est que la longueur de la série diffère pour chaque échantillon et que l'ordre des éléments de la série est significatif. RNN permet de bien gérer les caractéristiques des données en série.

Calcul de la propagation vers l'avant

Tout d'abord, définissez les caractères. Les index de chaque unité de la couche d'entrée, de la couche intermédiaire et de la couche de sortie sont respectivement représentés par $ i, j et k $. De plus, l'entrée au temps $ t $, l'entrée / sortie de la couche intermédiaire, l'entrée / sortie de la couche de sortie et l'enseignant sont exprimées comme suit.

En outre, les poids entre la couche d'entrée-intermédiaire, les poids du chemin de rétroaction entre les couches intermédiaires-intermédiaires et les poids entre les couches intermédiaire-sortie sont exprimés comme suit.

La structure du réseau comprenant la définition ci-dessus est illustrée dans la figure ci-dessous.

rnn.png

Maintenant, je vais expliquer le calcul de la propagation vers l'avant. Les entrées / sorties $ u_j ^ t $ et $ z_j ^ t $ de l'unité $ j $ dans la couche intermédiaire sont l'entrée $ \ boldsymbol x ^ t $ et la valeur de la couche intermédiaire à l'instant précédent $ \ boldsymbol z ^ {t Il peut être exprimé comme suit en utilisant -1} $. $ f $ est la fonction d'activation.

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

Cependant, lorsque $ t = 1 $, il n'y a pas d'entrée pour l'instant, donc $ \ boldsymbol z ^ 0 = \ boldsymbol 0 $. Lorsque les équations (1) et (2) sont résumées et exprimées dans une matrice, la sortie $ \ boldsymbol z ^ t $ de la couche intermédiaire est la suivante.

\boldsymbol z^t = \boldsymbol f(\boldsymbol W^{(in)}\boldsymbol x^t + \boldsymbol W \boldsymbol z^{t-1}) \tag{3}

L'entrée / sortie $ v_k ^ t $ et $ y_k ^ t $ de l'unité $ k $ de la couche de sortie peut être exprimée comme suit en utilisant la sortie $ \ boldsymbol z ^ t $ de la couche intermédiaire.

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

Lorsque les équations (4) et (5) sont rassemblées et exprimées dans une matrice, la sortie $ \ boldsymbol y ^ t $ est la suivante.

\boldsymbol y^t = \boldsymbol f^{(out)}(\boldsymbol W^{(out)}\boldsymbol z^t) \tag{6}

Calcul de rétropropagation

Le gradient est calculé à partir de l'erreur dans chaque unité de chaque couche par la méthode de propagation de retour d'erreur. Cette fois, j'expliquerai la ** méthode BPTT (rétropropagation dans le temps) **. Dans la méthode BPTT, le RNN est étendu dans le sens du temps, comme indiqué dans la figure ci-dessous, et la rétro-propagation d'erreur est calculée.

bptt.png

** Pente intermédiaire entre les couches de sortie **

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

** Pente intermédiaire dans le chemin de retour de la couche intermédiaire **

\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 entre les couches intermédiaires **

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

Intermédiaire - Dans le dégradé du chemin de retour de la couche intermédiaire, il y a un terme de l'erreur $ \ boldsymbol \ delta ^ {t + 1} $ de la couche intermédiaire à la prochaine fois. Si $ t = T $, alors $ \ boldsymbol \ delta ^ {T + 1} = \ boldsymbol 0 $. Propagez l'erreur $ \ delta $ dans l'ordre $ t = T, T-1, \ cdots, 2, 1 $, et prenez la somme des gradients à chaque instant. Le poids est mis à jour en utilisant la somme de ce gradient.

Mise à jour du poids

À partir des équations (7), (8) et (9), le gradient entre chaque couche peut être obtenu. À l'aide de ce dégradé, mettez à jour le poids à partir de la formule suivante.

w_{new} = w_{old} - \varepsilon \frac{\partial E}{\partial w_{old}} \tag{10}

Implémentation en python

Implémentation de la prédiction sinusoïdale. Le code peut être trouvé à ici. $ x ^ t = \ sin \ bigl (\ theta + (t -1) \ cdot \ Delta \ theta \ bigr) $ Entrez $ x ^ t $ et $ y ^ t = \ à la prochaine fois Prédisez $ y ^ t $, qui est sin \ bigl (\ theta + t \ cdot \ Delta \ theta \ bigr) $. Lors de la sortie de $ y ^ t $ pour une certaine entrée $ x ^ t $, la direction de prédiction ne peut pas être déterminée uniquement par l'entrée $ x ^ t $. Cependant, si vous entrez $ x ^ t $ et $ z ^ {t-1} $, vous pouvez utiliser les informations de l'heure précédente pour déterminer la direction de la prédiction.

résultat

Les données d'apprentissage sont un échantillon $ 1 $ des données de série de $ \ boldsymbol x = (x ^ 1, x ^ 2, \ cdots, x ^ T) $. $ \ theta $ est déterminé par un nombre aléatoire de la plage de $ [0, \ pi] $.

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

Les paramètres d'apprentissage sont les suivants. Données d'entraînement: 7000 $ Échantillon Taux d'apprentissage: $ \ varepsilon = 0,05 $ Coefficient de régularisation: $ \ lambda = 0,001 $ Époque: 30 $ $

Perte

La perte pendant l'apprentissage est la suivante.

loss.png

Prévision des données de série

Ensuite, vérifiez si la prédiction était correcte lorsque les données de la série chronologique ont été entrées. L'entrée est représentée par $ x $, la sortie est représentée par $ y $ et la sortie idéale est représentée par $ d $.

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

Les valeurs de $ y $ correspondent car les valeurs de $ x $ sont égales. De plus, la prédiction $ y $ est loin d'être la sortie idéale $ d $ car il n'y a aucune information de séquence. Par conséquent, je vais également entrer les données de la fois précédente.

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

Si vous les entrez en tant que données de série chronologique, le résultat de la prédiction correct est obtenu. Cela est possible car le RNN a une structure récursive qui contient des informations de série chronologique.

Prédiction de l'onde de péché

Enfin, nous prédisons la vague de péché. Un algorithme simple est présenté ci-dessous.

  1. Entrez les données de la série courte $ \ boldsymbol x = (x ^ 1, x ^ 2, \ cdots, x ^ {T '}) $ et obtenez le résultat $ y ^ {T'} $.
  2. Entrez $ y ^ {T '} $ comme $ x ^ {T' + 1} $ et obtenez le résultat $ y ^ {T '+ 1} $.
  3. Répétez l'étape 2 pour obtenir les résultats dans l'ordre.

La figure ci-dessous montre le résultat. Les données de série avec de courts points bleus et des points verts sont les résultats obtenus par prédiction. Si vous regardez le graphique, vous pouvez voir que l'onde de péché peut être prédite correctement.

sin.png

en conclusion

J'ai pu implémenter RNN. Ensuite, j'aimerais étudier le LSTM.

Recommended Posts

Implémentation RNN en python
Implémentation ValueObject en Python
Implémentation SVM en python
Implémentation de réseau neuronal en python
Implémentation du tri rapide en Python
Algorithme de tri et implémentation en Python
Implémentation de l'estimation des paramètres HMM en python
Implémentation de distribution normale mixte en python
Implémentation du jeu de vie en Python
Implémentation du tri original en Python
Quadtree en Python --2
Python en optimisation
CURL en Python
Métaprogrammation avec Python
Python 3.3 avec Anaconda
SendKeys en Python
Méta-analyse en Python
Unittest en Python
Époque en Python
Discord en Python
Allemand en Python
DCI en Python
tri rapide en python
nCr en python
N-Gram en Python
Programmation avec Python
Plink en Python
Constante en Python
FizzBuzz en Python
Sqlite en Python
Étape AIC en Python
LINE-Bot [0] en Python
CSV en Python
Assemblage inversé avec Python
Réflexion en Python
Constante en Python
nCr en Python.
format en python
Scons en Python 3
Puyopuyo en python
python dans virtualenv
PPAP en Python
Quad-tree en Python
Réflexion en Python
Chimie avec Python
Hashable en Python
DirectLiNGAM en Python
LiNGAM en Python
Aplatir en Python
Aplatir en python
Module d'implémentation de file d'attente et Python "deque"
Liste triée en Python
AtCoder # 36 quotidien avec Python
Texte de cluster en Python
AtCoder # 2 tous les jours avec Python
Daily AtCoder # 32 en Python
Daily AtCoder # 6 en Python
Daily AtCoder # 18 en Python