情報学部大学生のダラダラ日記

β日記

機械学習や日記っぽいものを書きます

誤差逆伝播法についてできるだけ丁寧に初心者がまとめる

スポンサーリンク

導入

はじめに

勾配法において、損失関数を重みにおいて偏微分しそれを用いて重みを更新します。その手法の一種として以前に数値微分法という微分の定義に基づき、近似を用いることで勾配を求める手法をまとめました。今回は勾配を求める手法の1つとして誤差逆伝播法についてできるだけ丁寧にまとめたいと思います。僕自身その道について未だ初心者であるので同じような方の助けになれば幸いです。

parco1021.hatenablog.com

 

おねがい

本記事は勉強中の筆者が書いたものです。ゆえに少し解釈違いがあったり、文字が違っていたりするかもしれません。そういった場合にはコメントまたは下の問い合わせフォームから教えていただけると幸いです。

また、誤差逆伝播法を学ぶにあたり文章を読むだけでなく手元に紙とペンを用意して数式を書きながら読んでいただければ理解が捗ると思います。

誤差逆伝播法って聞くと…??

僕は未だ自分でモデルを組む等したことがありません。なので誤差逆伝播法についての認識は"勾配を求めるいい感じの方法"ぐらいでしかないです。その認識は実際に使ってみないと変わらないと思うので今のところはこれで良しとします。

大学の講義や教科書でのBackpropの説明はほとんど,「教師あり学習の文脈で多層パーセプトロンを識別器あるいは関数近似器として訓練する」という文脈でなされます.そのため,初学者はBackpropは教師あり学習のためのアルゴリズムであると誤解してしまうケースが多々あるのではないかと思います.しかし後で説明する通り,Backpropは単に損失関数の微分を効率的に計算する手法の1つであって教師あり学習とか教師なし学習とかは関係ありません

引用元:https://qiita.com/Ugo-Nama/items/04814a13c9ea84978a4c#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB

だそうです。僕は講義で習っておらず、現場でも使っていないのでその誤認はしていないので気を付けます。

ニューラルネットモデル

今回扱うニューラルネットモデルを以下に示します。

f:id:Parco1021:20200112181056p:plain

 今回は、簡略化のために中間層を1層とします。それぞれの変数の定義をします。

  • {\displaystyle x }…入力
  • {\displaystyle v,w }…重み
  • {\displaystyle h(),g() }…活性化関数
  • {\displaystyle b_j=\sum_{i=0}^{D} w_{ji}x_i }

→前の層からの出力(x)に重み(w)を掛けたものを全ての矢印において行っている

  • {\displaystyle z_j=h(b_j) }

→先ほど求めたbを活性化関数に引数として渡す。これにより求めたzが次の層へ渡される

  • {\displaystyle a_k=\sum_{j=0}^{M} v_{kj}z_j }
  • {\displaystyle y_k=g(a_k) }
  • {\displaystyle t_k }…教師データ

{\displaystyle δ }については後述します。

 

誤差逆伝播

では、誤差逆伝播法についてやっていきましょう。誤差逆伝播は簡単に言うと、出力層の重み{\displaystyle v }を更新してから中間層の重み{\displaystyle w }を更新するように、入力層→出力層ではなく、出力層→入力層へと流れていく様子からこの名前が付けられました。バックプロパケーション誤差逆伝搬法とも呼ばれます。

最終的にバックプロップによって最小化したい損失関数は以下のようになります。

{\displaystyle E(v,w)=\frac{1}{N}\sum_{n=0}^{N-1} E_n(v,w) }

この式の意味するところは損失関数を学習に使うデータ数{\displaystyle N }だけ足して平均したものが目的となる関数であるということです。

この関数を最小化するために勾配を求めます。つまり各データ{\displaystyle n }に対する勾配{\displaystyle \frac{∂E_n}{∂w} }を得なければなりません。求めて平均をとることで{\displaystyle \frac{∂E}{∂w} }が得られます。当然、{\displaystyle wだけでなく、v }における勾配も求める必要があります。

{\displaystyle \frac{∂E}{∂v} }を求める

連鎖律を用いて{\displaystyle \frac{∂E}{∂v}を求めます。 }

{\displaystyle \frac{∂E}{∂v}=\frac{∂E}{∂a}\frac{∂a}{∂v} }

となるのでそれぞれ分解します。繰り返しになりますが、{\displaystyle v }{\displaystyle jk }間の重みであり、{\displaystyle aはj層 }からの入力総和です。

まず、

{\displaystyle \frac{∂a}{∂v}=\frac{∂}{∂v_kj}(\sum_{j} v_{kj}z_j)=\frac{∂}{∂v_kj}( v_{k0}z_0+v_{k1}z_1+…v_{kj}z_j) }=z_jとなります。

次に、

{\displaystyle δ^{(2)}_k= \frac{∂E}{∂a} }とすると

{\displaystyle \frac{∂E}{∂v_kj}=δ^{(2)}_kz_j}となり簡単な式になりました!

f:id:Parco1021:20200130171048p:plain>ちょっと待ちなさい!{\displaystyle δ^{(2)}_k}っていったいなんなのよ!

ごめんなさいお母さん!!

{\displaystyle δ^{(2)}_k= \frac{∂E}{∂a}=\frac{∂E}{∂y}\frac{∂y}{∂a}=\frac{∂E}{∂y}g'(a) }

{\displaystyle \frac{∂y}{∂a} }{\displaystyle y=g(a) }となっているので当然ですね。例えば損失関数を二乗誤差とし、係数など諸々を無視する{\displaystyle \frac{∂E}{∂y}は大体y-t }となります。{\displaystyle yは出力であり、tは教師データです。}ゆえに概要としては結合先で生じた誤差に関する変数といった感じです。

つまり、{\displaystyle \frac{∂E}{∂v_kj}は、}結合元のニューロンの出力{\displaystyle z_j}と結合先での誤差{\displaystyle δ^{(2)}_k}を掛けたものであることがわかります。

重みの更新規則は

{\displaystyle v^{r+1}_{kj}=v^r_{kj}-α\frac{∂E}{∂v_{kj}}=v^r_{kj}-αδ^{(2)}_kz_j}となります。{\displaystyle αは定数です。}

以上で重み{\displaystyle v}については終わりです。次は中間層周りの重み{\displaystyle w}についてです。

 

{\displaystyle \frac{∂E}{∂w} }を求める

では{\displaystyle \frac{∂E}{∂w}}を求めていきましょう。数式が一見複雑そうに見えますが、内容としてはこれまでと同様レベルです。一緒に頑張りましょう。

{\displaystyle \frac{∂E}{∂w}=\frac{∂E}{∂b}\frac{∂b}{∂w} }となります。

ここで先ほどと同様に結合先への総和{\displaystyle b}があるので

{\displaystyle \frac{∂E}{∂b}=δ^{(1)}_j}とします。

{\displaystyle \frac{∂b}{∂w}=\frac{∂}{∂w_ji}(\sum_{i} w_{ji}x_i)=\frac{∂}{∂w_ji}( w_{j0}x_0+w_{j1}x_1+…w_{ji}x_i) =x_i}

よって

{\displaystyle \frac{∂E}{∂w}=δ^{(1)}_jx_i }となり、先ほど同様簡単な形になりました!

f:id:Parco1021:20200130171048p:plain

 

…はい。例のごとく{\displaystyle δ^{(1)}_j}が何を指すのか調査しましょう。k層があるのでΣを用います。

{\displaystyle δ^{(1)}_j=\frac{∂E}{∂b}=\sum_{k}\frac{∂E}{∂y_k}\frac{∂y_k}{∂a_k}\frac{∂a_k}{∂z_j}\frac{∂z_j}{∂b_j}}

{\displaystyle \frac{∂E}{∂y}\frac{∂y}{∂a}=δ^{(2)}_k }であり、{\displaystyle \frac{∂a}{∂z}=v_{kj} }であり、さらに{\displaystyle \frac{∂z}{∂b}= h'(x)}となります。

これらを用いると{\displaystyle δ^{(1)}_j }

{\displaystyle δ^{(1)}_j=h'(b_j)\sum_{k}v_{kj}δ^{(2)}_k }となります。

この式と以下の図に着目してみてください。本来のNNは入力層→出力層(左から右)へと処理が為されるのに対し、中間層の{\displaystyle δ^{(1)}_j}を求めるために出力層から{\displaystyle δ^{(2)}_k}と中間層~出力層間の重み{\displaystyle v}を掛け合わせたものを逆方向へ伝達させていることがわかります。

{\displaystyle δ^{(2)}_k}は先ほども述べた通り出力層の誤差です。誤差を逆方向へ伝播させていることから誤差逆伝播法と言います(と思います)。

 

f:id:Parco1021:20200201203215p:plain

{\displaystyle \frac{∂E}{∂w}が求まったので重みwの }更新規則を書きます。
{\displaystyle w^{r+1}_{ji}=w^r_{ji}-α\frac{∂E}{∂w_{ji}}=w^r_{ji}-αδ^{(1)}_jx_i}

 

ここまで、誤差逆伝播法について数式を交えつつ解説してきました。次はより抽象的に図を主としてイメージを掴みます。

 

誤差逆伝播法のまとめ

①NNにxを入力し、b,z,a,さらに出力yを得て全て保持しておく

入力し出力を得るのでここは普通に順伝播(左から右)

f:id:Parco1021:20200201210825p:plain

 

 

②教師データtと出力yから出力層の誤差δを計算する。そして逆方向へ伝播し、重みvと乗算しΣ計算することで中間層の誤差を計算する

f:id:Parco1021:20200201212023p:plain

 

③δを用いて重みを更新する 

f:id:Parco1021:20200201213547p:plain

 

さいごに

いかがでしたでしょうか。数式は多かったと思いますが1つ1つ丁寧に追っていけば大学1年生レベルのものであることがわかると思います。誤差逆伝播法を使うと何がメリットで何がデメリットなのかわからないので今後調べていきたいと思います。例えば誤差逆伝播法は"人間っぽい"考え方ではないから別の手法を考えていると研究室の先輩が輪講で言ってたような言ってなかったような…みたいな。

 

参考文献

qiita.com

 

 

おわり。

もしよければ↓ぽちっと↓お願いします。

ブログランキング・にほんブログ村へにほんブログ村

 

PVアクセスランキング にほんブログ村

スポンサーリンク