【フレームワークを使用せず】ゼロから作る物体検出AIモデル
【No.4】ニューラルネットワークの理解(その4)
1. 本記事について
本記事はニューラルネットワークがどういったものかについて解説していきます。その1〜その4の4回を予定しており、本記事はその4です。
本シリーズを進めていくにあたり、参考にさせていただく書籍があります。オライリー・ジャパンから出版されている「ゼロから作るDeep Learning ーPythonで学ぶディープラーニングの理論と実装」です。
本記事は、上記書籍を参考にさせていただいております。
2. 誤差逆伝播法とは
誤差逆伝播法とは、あえて一言でいうと「ニューラルネットワークにおける、微分の計算方法」となります。
詳しい内容は後述しますが、よく前回解説した勾配法と混同されがちです。
以下の様な理解をするとすっきりいくと思います。
勾配法は以下の式で計算する。
「パラメータの更新を勾配法を用いて行うのだが、その際計算が大変複雑なので、それを誤差逆伝播法を用いて計算している」という理解です。
では、具体的にどの様に誤差逆伝播法を使って\(\frac{∂E}{∂W}\)を計算するのか見ていきます。
3. 計算に必要な知識
先に述べた様に、誤差逆伝播法は微分の計算方法になります。
なので、基本的に微分を使用していくのですが、特に偏微分と連鎖率を用いて進めていきます。
本章で、簡単に上記2つを解説します。
偏微分
偏微分は、変数が複数ある関数を微分する時に用いられます。
一つの変数にのみ注目し、それ以外の変数を定数として扱います。
以下に例を示します。
上記式を、xで偏微分する時、yを定数として扱います。yが定数なので、結果は以下となります。
同様に、yで偏微分する時、xを定数として扱うので、以下となります。
逆伝播の計算時、この考え方がすごく出てくるので、押さえておきます。
連鎖率
連鎖率とは、合成関数の微分を行う時に使用する計算式です。
本来合成関数から解説すべきですが、今回割愛させていただきます。
とにかく「こんな感じの計算をする」という部分の理解に絞って進めていきます。
理解しやすい様に、1変数→2変数→多変数という流れでみていきます。
1変数
まず、以下の関数を考えます。
上記式の\(y\)は\(u\)の関数と言え、且つ、\(u\)は\(x\)の関数と言えます。
これは、\(y = f(g(x))\)とも書くことができます。
上記式について、\(y\)を\(x\)について微分する時、以下の様に表せます。
具体例として、以下の式を考えます。
上記を\(y\)を\(x\)について微分する時、頑張って展開して解くことももちろんできますが、\(y = (3x^2 + 9)^4\)の\(3x^2 + 9\)を\(u\)として考えることもできます。
上記式において、\(y\)を\(x\)について微分する時、以下の様に解くことができます。
\(\frac{dy}{du} = 3u^3\)、\(\frac{du}{dx} = 6x\)なので、上記の様に計算することが可能です。
2変数
次に、以下の関数を考えてみます。
上記式の\(z\)は\(u\)の関数と言え、且つ、\(u\)は\(x, y\)の関数と言えます。
また、\(z\)は\(v\)の関数とも言え、且つ、\(v\)は\(x, y\)の関数と言えます。
これは、\(z = f(g(x, y), h(x, y))\)とも書くことができます。
上記式について、\(z\)を\(x\)について微分する時、以下の様に表せます。
具体例として、以下の式を考えます。
上記を\(z\)を\(x\)について微分する時、頑張って展開して解くことももちろんできますが、\((x^3 + y^4)\)を\(u\)として、また\(\sin xy\)を\(v\)として考えることもできます。
上記式において、\(z\)を\(x\)について微分する時、以下の様に解くことができます。
\(\frac{∂z}{∂u} = \sin xy\)、\(\frac{∂u}{∂x} = 3x^2\)、\(\frac{∂z}{∂v} = (x^3 + y^4)\)、\(\frac{∂v}{∂x} = y \cos xy\)なので、上記の様に計算することが可能です。
多変数
最後に、以下の関数を考えてみます。
上記式の\(z\)は\(u_1\)の関数と言え、且つ、\(u_1\)は\(x_1, x_2, x_3, ...\)の関数と言えます。
また、\(z\)は\(u_2\)の関数とも言え、且つ、\(u_2\)は\(x_1, x_2, x_3, ...\)の関数と言えます。
さらに、\(z\)は\(u_3\)の関数とも言え、且つ、\(u_3\)は\(x_1, x_2, x_3, ...\)の関数と言えます。
これは、\(z = f(g(x_1, x_2, x_3, ...), h(x_1, x_2, x_3, ...), ...)\)とも書くことができます。
上記式について、\(z\)を\(k\)番目の\(x\)について微分する時、以下の様に表せます。
上記式をシグマを使って表します。
左辺の\(\frac{∂z}{∂x_k}\)の部分、なんとなく\(\frac{∂E}{∂W_k}\)っぽい感じがしないでしょうか。
実際、最適なWたちの値を判別する際、必ず多変数の微分が必要になります。
そして各関数たちは、他の層の関数に依存している関係となっています。
それらを計算する為に、この連鎖率を使用してWを最適化しています。
頻繁に出てくるので、ここで押さえておきます。
4. 設定
本章では、計算を行う上での設定を確認します。
図1はあるニューラルネットワークを図示したものです。
以下に図1の具体的記号の説明や各関数の設定を示します。
表1 各記号の説明と各関数の設定記号 | 説明1 | 説明2 |
---|---|---|
\(x\) | 入力値 | \(x_2\)の場合、2番目の入力値\(x\)を指す |
\(z^l_j\) | 出力値 | 重み付き線形和\(u\)を活性化関数に通した値のこと \(z^3_2\)の場合、3層目で2番目の\(z\)を指す |
\(z^L_j, y_j\) | 出力層の出力値 | - |
\(w^l_{ij}\) | 重み | \(w^2_{23}\)の場合、\(z^1_{2}\)から\(z^2_{3}\)へ向かう重みを指す |
\(u^l_j\) | 重み付き線形和 | 前層のノードからの入力に重みを掛けて、全て足し合わせたもの \(u^l_j = w^l_{0j}z^{l-1}_0 + w^l_{1j}z^{l-1}_1 + w^l_{2j}z^{l-1}_2 ...\)とする |
\(t\) | 正解値 | \(y\)に対応しており、\(y_j\)に対応する値は\(t_j\) |
\(f()\) | 活性化関数 | ここでは活性化関数 = 恒等関数を使用する \(f(u) = u\) ※ 恒等関数は、入力値を何も変更せず出力する関数のこと。 例えば、\(f(5) = 5\)となる |
\(E\) | ロス関数 | ここではロス関数に以下の2乗誤差関数を使用する \(E = \frac{1}{2}\sum_i(y_i - t_i)^2\) |
\(η\)(イータ) | 学習率 | ここでは\(η = 0.001\)とする |
上記をもとに、誤差逆伝播の計算を進めていきます。
5. 誤差逆伝播法の計算
では、実際に計算をしていきます。
まず、出力層のWとそれ以外のWで計算を分けます。それらは計算方法が異なる為です。
最初に、出力層におけるW変化量を計算します。その後、出力層から一つ手前の層の出力層におけるW変化量を計算し、さらにその後、もう一つ手前、、、というように、出力層から入力層に向かってWの変化量を計算していきます。
この理由は、先述した様に、ある重みWの変化が、後続のニューラルネットワークの値に影響を与えてしまうことにあります。
これを避ける為、後続がない出力層から計算を進め、1層ずつ手前(入力層側)に向かって計算を進めていきます。
これが誤差逆伝播法の「逆」の由来になります。
また、おさらいですが、Wを更新する式は以下になります。
式1
ここで、ある1つの重みに注目します。設定より、以下の様に表せます。
式2
誤差逆伝播法によって求めるのはここです。この式を求めることが目的となります。
では進めていきます。
出力層の\(Δw\)の計算
出力層の\(w\)(\(w^L_{ij}\))について、以下の式を計算します。
式3
\(\frac{∂E}{∂w^L_{ij}}\)に注目します。連鎖率を使用し、以下の様にします。
式4
\(∂u^L_j\)が出てきました。
ロス関数\(E\)は重み付き線形和\(u\)の関数となっており、且つ、\(u\)は重み\(w\)の関数となっています。
\(E(u^L(w^L))\)ともかけます。
従って、式4の様に連鎖率で表すことが可能になっています。
関数の関係性については、図1をみていただくと分かりやすいと思います。
※ 式4において、多変数の連鎖率なのに\(Σ\)が入っていないのは、今回\(W^L_{ij}\)に注目しており、それに影響されるのは\(u^L_j\)のみであるからです。
\(\frac{∂E}{∂u^L_j} = δ^L_j\)(デルタ)とおきます。因みに、この\(δ\)を「誤差」といいます(説明は後述)。
式5
\(\frac{∂u^L_j}{∂w^L_{ij}}\)は実は計算可能で、\(z^{L-1}_i\)となります。以下にその理由を示します。
まず、\(u^L_j\)を表すと、以下になります。
ここで、\(\frac{∂u^L_j}{∂w^L_{ij}}\)を考えた時、偏微分なので、\(w^L_{ij} \times z^{L-1}_i\)のみが残ります。他は定数とみなすので全て落ちます。
よって、\(\frac{∂u^L_j}{∂w^L_{ij}}\)を計算すると、\(z^{L-1}_i\)となります。
式6
\(z^{L-1}_i\)はニューラルネットワーク内に出てくる数値(1つ前の層の出力)なので、これで完了です。
次に、\(δ^L_j\)を計算します。
\(δ^L_j\)は、以下の様に表すことができます。
式7
この連鎖率は式4と同様の考え方です。さらに変形します。
まず式7の\(\frac{∂z^L_{j}}{∂u^L_j}\)に注目します。
分子\(∂z^L_j\)は活性化関数を通した後の数値ですが、今回活性化関数は恒等関数としているので、以下となります。
式8
式8より、以下となります。
式9
次に式7の\(\frac{∂E}{∂z^L_j}\)に注目します。
分母\(z^L_j\)は、出力層の出力値なので\(z^L_j = y_j\)と表せます。
式10
式10は、つまり「ロス関数\(E\)を、\(y_j\)で偏微分せよ」ということです。
ロス関数Eは\(E = \frac{1}{2}\sum_i(y_i - t_i)^2\)です。
\(i\)の分だけ\((y - t)\)がありますが、今回注目するのは\((y_j - t_j)\)のみです。残りは定数とみなすので落ちます。
従って、以下となります。
式11
\(y_j\)と\(t_j\)はニューラルネットワーク内に存在する数値なので、それらを持ってくれば良いです。
結果的に、式7(\(δ^L_j\))は以下の様に表せます。
式12
これで必要な式は出揃いましたので、まとめます。
式5に、式6と式12を代入します。
式13
式3に、式13を代入します。
式14
これで、出力層の\(Δw\)の計算が完了しました。
非常に単純な計算式となりました。値も全てニューラルネットワーク内に存在する値なので、当然計算可能です。
ちなみに、\(δ^L_j\)は\(y_j - t_j\)となりました。まさに「誤差」ですよね。
次の出力層以外の計算時、この\(δ\)、つまり「誤差」が重要になってきます。
出力層以外の\(Δw\)の計算
出力層の\(w\)を\(w^l_{ij}\)とします。以下の式を計算します。
式15
\(\frac{∂E}{∂w^l_{ij}}\)に注目します。連鎖率を使用し、以下の様にします。
式16
\(\frac{∂E}{∂u^l_j} = δ^l_j\)(デルタ)とおきます。
式17
\(\frac{∂u^l_j}{∂w^l_{ij}}\)を計算します。
出力層と同じ様に、\(z^{l-1}_i\)となります。
式18
ここまでは、出力層の計算と同じです。
ここから先、\(δ^l_j\)の計算が先ほどとは違ってきます。
ということで、\(δ^l_j\)を計算していきます。
\(δ^l_j\)を以下の様に表します。
式19
出力層になかったシグマがつきました。
理由は、\(u^l_j\)は、仮に値が変わったとしたら、その次の層の\(u^{l+1}_1\), \(u^{l+1}_2\), \(u^{l+1}_3\)...も全て値が変わります。つまり影響をうけます。
従って、全て足し合わせる必要があります。
出力層の時と今回とで、シグマの有無に注意が必要です。
式19の\(\frac{∂E}{∂u^{l+1}_k}\)を\(δ^{l+1}_k\)とおきます。
さらに、\(\frac{∂u^{l+1}_k}{∂u^l_j}\)を次の様に変形します。
式20
式20について1つずつみていきます。
まず、\(\frac{∂u^{l+1}_k}{∂z^l_j}\)は結果的に\(w^{l+1}_{jk}\)と表すことが可能です。
理由として、まず\(u^{l+1}_k\)を考えます。
これは、重み付き線形和\(u\)の、\(l+1\)層目のものです。
\(...+...+ w^{l+1}_{jk} z^l_j + ...\)となっています。
この\(u^{l+1}_k\)を\(z^l_j\)で偏微分すると、\(w^{l+1}_{jk} z^l_j\)以外は定数とみなす為落ちます。
\(w^{l+1}_{jk} z^l_j\)のみと考えるので、結果\(w^{l+1}_{jk}\)となります。
次に、\(\frac{∂z^l_j}{∂u^l_j}\)は結果的に\(\frac{∂f^l(u^l_j)}{∂u^l_j}\)となります。
理由は、\(z^l_j\)は\(z^l_j = f(u^l_j)\)であるから、 \(\frac{∂z^l_j}{∂u^l_j} = f^{l'}(u^l_j)\)となります。つまり、単純に\(u^l_j\)についての微分となります。
更に、今回活性化関数\(f\)は恒等関数(\(f(x) = x\))なので、微分すると\(f'(x) = 1\)となります。
よって\(\frac{∂z^l_j}{∂u^l_j} = 1\)となります(今回はそのまま\(\frac{∂z^l_j}{∂u^l_j} = \frac{∂f^l(u^l_j)}{∂u^l_j}\)としておきます)。
最後に、\(δ^{l+1}_j\)は結論からいうともう値が出ています。
例えば、出力層の1つ手前の中間層を\(l\)層とすれば、\(l+1\)層は出力層です。
出力層の\(δ\)は\(δ^L_j\)、つまり\(y_j - t_j\)でした。
ということは、\(δ^{l+1}_j = δ^L_j = (y_j - t_j)\)となります。
それをもとに\(δ^l_j\)を算出していきます。
次に、もう1つ手前の中間層に行った場合、\(δ^{l+1}_j\)は今回算出した\(δ^l_j\)を使って計算していきます。
\(δ^L\)が分かれば\(δ^{L-1}\)が分かり、\(δ^{L-2}\)が分かり、\(δ^{L-3}\)... 最終的に\(δ^1\)が分かります。
この様に、出力層から入力層へ\(δ\)を伝播させていきます。
因みに、\(δ^L_j = y_j - t_j\)(誤差)であり、それが逆方向へ伝播していくから「誤差逆伝播法」と呼ばれます。
これで必要な式は出揃いましたので、まとめます。
式17に式18と式20を代入します。
式21
式15に式21を代入します。
式22
計算まとめ
まとめます。
出力層の\(Δw\)の計算
出力層以外の\(Δw\)の計算
6. まとめ
今回はニューラルネットワークの学習における、誤差逆伝播法について解説しました。
次回も是非みてみてください!
7. 参考文献
斎藤康毅 著 「ゼロから作るDeep Learning ーPythonで学ぶディープラーニングの理論と実装」
Link
Search