ReLUレイヤの実装|Excel VBAでMNIST機械学習

本ページはゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装を参考にニューラルネットワークを作成していきます。参考書籍では「Affineレイヤ」「ReLUレイヤ」「Softmax-with-Lossレイヤ」という3つのレイヤを作成し、それらを組み合わせることでニューラルネットワークを構築していきます。本サイトでも同じように3つのレイヤをVBAで作成し実装していきます。

本ページではその中の「ReLUレイヤ」をVBAで実装していきます。

 

ReLUレイヤの機能

ReLUレイヤは入力された値にReLU関数を適用し活性化させる機能を持ちます。
本レイヤは「順伝播」と「逆伝播」の両機能をもっているため、このレイヤを呼び出すだけで簡単にニューラルネットワークを構築することができるようになっています。

 
機械学習の流れ 

今回作成していくニューラルネットワークをレイヤで表すと下図の通りです。

このレイヤの流れは以下のようになっています。(以下では上図の各レイヤを左から「Affine1」「ReLU」「Affine2」「Softmax-with-Loss」として説明していきます)

1. 入力値を「Affine1」に入れ、入力値と重みの総和を計算する。
2.「Affine1」の出力を「ReLU」に入れて活性化させる。
3.「ReLU」の出力を「Affine2」に入れ、入力値と重みの総和を計算する。
4.「Affine2」の出力を「Softmax-with-Loss」に入れ、活性化の結果/損失関数を求める。
5.「Softmax-with-Loss」から「Affine2」に逆伝播(Affine2のパラメータを更新)
6.「Affine2」から「ReLU」に逆伝播
7.「ReLU」から「Affine1」に逆伝播(Affine1のパラメータを更新)

上記の1~7を何百、何千回とループすることで「Affine1」と「Affine2」のパラメータ(重み/バイアス)が正解に近づくように徐々に更新されていきます。あとは損失関数をもとにループを止めれば学習終了といった流れになってます。

 

ReLUレイヤの実装

まずはクラスモジュールで「ReLU_Layer」というモジュールを作成します。
ReLUレイヤでは逆伝播時に「順伝播時の入力値」が必要になるため、値を保存することのできるクラスモジュールで作成します。

また「Option Base 1」を使い配列を「1」スタートにします。
これは要素数とインデックスを合わせ配列同士の計算をわかりやすくするためです。

以下はReLUレイヤの全コードです。

 
ReLUレイヤはPythonで書くと以下のようなコードです。(書籍のコード)
引数や関数名などはできる限りは揃えているのでPythonコードが読める方は見比べてみて下さい。

 
以下では各関数で何を行っているかを解説していきます。

 

Function forward

関数「forward」は名前のとおり順伝播を行う関数です。
順伝播といっても、入力された値に対してReLU関数で活性化させるだけです。
(図でいうと「a1」を「z1」に変換する部分)

ReLU関数は入力値が0以下の場合は0を0より大きい場合は入力値をそのまま返すという非常にシンプルな関数です。

この関数の引数としては「x()」があります。
これはAffineレイヤからの出力値が入った1次元配列です。
(先ほどの図でいう「a1」)

ループを使ってこの引数の配列の要素1つずつにReLU関数を適応させていきます。

また、順伝播時の入力「x()」の大きさによって逆伝播する値が変化します。
そのためここではReLU関数を適応させるとともに「mask()」というBoolean型の配列を使って、「x()」が0以下の場合は「True」、0より大きい場合は「False」として保存しています。たとえば「x()」の中身が、x(1,-1,0,2,3,-5,4,-1,3,6)の場合は「mask()」の中身はmask(F,T,T,F,F,T,F,T,F,F)となります。(T=True,F=False)

返り値は「x()」にReLU関数を適応させた1次元配列です。
「mask()」は逆伝播時に使用します。

 

Function backward

関数「backward」は名前のとおり逆伝播を行う関数です。
ReLU関数の逆伝播は順伝播時の入力値が0以下の場合は0を、0より大きい場合は前の層から逆伝播してきた「微分の値」をそのまま返します。

この関数の引数としては「dout()」があります。
これは逆伝播でいう前の層の関数「backward」で求めた「微分の値」が入った配列です。

この「微分の値」をすべての層に逆伝播していくことでAffineレイヤにある重み/バイアスパラメータを徐々に正解に近づけていくことができます。(Affineレイヤではこの逆伝播された「微分の値」を使うことでパラメータを更新していきます)

ReLU関数の逆伝播では、順伝播同様ループを使って「dout()」の要素を1つ1つチェックしていきます。「mask()」がTrueの場合(順伝播での入力値が0以下の場合)は要素の値は0に、「mask()」がFalseの場合(順伝播での入力値が0より大きい場合)は要素の値はそのままにします。

これら逆伝播のReLU関数を適用させた値は1次元配列の「dx()」に格納し、その配列を戻り値として返します。この「微分の値」が入った配列が次の層に渡されることで逆伝播が連鎖していきます。

 

まとめ

ここではゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装を参考にVBAでReLUレイヤの実装を行いました。

今回実装したReLUレイヤの機能をまとめると以下の通りです。

Function forward:順伝播(ReLU関数を適用する)
Function backward:逆伝播(逆伝播でのReLU関数を適用する)

ReLUレイヤは比較的シンプルな内容なので、何をやっているかはすぐに理解できると思います。

活性化関数なので入力された値を変化させるだけなので配列の”かたち”は変化しません。
つまり要素数が10の1次元配列「x()」が入力された場合は、活性化された要素数10の1次元配列が出力されるということです。

今回はReLU関数を使っていますがこの中身をSigmoid関数に変えればSigmoid関数を適用させることもできます。(実際に書籍ではSigmoidレイヤの実装方法も書かれています)
  

ニーラルネットワークはいくつものレイヤが紐づくことで学習が可能になります。
つまり本ページの内容だけではニューラルネットワーク内で何が行われているのか理解できません。
メインページよりいくつかのページと関連付けて見ることでようやく理解ができるようになります。

ニューラルネットワークについてはぜひ、時間をかけてじっくりと学んでください。

最終的なイメージが全くつかない人は、1度コピペでもいいのでニューラルネットワークをすべて構築して実際に機械学習を行ってみることをオススメします。

メインページ
 

 icon-book 参考書籍

 

AI, Deep Learning, VBA

Posted by Lic