再帰型ニューラルネットワーク(RNN)のBPTTをExcelに実装してみた。
管理人の住む国でも10月1日からコロナ制限が緩和され、週末はすっかり羽を伸ばしてしまいました。
一つ気になるのは、我が千葉ロッテマリーンズがマジック点灯目前で足踏みしてしまったことです。
さっさと優勝を決めて、CSと日本シリーズで短期決戦に滅法強いところを見せてもらいたいものです。
再帰型ニューラルネットワーク(RNN)とは?
記憶を持たせた再帰型ニューラルネットワーク
さて、野球では土壇場での監督の采配が勝負を分けることがありますね。
12回裏もう負けはない状態の時、先頭打者の結果次第で、次打者の守備固め選手に誰を代打に送るかの判断は、相手チームのピッチャー交代にも左右されます。
監督には、このように時系列の状況に応じた判断が求められます。
このような判断を行う時には、時系列の状況を記憶していないとできません。
相手チームのピッチャーが右から左に変わったとしても、その前のバッターが凡打に倒れたのか、3塁打を打ったのかによって、送る代打の顔ぶれは変わってくるかもしれないからです。
このような記憶を持たせたニューラルネットワークのことを、再帰型ニューラルネットワーク(Recurrent Neural Network:RNN)といいます。
自然言語処理での例
機械翻訳などの自然言語処理によく用いられています。
例えば、
「私は学校へ行きます。」
という文章を英語に翻訳する場合を考えてみます。
キーボードから
「私は」
と打ち込まれた時には、
「私はロッテファンです。」
「私は飲み会を楽しみにしています。」
など、その後どんな文章になるのか見当がつきません。
すると、ニューラルネットワークは沢山の英単語を候補として用意しておかないといけません。
ところが
「私は学校へ」
まで打ち込まれると、「行きます」か「行きません」くらいに候補が絞られます。
ニューラルネットワークとしては、少ない候補の中から効率的に英文を組み立てられるのです。
昔の中間処理情報を今の入力に並列に加える
このようにニューラルネットワークに記憶を持たせることは大変有用ですが、その原理は至って単純です。
昔の中間処理情報を今の入力に並列に加えるのです。
先ほどの例で言うと、「私は」の中間処理情報を捨ててしまわないで、「学校へ」を処理する時に一緒に使います。
そうすれば「私は」も「学校へ」も、両方判断に使うことができるという当たり前の考え方です。
再帰型ニューラルネットワークは可変長の入力に対応できる
しかし、ここで一つの疑問が沸き起こります。
「私は」も「学校へ」も2つの入力として一緒に処理すれば良いのではないか?
つまり、次のようにしてはどうかということです。
確かにこの場合はそれでも良いと思うのですが、文には短文もあれば長文もあります。
入力層のユニットの数が限られていたら、長文ではユニットが足りなくなるかもしれませんね。
この再帰型ニューラルネットワーク(RNN)には、可変長の入力に対応できるという長所もあるのです。
バックプロパゲーションスルータイム(BPTT)とは?
通常のバックプロパゲーション(誤差伝播法)の計算式
このようにアイデア自体は単純なRNNですが、問題はどのようにパラメータを最適化するかです。
パラメータの最適化には誤差伝播法を使うのが基本ですが、RNNでもそれを使います。
通常のニューラルネットワークにおける誤差の伝播の仕方は、次の通りでした。
まず、出力と教師データとの差z-tをf’(u)倍した値が出力層の誤差になりました。(赤字)
次に、この出力層の誤差に各出力層への重みを掛けた値を、すべての出力層について合計した値が隠れ層の誤差になります。(青字)
これらの誤差に各ユニットへの信号を掛けた値が、その信号の重みの勾配になります。
バックプロパゲーションスルータイム(BPTT)の計算式
この考え方はRNNでも同じで、下図において赤線で囲んだ箇所だけが追加になります。
隠れ層(1)は前回の入力の隠れ層、隠れ層(2)は今回の入力の隠れ層を指します。
隠れ層(1)の誤差が追加されるだけです。
これに隠れ層(1)から隠れ層(2)への信号zH(1)1やzH(1)2をかけるとr1やr2の勾配になるのも、通常の誤差伝播法と同じです。
時空を遡って誤差が伝播するのでBackpropagation through Time(BPTT)と呼ばれています。
バレンタイン監督の頭脳をRNNで構築する
想定場面
それでは、BPTTを使ったRNNのパラメータ最適化をExcelで試してみましょう。
冒頭に述べた場面を使います。
ロッテ対中日の日本シリーズ、12回表が終わった時点で3対3の同点。
裏のロッテの攻撃で点が入ればサヨナラ勝ち、無得点に終われば引き分けです。
この回のロッテの二人目のバッターは守備要員で打撃は全く期待できないため、代打を送ることは決定しています。
代打要員としては福浦、堀、サブローの3人が控えています。
中日のピッチャーは吉見。
リリーフとしては浅尾と岩瀬が控えています。
このような場面で、ロッテのバレンタイン監督は先頭バッターの結果によって、次のような選手起用をしようと考えています。
このバレンタイン監督の頭脳をRNNで構築してみましょう。
RNNに定式化する
まずは問題を定式化します。
この場合、先頭打者の結果を見てから、中日の落合監督がピッチャー交代を決めるので、
先頭打者の結果 >> ピッチャー交代
は時系列です。
そこで、先頭打者の結果を最初の入力(X-1)、ピッチャー交代を後の入力(X-2)とします。
出力は3つとします。
それぞれ代打福浦の確率(O1)、代打堀の確率(O2)、代打サブローの確率(O3)です。
そして、X-1とX-2が入力された後に、代打が福浦のケースではO1の値が最大、堀のケースではO2が最大、サブローのケースではO3が最大になるような結果を返すようなRNNを構築できれば良いことになります。
X-1には6択、X-2には3択ありますので、それぞれ二進法で表すことにしましょう。
つまりこういうことです。
X-1
アウト・・・001
四球・・・010
エラー出塁・・・011
ヒット・・・100
二塁打・・・101
三塁打・・・110
X-2
続投・・・001
浅尾・・・010
岩瀬・・・011
教師データを作る
また、この時の正解データは3通りありますので、次のように表すことにします。
福浦・・・100
堀・・・010
サブロー・・・001
すると、教師データは次のように18組できます。
Excelに実装する
これを計算シートに入力して何度も何度も学習させます。
隠れ層は2層として、勾配アルゴリズムは最急降下法を使います。
計算シートは次のように作成しました。
横に長いので3枚に分けます。
(1枚目)
(2枚目)
(3枚目)
VBAでループ処理させることにより収束
なかなか収束しなかったためExcelだけで作ることを諦め、VBA(マクロ)を使いました。
18組の教師データを何回も学習させますが、Excelだけでやろうとするととんでもない行数になってしまい、動きが重くなりフリーズしてしまったからです。
そこで、18組の教師データを3回転だけExcelで計算し、3回目の計算が終わったパラメータを2回目のパラメータに貼り付け、再度3回目を計算するというようにループ処理させました。
一番左の列で18組の教師データに対する正解率を計算していますので、これが100%になるまで繰り返しました。
結果、594回目で収束しました。
最適化されたパラメータは次の通りです。
これで、もしバレンタイン監督にイニング途中で何かあっても、ニューロ君が代行できるようになりました。
異なるパラメータで同じ判断をするニューラルネットワークになることもある
ちなみに、上記のパラメータは唯一の解ではありません。
パラメータの初期値を変えて計算した場合には、下記のように全く異なるパラメータで収束しました。
これは「脳の中身が全く異なる別の人が同じ判断をすることがある」という人間社会でよくあることを表しているようで興味深い結果です。