RNN#

シンプルなRNN#

時点\(t\)の予測値\(\boldsymbol{y}_t\)を、その時点までに入手可能な特徴量\(\boldsymbol{x}_t\)で予測する関数\(\boldsymbol{y}_t = f(\boldsymbol{x}_t)\)を求めたい。 (添字は同じ\(t\)だが、\(\boldsymbol{x}_t\)\(\boldsymbol{y}_t\)より古い時点のデータとなることに注意)

特徴量だけでなく、1時点前の目的変数\(\boldsymbol{y}_{t-1}\)を利用すれば、より精度は良くなると考えられる

\[ \newcommand{\b}[1]{\boldsymbol{#1}} \b{y}_t = f(\b{x}_t, \b{y}_{t-1}) \]

最もシンプルなモデルは行列\(\b{W}_x, \b{W}_y\)を用いて

\[ \b{y}_t = \b{W}_x \b{x}_t + \b{W}_y \b{y}_{t-1} \]

と記述し、重みパラメータ\(\b{W}_x, \b{W}_y\)を求める方法が考えられる。

ディープラーニングとして扱う場合、活性化関数\(h(\cdot)\)を通した\(\b{z}_t = \b{h}(\b{a}_t)\)を考えて次のように書き換える形が考えられる

\[ \b{y}_t = \b{W}_z \b{z}_t \]

ここで

\[ \b{a}_t = \b{W}_z \b{x} + \tilde{\b{W}}_z \b{z}_{t-1} \]

である。 また\(\b{a} = (a_1, \cdots, a_K)^\top, \b{h}(\b{a})=(1, h(a_1), \cdots, h(a_K))^\top\)である。

活性化関数にはシグモイド関数やReLU関数でもよいが、RNNの場合は双曲線正接(tanh)関数

\[ f_{tanh}(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}} \]

を用いることが多い。tanhはシグモイド関数と形状が似ているが、値域が\([-1, 1]\)と負の値を許しており、また二次微分の減衰がゆっくりとゼロになるため勾配消失が起きにくいという特性がある。

定数項を書く場合#

中間層

\[ h_t = f(W^{(in)} x_t + W^{(hidden)} h_{t-1} + b_f) \]

出力層

\[ y_t = g(W^{(out)} h_{t} + b_g) \]

行列じゃない表記にすると、\(j\)番目のユニットは

\[\begin{split} \begin{align} h^{(t)}_j &= f\left( \sum^{N(in)}_{i=1} w^{(in)}_{ij} x_j + \sum^{N(hidden)}_{i=1} w^{(hidden)}_{ij} h_j^{(t-1)} + b_j^{(f)} \right) \\ y^{(t)}_j &= g \left( \sum^{N(out)}_{i=1} w^{(out)}_{ij} h_j^{(t)} + b^{(g)}_j \right) \end{align} \end{split}\]

と思われる

実装(Keras)#

kerasだとSimpleRNNというクラスがあり、上記のようなRNNを呼び出すことができる

tf.keras.layers.SimpleRNN  |  TensorFlow v2.12.0

実装(Pytorch)#

実装(Python)#