t_wの輪郭

Feedlyでフォローするボタン
誤差逆伝播法

合っているかは保証しない。ちょっと自信がない。

前置き

ニューラルネットワークの構成

変数の整理

入力層の出力を\(z_i\), 中間層の出力を\(y_j\), 出力層の出力を\(o_k\)と置く。
入力層から中間層への重みを\( v_{ji} \), 中間層から出力層への重みを\( w_{kj} \)と置く。
\(f\)をsigmoidなどの活性化関数と置く。

ニューロンの出力の計算

$$y_j = f({\sum_{i=1}^{I} v_{ji} z_i})$$
$$o_k = f({\sum_{j=1}^{J} w_{kj} y_j})$$

微分の伝播

損失関数を出力層の出力\(o_k\)で微分

教師信号を\(t_k\), 損失関数を\(L = \cfrac{1}{2}\sum_{k=1}^{K}(t_k - o_k)^2\)と置くと、損失関数\(L\)を出力層の出力\(o_k\)について微分した関数は

$$\frac{\partial L}{\partial o_k} = -(t_k - o_k)$$

となる。

損失関数\(L\)についている\(\cfrac{1}{2}\)は、微分時に発生する2の乗算を打ち消し、微分後の数式を単純化して良い気分になるためについている。実用上はあってもなくても変化がない。学習率で調整される。

出力層の出力\(o_k\)を出力層の重み\(w_{kj}\)で微分

$$\frac{\partial o_k}{\partial w_{kj}} = \frac{\partial f({\sum_{j=1}^{J} w_{kj} y_j})}{\partial w_{kj}} = f'({\sum_{j=1}^{J} w_{kj} y_j}) y_j$$

損失関数を出力層の重み\(w_{kj}\)で微分

$$\frac{\partial L}{\partial w_{kj}} = \frac{\partial L}{\partial o_k}\frac{\partial o_k}{\partial w_{kj}} = -(t_k - o_k) f'({\sum_{j=1}^{J} w_{kj} y_j}) y_j$$

のちの計算のために、

$$\delta_{o_k} = -(t_k - o_k) f'({\sum_{j=1}^{J} w_{kj} y_j})$$

としておく。

出力層の重みの更新

最急降下法を用いて更新する。
\(w_{kj}\)の変量を\(\varDelta{w_{kj}}\), 学習率を\(\eta\)と置くと、

$$\varDelta{w_{kj}} = - \eta \frac{\partial L}{\partial w_{kj}} = - \eta \delta_{o_k} y_j$$

となり、\(w_{kj}\)

$$ w_{kj} = w_{kj} + \varDelta{w_{kj}} $$

のように更新する。

損失関数を中間層の出力で微分

$$\frac{\partial L}{\partial o_k} = -(t_k - o_k)$$
$$\frac{\partial o_k}{\partial y_j} = \frac{\partial f({\sum_{j=1}^{J} w_{kj} y_j})}{\partial y_j} = f'({\sum_{j=1}^{J} w_{kj} y_j}) w_{kj}$$
$$\delta_{o_k} = -(t_k - o_k) f'({\sum_{j=1}^{J} w_{kj} y_j})$$

より

$$\frac{\partial L}{\partial y_j} = \frac{\partial L}{\partial o_k} \frac{\partial o_k}{\partial y_j} = \frac{\partial \cfrac{1}{2}\sum_{k=1}^{K}(t_k - o_k)^2}{\partial o_k} \frac{\partial o_k}{\partial y_j} = \sum_{k=1}^{K}-(t_k-o_k) f'({\sum_{j=1}^{J} w_{kj} y_j}) w_{kj} = \sum_{k=1}^{K} \delta_{o_k} w_{kj}$$

となる。

損失関数を中間層の重みで微分

$$\frac{\partial y_j}{\partial v_{ji}} = \frac{\partial f({\sum_{i=1}^{I} v_{ji} z_i})}{\partial v_{ji}} = f'({\sum_{i=1}^{I} v_{ji} z_i}) z_i$$
$$\frac{\partial L}{\partial v_{ji}} = \frac{\partial L}{\partial y_j} \frac{\partial y_j}{\partial v_{ji}} = \sum_{k=1}^{K} \delta_{o_k} w_{kj} f'({\sum_{i=1}^{I} v_{ji} z_i}) z_i$$

簡単化のために

$$\delta_{y_j} = \sum_{k=1}^{K} \delta_{o_k} w_{kj} f'({\sum_{i=1}^{I} v_{ji} z_i})$$

と置くと、

$$\frac{\partial L}{\partial v_{ji}} = \delta_{y_j} z_i$$

となる。

中間層の重みの更新

出力層の重みの更新と同様に、

$$\varDelta{v_{ji}} = - \eta \frac{\partial L}{\partial v_{ji}} = - \eta \delta_{y_j} z_i$$
$$ v_{ji} = v_{ji} + \varDelta{v_{ji}} $$

のように更新する。

入力層の重みの更新

筆者は力尽きたので読者の宿題とします。

あれCartesian Genetic Programmingにおける誤差逆伝播法の導出微分の連鎖律を用いた誤差逆伝播法の導出あれあれあれ

まだ導出途中

Cartesian Genetic Programmingの模式図

準備

記号の準備

入力層の出力:\( x_i \)
中間層の出力:\( y_j = f_j(x_{o(j)}, x_{p(j)}, a_j) \)
出力層の出力:\( z_k = g_k(y_{m(k)}, y_{n(k)}, b_k) \)

\(z_k\)の入力1:\(y_{m(k)}\)
\(z_k\)の入力2:\(y_{n(k)}\)

\(y_j\)の入力1:\(x_{o(j)}\)
\(y_j\)の入力2:\(x_{p(j)}\)

中間層のj番目のノードが持つ関数:\(f_j\)
出力層のk番目のノードが持つ関数:\(g_k\)

中間層のj番目のノードが持つ定数:\(a_j\)
出力層のk番目のノードが持つ定数:\(b_k\)

出力層の出力と教師信号からなる損失関数:\(E\)

ゴール

損失関数について中間層のj番目のノードが持つ定数\(a_j\)と出力層のk番目のノードが持つ定数\(b_k\)で微分


損失関数\(E\)を出力層の入力値で微分

$$ \frac{\partial z_k}{\partial y_{m(k)}} = \frac{\partial g_k(y_{m(k)}, y_{n(k)}, b_k)}{\partial y_{m(k)}} $$
$$ \frac{\partial z_k}{\partial y_{n(k)}} = \frac{\partial g_k(y_{m(k)}, y_{n(k)}, b_k)}{\partial y_{n(k)}}$$
$$ \frac{\partial z_k}{\partial b_k} = \frac{\partial g_k(y_{m(k)}, y_{n(k)}, b_k)}{\partial b_k}$$

$$ \frac{\partial E}{\partial y_{m(k)}} = \frac{\partial E}{\partial z_k} \frac{\partial z_k}{\partial y_{m(k)}}$$
$$ \frac{\partial E}{\partial y_{n(k)}} = \frac{\partial E}{\partial z_k} \frac{\partial z_k}{\partial y_{n(k)}}$$
$$ \frac{\partial E}{\partial b_k} = \frac{\partial E}{\partial z_k} \frac{\partial z_k}{\partial b_k}$$

\( \frac{\partial E}{\partial z_k} \)の値はいい感じにプログラマが計算して与えるものとする。損失関数を数値微分しても良い。

損失関数\(E\)を中間層の入力値で微分

\(j = m(k)\)あるいは\(j = n(k)\)のときの\(\frac{\partial E}{\partial y_j}\)についてはすでに上にて計算済みであり、使いまわすことができる。

$$ \frac{\partial y_j}{\partial x_{o(j)}} = \frac{\partial f_j(x_{o(j)}, x_{p(j)}, a_j)}{\partial x_{o(j)}} $$
$$ \frac{\partial y_j}{\partial x_{p(j)}} = \frac{\partial f_j(x_{o(j)}, x_{p(j)}, a_j)}{\partial x_{p(j)}} $$
$$ \frac{\partial y_j}{\partial x_{o(j)}} = \frac{\partial f_j(x_{o(j)}, x_{p(j)}, a_j)}{\partial a_j} $$
$$ \frac{\partial E}{\partial x_{o(j)}} = \frac{\partial E}{\partial y_j} \frac{\partial y_j}{\partial x_{o(j)}} = \frac{\partial E}{\partial y_j} \frac{\partial f_j(x_{o(j)}, x_{p(j)}, a_j)}{\partial x_{o(j)}} $$
$$ \frac{\partial E}{\partial x_{o(j)}} = \frac{\partial E}{\partial y_j} \frac{\partial y_j}{\partial x_{o(j)}} $$
$$ \frac{\partial E}{\partial x_{o(j)}} = \frac{\partial E}{\partial y_j} \frac{\partial y_j}{\partial x_{o(j)}} $$

あれ

2023/8/21 23:21:00

うまく微分の伝搬を表現できれば、もうちょっとシンプルな導出にできそうな気がする。
具体的な数式じゃなくて抽象的な数式をこねこねしたら行ける雰囲気。

あれ

2023/8/20 23:53:00

誤差関数を出力層の重み\(w_{kj}\)で微分

このあたりで力尽きそう

あれ

2023/8/20 22:42:00

誤差逆伝播法の導出を書くにあたって、理解を容易ならしめるために作図してウェイウェイしたいけど、作図してウェイウェイできる手段をどうしよう。

手書きで見苦しくなるけど、TwEgakuが最適か。

ちょっとやってみたけど、手書きめんどいな。SVGのホスティング機能を備えたまともな作図サービスが要るな。
TwEgakuを拡張するのが良さそうな予感だけど、なんかあれなんだよな。