【実はとても簡単だった!】誤差伝播法をシンプルにわかりやすく解説します。

ニューラルネットワークの計算の肝となる誤差伝播法

わかりやすい解説を読めば理解した気になるのですが、実際に自分で実装しようと思うと理解していないことに気づく。

管理人と同じ人はいませんか?

 

特にExcelで実装しようとすると、完璧に理解していないと実装で躓きます。

ライブラリーを使ってワープできるPythonと違って、ゼロからスクラッチするExcelだと、自分の理解だけが頼りなのです。

 

このような時には、必要最小限に簡単なモデルで考えてみることが一番です。

すると、なんてことはない、普通に偏微分すれば解けるじゃないか!

何でそんなに難しく解説するんだ!

と思ってしまいました。

 

ほとんどの解説にはδを定義してどのこうの。。。

と書いてありますが、そんなこと気にせずに普通に偏微分すればよいことが分かりました。

難しく考える必要なんてありません。

メモを作りましたので、参考にしてみて下さい。

 

表記方法の約束事

以前の記事で、

出荷量=人数×8+台数×2+10

の式は、ニューラルネットワークでは次のように描くことを紹介しました。

【今さら聞けない】ニューラルネットワークとは何かを身近な例で解説します。より抜粋

 

これをもう少し一般化すると次のように描けます。

 

バイアスは入力層から来る信号には関係ないため、独立してノードに加えています。

また2つの入力に重みを掛けて合計した値をuという変数に入れています。

それ以外に難しい所はありませんね。

 

これは入力層と出力層しかない単純パーセプトロンですが、隠れ層(中間層)を加えて多層パーセプトロンに拡張させてみましょう。

次のようになります。

 

先ほど出力層のノードで、前の層から来た信号に重みを掛けて合計しましたが、同じことを隠れ層のノードでも行います。

こうなると、重みwバイアスθ合計値uを層ごとに区別する必要がありますので、それぞれ右肩に層を表す記号HOを付けます。

上図で描いたように、隠れ層Hのグループは青色、出力層Oのグループは赤色になります。

このように重みは、その後のノードに紐づいていると考えることが重要です。

また、バイアスθは入力信号に依存せず、毎回それぞれのノードに加えるものですので、今後はわざわざ図には描かないことにします。

 

さて、ニューラルネットワークではそれぞれのノードにおいて、入力に重みを掛けて合計しているだけではありません。

合計した値を更に違う値に変換します。

この変換を行う関数のことを、活性化関数と呼んでいます。

なぜ変換するのかというと、こうすることでより複雑な問題が解けるようになるからです。

単に入力信号に重みを掛けて加えるだけでは、いくら隠れ層(中間層)を増やしたところで直線的な関係しかモデル化できません。

二次元グラフ上の点の集合を、直線で2つのグループに分けるようなことしかできないのです。

曲線でグループ分けしたいような場合には、非線形の活性化関数を入れないとできないのです。

 

従って、隠れ層と出力層にあるすべてのノードでは活性化関数による変換も行います。

図で表すと、次のようになります。

 

このように、それぞれのノードには2つの関数が入っていると考えます。

活性化関数はシグモイド関数ReLU関数などいろいろある中から、目的に応じて選びます。

今回は一番簡単な

f(u)=u

を活性化関数として話しを進めます。

簡単にいうと、何も変換せずにそのまま通す関数です。

恒等関数ともいいます。

 

さて、ここまでで入力層に2つのノード、隠れ層と出力層にそれぞれ1つずつのノードを持つモデルを表しましたが、誤差伝播法を理解するためには最低でも入力層:2つのノード隠れ層:3つのノード出力層:2つのノードを持つモデルで考える必要があります。

これを図で表すと、次のようになります。

 

紐づいているグループごとに色分けしてあります。

ここで新しいことは、それぞれの層に複数のノードがある時には、次のような規則によって文字を区別することです。

  1. ノード名をH1やO1のように、層名の右下に数字を付けて区別する
  2. uとzの右下にも数字を付けて区別する
  3. 重みwの右下には2つの数字を付けて区別する。数字の順序は次の規則に従う

 

重みwの右下に付ける数字の順番は、逆に定義する人もいます。

単なる決め事ですので、ここでは行き先を先に書く定義で進めます。

 

まずは簡単な出力層から

さて、本題に入ります。

誤差伝播法は損失関数の勾配を簡単に求めるための方法です。

なぜ勾配を求めるのかというと、損失関数の値が最小になる時の重みwバイアスθを求めたいからです。

この重みwとバイアスθは初めに初期値をテキトーに決めますが、勾配を求めることで、プラスマイナスどちらの方向にどくれくらいwやθを動かせば良いかということが分かります。

これを勾配降下法といいました。

>> 【Excelでわかりやすく】勾配降下法で最小値が見つかる理由を視覚的に理解する

>> 【例題をExcelでわかりやすく】最急降下法で単回帰の最小二乗法を解いてみる

 

この勾配の計算は単純パーセプトロンでは簡単でした。

>> 【スーパーわかりやすく!】Excelで単純パーセプトロンの具体例を試してみる

 

ところが、多層パーセプトロンでは少し難しくなります。

それを簡単にする道しるべを与えてくれるのが誤差伝播法です。

誤差伝播法では、「まず最初に出力層の重みから計算しなさい」と教えています。

ですので、まず出力層の重みから求めてみましょう。

 

出力zO1とzO2の正解がt1t2だとします。

正解とは教師データのことですので、teacherの頭文字を取ってtnとします。

 

すると、損失関数は次式のように誤差の平方和で表されます。

E={(zO1-t1)2+(zO2-t2)2}/2

ここで、zO1zO2はそれぞれuO1uO2同じです。

なぜなら、今回の活性化関数f(u)=uという、そのまま通す関数を仮定しているからです。

ですので、zO1とzO2はそれぞれ次式で表されます。

zO1=uO1=wO11zH1+ wO12zH2+ wO13zH3+θO1

zO2=uO2=wO21zH1+ wO22zH2+ wO23zH3+θO2

 

ここで、wO11の勾配を求めてみましょう。

つまり、E/∂ wO11を計算するということです。

一瞬ひるみますが、これはそれほど難しくはありません。

高校で習った合成関数の微分を使えばいいからです。

>> 合成関数の微分公式と例題7問|高校数学の美しい物語

 

損失関数EはzO1の関数で、zO1wO11の関数ですので、

∂E/∂ wO11 =∂E/∂ zO1 ・∂zO1/∂ wO11

です。

∂E/∂ zO1 = zO1-t1

∂zO1/∂ wO11 = zH1

ですので、

∂E/∂ wO11 = (zO1-t1) zH1

と簡単に計算できます。

出力層の重みはバイアスθも含めるとあと7個ありますが、すべて同じように計算できます。

 

次に隠れ層、でも同じこと

次に隠れ層の重みを計算します。

この計算は先ほどより少し難しくなります。

なぜでしょうか?

wH11の勾配、つまりE/∂ wH11 の計算をしてみましょう。

 

先ほどの式

zO1=uO1=wO11zH1+ wO12zH2+ wO13zH3+θO1

zO2=uO2=wO21zH1+ wO22zH2+ wO23zH3+θO2

にzH1が含まれていますが、この中にwH11

zH1=uH1=wH11x1+ wH12x2 +θH1

のように入れ子で含まれているため、先ほどのように簡単には微分ができないのです。

 

しかし、ひるむ必要はありません。

ここでも合成関数の微分を使えばいいのです。

先ほど出力層の重みの微分では、次式のように分解しました。

∂E/∂ wO11 =∂E/∂ zO1 ∂zO1/∂ wO11

これはEがzO1 の関数で、zO1wO11 の関数だからでした。

 

今度はEがzO1 の関数で、zO1zH1 の関数で、zH1wH11 の関数です。

つまり、一つ入れ子が増えただけです。

ですので、そのまま計算すればいいだけです。

∂E/∂ wH11 =∂E/∂ zH1 ・∂zH1/∂ wH11

=(∂E/∂ zO1 ∂zO1/∂ zH1 +∂E/∂ zO2 ・∂zO2/∂ zH1)・∂zH1/∂ wH11

2行目で合成関数の微分を多変数に拡張した連鎖律を使っていますが、これはそんなに難しくありません。

こちらを参考にしてみて下さい。

>> 連鎖律(多変数関数の合成関数の微分)|高校数学の美しい物語

 

あとは各項の偏微分を計算すればいいだけです。

∂E/∂ zO1 は出力層で計算したのと同じです。

残りの項は次のようになります。

∂zO1/∂ zH1 = wO11

∂E/∂ zO2 = zO2-t2

∂zO2/∂ zH1 = wO21

∂zH1/∂ wH11 = x1

 

従って、

∂E/∂ wH11 = {(zO1-t1) wO11 + (zO2-t2) wO21} x1

です。

何も難しくありませんね。

他の隠れ層の重みも同じようにして計算できます。

 

以上のようにすれば普通に勾配を求めることができるのですが、なぜこのやり方にわざわざ誤差伝播法という仰々しい名前が付いているのでしょうか?

それは、∂E/∂ zH1 ∂E/∂ zO1 を使って求めることができるからです。

Oは出力層でHは隠れ層ですが、OはHの次の層ともいうことができます。

つまり、O層はH+1層なのです。

これは何を意味しているかというと、H+1層の∂E/∂ zH+11 が分かれば、H層の∂E/∂ zH1 が偏微分なんてしなくても簡単に求まるということです。

∂E/∂ zH1 =∂E/∂ zO1 ・∂zO1/∂ zH1 +∂E/∂ zO2 ・∂zO2/∂ zH1

でしたね。

O層はH+1層なので、

∂E/∂ zH1 =∂E/∂ zH+11 ・∂zH+11/∂ zH1 +∂E/∂ zH+12 ・∂zH+12/∂ zH1

=∂E/∂ zH+11 ・wH+111+∂E/∂ zH+12 ・wH+121

です。

そして一番最後の層は出力層で、そのE/∂ zH(Last)iは簡単に求まるので、その前の隠れ層のE/∂ zHiも遡ってすべて求めることができるのです。

その他の項の偏微分は簡単に求められることもポイントです。

なお、∂E/∂ zH(Last)i(zH(Last)i-ti)ですので、出力と教師データの差、つまり誤差です。

この誤差を前の層に伝播させることによって連鎖的にすべての勾配が求められるので、誤差伝播法というのです。

 

次回は、誤差伝播法をExcelに実装して、ちょっとした画像処理を試してみたいと思います。