誤差逆伝播法の導出

2015-11-27

Neural networks and deep learningHow the backpropagation algorithm works (日本語訳:逆伝播の仕組み) を読んで、多層パーセプトロン(ニューラルネットワーク)の誤差逆伝播法について ようやく理解したので、導出方法をメモ。

フィードフォワードに関しては多層パーセプトロンの出力値の計算(フィードフォワード) を参照のこと。

コスト関数

ニューラルネットワークのウェイトやバイアスをどのように調整したらいいかを 判断するために、学習パターンの入力値に期待される出力値とのずれを測る コスト関数 \(C(\mathbf{x})\)を導入する。

ここではひとまず入力\(\mathbf{x}\)に期待される出力\(\mathbf{y}\)と 実際の値\(\mathbf{a}^L\)の差の二乗誤差とする:

$$ \begin{align*} C(\mathbf{x}) &= \frac{1}{2} | \mathbf{y}(\mathbf{x}) - \mathbf{a}^L(\mathbf{x}) |^2 \\ &= \frac{1}{2} \sum_i (y_i - a^L_i)^2 \\ &= \frac{1}{2} \left( (y_1 - a^L_1)^2 + (y_2 - a^L_2)^2 + \cdots \right) \end{align*} $$

実際には学習パターン\(\mathbf{x}\)-教師データ\(\mathbf{y}\)のペアは複数与えられて 全体の合計コストとする:

$$ C = \frac{1}{n} \sum_{\mathbf{x}} C(\mathbf{x}) $$

コストを最小化するために、ウェイトやバイアスをいじった時にどのように変化するかを知りたい。 それがわかれば、コストを減らす方向に少しずついじることによって 達成できる(うまくいけば)。

関数の傾きを得るには偏微分を使い、チェインルールで求める。

誤差逆伝播法(バックプロパゲーション)

ウェイトやバイアスを変化させた時にコストがどのように変化するかを調べるには、 コスト関数をウェイトやバイアスで偏微分して求める:

$$ \frac{\partial C}{\partial w^l_{jk}}, \\ \frac{\partial C}{\partial b^l_j} $$

しかしこれらの偏微分を直接求めるのは難しいので、中間の変数として ニューロンへの入力\(z^l_j\)を偏微分のチェインルールに用いる:

$$ \begin{align*} \frac{\partial C}{\partial w^l_{jk}} &= \frac{\partial C}{\partial z^l_j} \frac{\partial z^l_j}{\partial w^l_{jk}}, \\ \frac{\partial C}{\partial b^l_j} &= \frac{\partial C}{\partial z^l_j} \frac{\partial z^l_j}{\partial b^l_j} \end{align*} $$

実際の計算は次のようなステップを踏んで行う:

  1. 出力層での教師データとの差から、変化量\(\mathbf{\delta}^L\)を求める
  2. 後段の層の誤差から、前段の層の変化量\(\mathbf{\delta}^l\)を計算する
  3. 各層の変化量から、ウェイトとバイアスでの変化量を求める

出力層から入力層に向かって誤差を伝播させて計算していくこの一連のステップを 誤差逆伝播法(バックプロパゲーション)という。

1. 出力層での誤差

コスト関数\(C\)に対する、出力層のニューロン\(j\)への入力\(z^L_j\)での偏微分を\(\delta^L_j\)と置く。 偏微分の中間変数として\(a^L_k\)を導入して計算する:

$$ \begin{align*} \delta^L_j &= \frac{\partial C}{\partial z^L_j} \tag{36} \\ &= \sum_k \frac{\partial C}{\partial a^L_k} \frac{\partial a^L_k}{\partial z^L_j} \tag{37} \end{align*} $$

\(k \ne j\)の場合同じ層の別のニューロンだから、\(a^L_k\)は\(z^L_j\)と無関係なので \(\frac{\partial a^L_k}{\partial z^L_j} = 0\)。

よって\(\sum_k\)は\(j\)の時だけとなる。 定義より\(a^L_j = \sigma(z^L_j)\)なので、 \(\frac{\partial a^L_k}{\partial z^L_j} = \sigma^\prime(z^L_j)\)となり、

$$ \begin{align*} \delta^L_j &= \frac{\partial C}{\partial a^L_j} \frac{\partial a^L_j}{\partial z^L_j} \tag{38} \\ &= \frac{\partial C}{\partial a^L_j} \sigma^\prime(z^L_j) \end{align*} $$

\(C = \frac{1}{2} \left( (y_1 - a^L_1)^2 + (y_2 - a^L_2)^2 + \cdots \right)\)から、

$$ \frac{\partial C}{\partial a^L_j} = (a^L_j - y_j) $$

となるので、

$$ \therefore \delta^L_j = (a^L_j - y_j) \sigma^\prime(z^L_j) $$

ベクトル表記で書くと、

$$ \begin{align*} \mathbf{\delta}^L &= \nabla_a C \odot \sigma^\prime(\mathbf{z}^L) \\ &= (\mathbf{a}^L - \mathbf{y}) \odot \sigma^\prime(\mathbf{z}^L) \end{align*} $$

記号\(\odot\)はアマダール積といい、ベクトルの各要素ごとの乗算を表す演算子。

2. 中間層での誤差

出力層以外の、中間層の誤差は後の層の誤差から求めることができる:

$$ \begin{align*} \delta^L_j &= \frac{\partial C}{\partial z^l_j} \tag{40} \\ &= \sum_k \frac{\partial C}{\partial z^{l+1}_k} \frac{\partial z^{l+1}_k}{\partial z^l_j} \tag{41} \\ &= \sum_k \frac{\partial z^{l+1}_k}{\partial z^l_j} \delta^{l+1}_k \tag{42} \end{align*} $$

$$ \begin{align*} z_k^{l+1} &= \sum_j w_{kj}^{l+1} a^l_j + b_k^{l+1} \\ &= \sum_j w_{kj}^{l+1} \sigma(z_j^l) + b_k^{l+1} \tag{43} \\ \therefore \frac{\partial z_k^{l+1}}{\partial z_j^l} &= w_{kj}^{l+1} \sigma^\prime(z_j^l) \tag{44} \end{align*} $$

(44)を(42)に代入して:

$$ \delta^L_j = \sum_k w^{l+1}_{kj} \delta^{l+1}_k \sigma^\prime(z^l_j) $$

ベクトル表記で書くと、

$$ \mathbf{\delta}^l = \left( \left( \mathbf{W}^{l+1} \right)^T \mathbf{\delta^{l+1}} \right) \odot \sigma^\prime(z^l) $$

3. バイアスでの偏微分

$$ \frac{\partial C}{\partial b^l_j} = \frac{\partial C}{\partial z^l_j} \frac{\partial z^l_j}{\partial b^l_j} $$

ここで \(\frac{\partial C}{\partial z^l_j} = \delta^l_j\) 、 \(\frac{\partial z^l_j}{\partial b^l_j} = 1\) なので、

$$ \frac{\partial C}{\partial b^l_j} = \delta^l_j $$

となる。

ベクトル表記だと、

$$ \frac{\partial C}{\partial \mathbf{b}^l} = \mathbf{\delta}^l $$

4. ウェイトでの偏微分

$$ \frac{\partial C}{\partial w^l_{jk}} = \frac{\partial C}{\partial z^l_j} \frac{\partial z^l_j}{\partial w^l_{jk}} $$

ここで

$$ \begin{align*} \frac{\partial z^l_j}{\partial w^l_{jk}} &= \frac{\partial}{\partial w^l_{jk}} \left( \sum_t w^l_{jt} a^{l-1}_t + b^l_j \right) \\ &= a^{l-1}_k \end{align*} $$

なので、

$$ \frac{\partial C}{\partial w^l_{jk}} = a^{l-1}_k \delta^l_j $$

となる。

ベクトル(マトリクス)形式だと、

$$ \frac{\partial C}{\partial \mathbf{w}^l} = \mathbf{\delta}^l \cdot (\mathbf{a}^{l-1})^T $$

学習の適用

すべての層のウェイトとバイアスに対するコスト関数の偏微分が求まったので、 ある学習率\(\eta\)を設定して、コストを減らす方向に変更してやる(確率的最急降下法):

$$ \begin{align*} w^l_{jk} &\leftarrow w^l_{jk} - \eta \frac{\partial C}{\partial w^l_{jk}}, \\ b^l_j &\leftarrow b^l_j - \eta \frac{\partial C}{\partial b^l_j} \end{align*} $$

ベクトル表記だと:

$$ \begin{align*} \mathbf{w}^l &\leftarrow \mathbf{w}^l - \eta \frac{\partial C}{\partial \mathbf{w}^l}, \\ \mathbf{b}^l &\leftarrow \mathbf{b}^l - \eta \frac{\partial C}{\partial \mathbf{b}^l} \end{align*} $$