ゼロから作るRNN1

機械学習 Python R

ゼロから作るDeep Learning 2のRNN に関するコードを写経、解説していきます。お仕事で使う機会があったけど理解があやふやだったので、忘備録気味です。keras を使う際のパラメーターが何をするパラメーターか解説したいと思います。
今回は、シンプルなRNNそのものについてのお話です。参考書は以下です。

ゼロから作るdeep learning

RNNとは?

大体の解説や、使い方は以下の記事を参考にしてください。

リカレントニューラルネットワーク(RNN)
ニューラルネットワークモデルの一つに、リカレントニューラルネットワーク(RNN)と呼ばれるものがあります。自己相関の高いデータに対して有用なモデルです。RNN, LSTM, GRUの解説をして、映画レビューの分類問題で3つのモデルの特徴を掴みます。

RNNとは、リカレントニューラルネットワーク(Recurrent Neural Network )の略語です。ニューラルネットワークの変種で、データ同士に関係があるという前提のモデルです。RNN層を計算グラフで描くと以下のようになります。

RNN計算グラフ
RNNの計算グラフ

\(x_t \)が入力で\(h_t \)が出力です。大きな特徴は、出力\(h_t \)を入力 \( x_{t+1 }\)に加える事です。過去の情報を未来へ伝えていくイメージです。RNN層はそれ自体がモデルのような雰囲気がありますが、あくまで1つの層です。

RNNの実装

上に載せた計算グラフのようなモデルをpython で実装します。ニューラルネットワークとの違いは、活性化関数が\( \tanh \)である点と、過去の出力 \(h_{t-1} \)も全結合されている点です。誤差逆伝搬で必要な\( \tanh(x) =\frac{\sinh (x)}{\cosh (x) } \) の微分は以下のように計算出来ます。
$$\begin{eqnarray}
\tanh ^{,} (x)&=& 1- \sinh (x) \frac{ \sinh (x) }{\cosh ^2 (x) }\\
&=& 1-\tanh ^2 (x)
\end{eqnarray} $$
RNN層の時刻\(t \)の出力は以下の形をしている事に注意1 しましょう。
$$\begin{eqnarray}
h_t = \tanh \left(x_t W_{x_t} +h_{t-1} W_{t-1} +b_t \right)
\end{eqnarray} $$
それぞれの変数での微分は以下のようになります。
$$\begin{eqnarray}
\frac{\partial h_t}{\partial W_x} &=& \tanh ^{,} (x) \frac{\partial \left( x W_{x} +h W_{h} +b \right) }{\partial W_x} \\
&=& \tanh ^{,} (x) *x^{T} \\
\nabla _{x}h_t&=& \tanh ^{,}(x) \nabla _{x} \left( x W_{x} +h W_{h} +b \right) \\
&=& \tanh ^{,} (x) W_x ^{T} \\
\nabla _{b} h_t&=& \tanh ^{,}(x) \nabla _{b}\left( x W_{x} +h W_{h} +b \right) \\
&=&\sum \tanh ^{,}(x)
\end{eqnarray} $$
それではRNN層を実装します。ニューラルネットワークと殆ど同じ2 なので簡単です。

これでRNN層が実装出来ます。

ニューラルネットワークでも同様ですが、誤差逆伝搬では、後ろにある層から微分流れてきます。式で書くと以下のような状況になっています。本当の出力を\(O \)で表します。
$$\begin{eqnarray}
\nabla _{x} O= dh_{next}\nabla _{x} \tanh \left(x W_{x} +h W_{h} +b \right)
\end{eqnarray} $$
\(dh_{next} \)には色々な微分係数が入っています。

実際に使う際3には、勾配消失が起きる事を進歩居してバッチ学習をします。次は、バッチ学習が可能なRNNを実装しましょう。

バッチ学習用のRNN

例えば、\(t \)が\( 0\)から\(100000 \)まであるようなデータ\(x_t \)を一回で学習しようとすると、勾配が\(t=0 \)まで伝わる前に\( 0\)になってしまい、前半のデータの情報を学習に取り込むことが出来ません。
そこで、例えば\( t=10 \)毎にデータを区切って、それぞれに対して学習をします。ただし、区切るのは微分の情報だけで、順方向の情報はそのまま流します。
例えば、\(t=1000\)のデータで, 100個毎に区切り、バッチ数を2とすると、データを800個に分ける事になります。
$$\begin{eqnarray}
( x_0 , \cdots , x_9 ) \\
(x_{100} , \cdots, x_{109}) \\
\vdots\\
( x_{800} , \cdots , x_{809} ) \\
(x_{900} , \cdots, x_{999}) \\
\end{eqnarray}$$
この手法を TBTT(Truncated Backpropagation Through Time)と呼んだりします。
これをTimeRNN というクラスで実装します。

誤差逆伝搬が1つのバッチで完結していることに注目です。

次回の記事はこちら。
https://masamunetogetoge.com/makernn2

まとめ

  • RNNの概要を説明した
  • シンプルなRNN層を実装した
  • 勾配消失を防ぐためのバッチ学習に対応したRNNを実装した
  1. 出てくる文字は出力と大文字以外はベクトルです。
  2. ニューラルネットワークの実装はこちらからどうぞhttps://masamunetogetoge.com/make-neuralnet-1
  3. そもそもこのようなシンプルなRNNは使われませんが
タイトルとURLをコピーしました