誤差逆伝播法を数式で追う 連鎖律で勾配を導く

こんにちは。ゆうせいです。

前回の記事では、誤差逆伝播法を言葉で説明しました。出力層で要望を作り、それを前の層へ遡らせる。この流れを追いました。

今回は、同じ内容を数式で書き直します。

正直に言うと、ここが一番つらい部分です。添え字が増え、偏微分の記号が並び、何を見ているか分からなくなります。私も最初はそうでした。

しかし、構造そのものは単純です。連鎖律を使い、変化率を掛け合わせるだけです。その掛け算の各因子が何を意味するかを一つずつ確認すれば、霧は晴れます。

各層にニューロンが1個ずつという最小の構成から始めます。

結論

数式で追うときの要点は、三つです。

要点内容
連鎖律は変化率の掛け算三つの比を掛けるだけ。難しい操作はない
各因子に意味がある出力の誤差、活性化関数の傾き、前の層の活性化
ニューロンが増えても構造は同じ添え字が増え、和が入るだけ

特に三番目を先に書いておきます。

ニューロンが増えると複雑になるように見えますが、本質は変わりません。前の層の活性化について微分するところで、和が現れる。それだけの違いです。

以下、順に見ていきます。

1 記号の準備

数式に入る前に、記号を確認します。ここを飛ばすと、後で必ず混乱します。

上付き文字は層の番号

a^{(L)} と書いたとき、L は累乗ではありません。層の番号です。

一つ前の層は a^{(L-1)} と書きます。

なぜ上付きにするのでしょうか。下付きの位置は、後でニューロンの番号に使いたいからです。

記号の一覧

記号読み方意味
a^{(L)} エー エルL 層の活性化
w^{(L)} ダブリュー エルL 層に入る重み
b^{(L)} ビー エルL 層のバイアス
z^{(L)} ゼット エル活性化関数を通す前の値
y ワイ正解の値
C_0 シー ゼロ訓練例1個分のコスト
\sigma シグマ活性化関数
\partial ラウンド偏微分の記号

C_0 の添え字0は、1個分という意味です。全データの平均は C と書きます。

練習問題1

a^{(3)} a^3 は、それぞれ何を表しますか。違いを説明してください。

解答を示します。

a^{(3)} は、第3層の活性化を表します。上付き文字は層の番号であり、指数ではありません。

a^3 は、a の3乗を表します。

補足します。文献によっては括弧を付けずに a^L と書くこともあります。

その場合、文脈で判断する必要があります。研修資料を作る際は、括弧を付けることをおすすめします。初学者の誤解を防げます。

2 最小のネットワーク

構成

各層にニューロンが1個ずつという構成から始めます。

入力層、中間層が2つ、出力層。合計4層とします。

この場合、重みが3個、バイアスが3個です。調整できるつまみは6個だけです。

注目する部分

最後の2つのニューロンのつながりだけを見ます。

a^{(L-1)} \rightarrow z^{(L)} \rightarrow a^{(L)} \rightarrow C_0

三つの式

この部分は、三つの式で表せます。

z^{(L)} = w^{(L)} a^{(L-1)} + b^{(L)}

a^{(L)} = \sigma \left( z^{(L)} \right)

C_0 = \left( a^{(L)} - y \right)^2

一つずつ確認します。

一つ目は、前の層の活性化に重みを掛け、バイアスを足したものです。これを z と名付けます。名前を付けておくと、後の計算が楽になります。

二つ目は、z に活性化関数を適用したものです。

三つ目は、出力と正解の差を二乗したコストです。

依存関係の図

三つの式を、流れとして描きます。

w^{(L)}, ; a^{(L-1)}, ; b^{(L)} \rightarrow z^{(L)} \rightarrow a^{(L)} \rightarrow C_0

重み、前の活性化、バイアスが z を決める。z a を決める。a と正解 y がコストを決める。

この鎖が、連鎖律の対象です。

図解案

研修資料では、数直線を並べて描くと効果的です。

w^{(L)} z^{(L)} a^{(L)} C_0 の4本の数直線を縦に並べます。そして、それぞれの上に小さな矢印を描き、「少し動かす」という操作を表します。

上の線を少し動かすと、下の線がどれだけ動くか。この対応関係を目で見ると、連鎖律が腑に落ちます。

練習問題2

w^{(L)} = 2 a^{(L-1)} = 3 b^{(L)} = -1 のとき、z^{(L)} を求めてください。また、y = 0.5 、活性化関数を恒等関数とした場合のコストを求めてください。

解答を示します。

z^{(L)} を計算します。

z^{(L)} = 2 \times 3 + (-1) = 6 - 1 = 5

活性化関数が恒等関数なので、次の通りです。

a^{(L)} = 5

コストを計算します。

C_0 = (5 - 0.5)^2 = 4.5^2 = 20.25

補足します。恒等関数とは、入力をそのまま返す関数です。

\sigma(z) = z

説明を簡単にするため、この記事の計算例ではしばしば恒等関数を使います。実際のネットワークでは、シグモイドやReLUが使われます。

3 重みに対する感度

知りたいこと

最初の目標は、次の値を求めることです。

\frac{\partial C_0}{\partial w^{(L)}}

重みを少し動かしたとき、コストがどれだけ動くか。この比です。

記号の意味を確認する

\partial w^{(L)} は、重みへの小さな変化だと考えてください。たとえば0.01動かす、というような変化です。

\partial C_0 は、その結果として生じるコストの変化です。

求めたいのは、この二つの比です。

連鎖を分解する

重みを動かすと、何が起きるでしょうか。

w^{(L)} が動く。すると z^{(L)} が動く。すると a^{(L)} が動く。そしてコストが動く。

この連鎖を、三つの比に分解します。

\frac{\partial C_0}{\partial w^{(L)}} = \frac{\partial z^{(L)}}{\partial w^{(L)}} \cdot \frac{\partial a^{(L)}}{\partial z^{(L)}} \cdot \frac{\partial C_0}{\partial a^{(L)}}

これが連鎖律です。

なぜ掛け算なのか

前回までの記事で使った歯車の比喩を、もう一度使います。

1番目の歯車を1回転させると2番目が3回転し、2番目を1回転させると3番目が2回転する。

このとき、1番目を1回転させれば3番目は6回転します。

3 \times 2 = 6

変化率が連鎖するときは、掛け算になります。

三つの因子を求める

一つずつ計算します。

因子1 コストを活性化で微分する

C_0 = \left( a^{(L)} - y \right)^2 a^{(L)} で微分します。

外側の二乗を微分すると2が出て、内側の微分は1です。

\frac{\partial C_0}{\partial a^{(L)}} = 2 \left( a^{(L)} - y \right)

この因子の意味

大きさが、出力と正解の隔たりに比例しています。

出力が正解から大きく離れていれば、この値は大きくなります。つまり、少しの変化が大きな影響を持ちます。

前回の記事で「要望の強さは隔たりに比例する」と説明しました。その正体が、この式です。

因子2 活性化を z で微分する

a^{(L)} = \sigma \left( z^{(L)} \right) z^{(L)} で微分します。

\frac{\partial a^{(L)}}{\partial z^{(L)}} = \sigma' \left( z^{(L)} \right)

活性化関数の微分そのものです。

シグモイドならシグモイドの微分、ReLUならReLUの微分になります。

因子3 z を重みで微分する

z^{(L)} = w^{(L)} a^{(L-1)} + b^{(L)} w^{(L)} で微分します。

w^{(L)} に掛かっているのは a^{(L-1)} です。バイアスは w を含まないので消えます。

\frac{\partial z^{(L)}}{\partial w^{(L)}} = a^{(L-1)}

この因子の意味

ここが、前回の記事と直接つながる部分です。

重みを少し動かしたときの影響は、前の層の活性化の大きさで決まります。

前の層が活発であれば、重みの変化が大きく響きます。前の層が0に近ければ、重みを変えてもほとんど影響しません。

前回、「明るいニューロンとのつながりほど効果が大きい」と説明しました。その根拠が、この式です。

ヘッブの法則との類似も、ここに現れています。同時に活発なニューロンの間で、結合が最も強く変化します。

完成した式

三つを掛け合わせます。

\frac{\partial C_0}{\partial w^{(L)}} = a^{(L-1)} \cdot \sigma' \left( z^{(L)} \right) \cdot 2 \left( a^{(L)} - y \right)

この一行が、誤差逆伝播法の中心にある式です。

三つの因子の役割

意味を整理します。

因子表すもの
a^{(L-1)} 前の層がどれだけ活発か
\sigma'(z^{(L)}) 活性化関数がどれだけ反応するか
2(a^{(L)} - y) 出力がどれだけ間違っているか

どれか一つでも0に近ければ、全体が小さくなります。掛け算だからです。

練習問題3

連鎖律の三つの因子を挙げ、それぞれが何を表すか説明してください。

解答を示します。

一つ目は \frac{\partial z^{(L)}}{\partial w^{(L)}} = a^{(L-1)} です。前の層の活性化の大きさを表します。前の層が活発なほど、重みの変化が大きく影響します。

二つ目は \frac{\partial a^{(L)}}{\partial z^{(L)}} = \sigma'(z^{(L)}) です。活性化関数の傾きを表します。関数が急な領域にいるほど、変化が伝わります。

三つ目は \frac{\partial C_0}{\partial a^{(L)}} = 2(a^{(L)} - y) です。出力と正解の隔たりを表します。間違いが大きいほど、大きな修正が必要になります。

補足します。この三つが掛け算で結ばれている点が重要です。

一つでも0になれば、その重みは更新されません。たとえばReLUを使っていて z < 0 であれば、二つ目の因子が0になり、全体が0になります。

練習問題4

次の値のとき、\frac{\partial C_0}{\partial w^{(L)}} を求めてください。活性化関数は恒等関数とします。

a^{(L-1)} = 3, \quad a^{(L)} = 5, \quad y = 0.5

解答を示します。

恒等関数の微分は1です。

\sigma'(z) = 1

三つの因子を計算します。

\frac{\partial z^{(L)}}{\partial w^{(L)}} = a^{(L-1)} = 3

\frac{\partial a^{(L)}}{\partial z^{(L)}} = 1

\frac{\partial C_0}{\partial a^{(L)}} = 2 (5 - 0.5) = 2 \times 4.5 = 9

掛け合わせます。

3 \times 1 \times 9 = 27

補足します。値が正なので、この重みを減らすとコストが下がります。

学習率を0.01とすれば、更新後の重みは次の通りです。

2 - 0.01 \times 27 = 2 - 0.27 = 1.73

練習問題5

前の層の活性化 a^{(L-1)} が0だった場合、\frac{\partial C_0}{\partial w^{(L)}} はいくつになりますか。また、それは妥当ですか。

解答を示します。

0になります。三つの因子のうち一つが0なので、掛け算の結果も0です。

妥当です。前の層の活性化が0であれば、その重みが何であっても w \times 0 = 0 となり、出力に寄与していません。寄与していない重みを調整しても、この訓練例に関しては意味がありません。

補足します。ReLUを使っている場合、この状況はよく起きます。

負の入力を受けたニューロンは0を出力し、そこにつながる重みは更新されません。これが死んだReLU問題の背景にある仕組みです。

4 バイアスに対する感度

ほとんど同じ

重みが分かれば、バイアスは簡単です。

連鎖律の最後の因子だけを差し替えます。

\frac{\partial C_0}{\partial b^{(L)}} = \frac{\partial z^{(L)}}{\partial b^{(L)}} \cdot \frac{\partial a^{(L)}}{\partial z^{(L)}} \cdot \frac{\partial C_0}{\partial a^{(L)}}

最初の因子を計算する

z^{(L)} = w^{(L)} a^{(L-1)} + b^{(L)} b^{(L)} で微分します。

b^{(L)} の係数は1です。

\frac{\partial z^{(L)}}{\partial b^{(L)}} = 1

結果

\frac{\partial C_0}{\partial b^{(L)}} = \sigma' \left( z^{(L)} \right) \cdot 2 \left( a^{(L)} - y \right)

重みの式から、a^{(L-1)} が消えただけです。

意味

バイアスは、直接足される値です。前の層の活性化とは無関係に働きます。

だから、その大きさに依存しません。

練習問題6

練習問題4と同じ値で、\frac{\partial C_0}{\partial b^{(L)}} を求めてください。また、重みの勾配との比を示してください。

解答を示します。

計算します。

\frac{\partial C_0}{\partial b^{(L)}} = 1 \times 9 = 9

重みの勾配は27でしたので、比は次の通りです。

\frac{27}{9} = 3

重みのほうが3倍大きくなっています。

補足します。この3は、a^{(L-1)} = 3 に由来します。

前の層の活性化が1より大きければ重みの勾配のほうが大きく、1より小さければバイアスの勾配のほうが大きくなります。

5 前の層への感度

逆伝播が始まる場所

ここが、逆伝播という名前の由来です。

前の層の活性化に対する感度を求めます。

\frac{\partial C_0}{\partial a^{(L-1)}} = \frac{\partial z^{(L)}}{\partial a^{(L-1)}} \cdot \frac{\partial a^{(L)}}{\partial z^{(L)}} \cdot \frac{\partial C_0}{\partial a^{(L)}}

最初の因子

z^{(L)} = w^{(L)} a^{(L-1)} + b^{(L)} a^{(L-1)} で微分します。

a^{(L-1)} に掛かっているのは w^{(L)} です。

\frac{\partial z^{(L)}}{\partial a^{(L-1)}} = w^{(L)}

結果

\frac{\partial C_0}{\partial a^{(L-1)}} = w^{(L)} \cdot \sigma' \left( z^{(L)} \right) \cdot 2 \left( a^{(L)} - y \right)

重みの式で a^{(L-1)} だった位置が、w^{(L)} に変わりました。

三つの式を並べる

ここまでの結果を整理します。

対象最初の因子
重み w^{(L)} a^{(L-1)}
バイアス b^{(L)} 1
前の活性化 a^{(L-1)} w^{(L)}

残りの二つの因子は、すべて共通です。

\sigma' \left( z^{(L)} \right) \cdot 2 \left( a^{(L)} - y \right)

この共通部分を \delta^{(L)} と名付けることがあります。

\delta^{(L)} = \sigma' \left( z^{(L)} \right) \cdot 2 \left( a^{(L)} - y \right)

すると、三つの式が次のように書けます。

対象勾配
w^{(L)} a^{(L-1)} \delta^{(L)}
b^{(L)} \delta^{(L)}
a^{(L-1)} w^{(L)} \delta^{(L)}

この \delta が、誤差項と呼ばれるものです。

直接は変えられない

前の層の活性化を、直接変えることはできません。

しかし、この値が分かれば、さらに前の層の重みとバイアスを求められます。

繰り返す

\frac{\partial C_0}{\partial a^{(L-1)}} が分かったら、同じ連鎖律を L-1 層に適用します。

\frac{\partial C_0}{\partial w^{(L-1)}} = a^{(L-2)} \cdot \sigma' \left( z^{(L-1)} \right) \cdot \frac{\partial C_0}{\partial a^{(L-1)}}

最後の因子が、一つ前の段階で求めた値です。

この再帰が核心

出力層から始めて、同じ操作を繰り返しながら入力層へ遡る。

前の段階の結果を使って、次の段階を計算する。だから効率的なのです。

練習問題7

w^{(L)} = 0.5 \sigma'(z^{(L)}) = 1 a^{(L)} = 0.8 y = 0.2 のとき、\frac{\partial C_0}{\partial a^{(L-1)}} を求めてください。

解答を示します。

各因子を計算します。

\frac{\partial C_0}{\partial a^{(L)}} = 2(0.8 - 0.2) = 2 \times 0.6 = 1.2

掛け合わせます。

0.5 \times 1 \times 1.2 = 0.6

補足します。値が正なので、a^{(L-1)} を減らすとコストが下がります。

ただし、活性化を直接変えることはできません。この値は、さらに前の層の重みとバイアスを求めるために使われます。

練習問題8

誤差項 \delta^{(L)} を使うと、重み、バイアス、前の活性化の勾配がどう書けるか示してください。

解答を示します。

\frac{\partial C_0}{\partial w^{(L)}} = a^{(L-1)} \delta^{(L)}

\frac{\partial C_0}{\partial b^{(L)}} = \delta^{(L)}

\frac{\partial C_0}{\partial a^{(L-1)}} = w^{(L)} \delta^{(L)}

補足します。\delta を一度計算すれば、三つすべてに使い回せます。

実装では、この共通部分を先に求めておきます。同じ計算を繰り返さずに済むためです。

これが、誤差逆伝播法が効率的である理由の一つです。

6 全データでの平均

ここまでは1例分

ここまでの計算は、訓練例1個に対するものでした。

C_0 という記号の添え字0が、それを表しています。

本当のコスト関数

全訓練データの平均を取ります。

C = \frac{1}{n} \sum_{k=0}^{n-1} C_k

n は訓練データの数です。

勾配も平均する

したがって、勾配も平均になります。

\frac{\partial C}{\partial w^{(L)}} = \frac{1}{n} \sum_{k=0}^{n-1} \frac{\partial C_k}{\partial w^{(L)}}

各訓練例について勾配を計算し、平均を取る。この操作が必要です。

前回の記事とのつながり

前回、「すべての訓練例の要望を平均する」と説明しました。

その要望の正体が、いま求めた偏微分です。平均を取るという操作も、この式が表しています。

練習問題9

3個の訓練例について、ある重みの勾配がそれぞれ 0.6 -0.2 0.5 でした。平均した勾配を求め、学習率0.1で更新した場合の変化量を答えてください。

解答を示します。

平均を計算します。

\frac{0.6 + (-0.2) + 0.5}{3} = \frac{0.9}{3} = 0.3

更新の変化量を計算します。

-0.1 \times 0.3 = -0.03

重みは0.03だけ減ります。

補足します。2番目の訓練例は、逆方向の要望を出していました。

しかし、他の二つと合算した結果、正味では減らす方向になりました。個々の要望が打ち消し合うのは、正常な動作です。

7 ニューロンが増えても同じ

添え字を追加する

各層に複数のニューロンがある場合を考えます。

活性化に、ニューロンの番号を付けます。

記号意味
a^{(L)}_j L 層の j 番目のニューロン
a^{(L-1)}_k L-1 層の k 番目のニューロン

L 層を j L-1 層を k で数えることにします。

重みの添え字

重みには、二つの番号が要ります。どこからどこへのつながりかを示すためです。

w^{(L)}_{jk}

k 番目のニューロンから j 番目のニューロンへの重みです。

順序が逆に見える

jk という並びは、最初は不自然に感じます。「k から j へ」なら kj のほうが自然に思えるからです。

しかし、これには理由があります。

第1回の記事で扱った重み行列を思い出してください。行が出力側、列が入力側でした。

行列の要素を W_{jk} と書くとき、j が行番号、k が列番号です。この慣習と一致させるため、jk の順にします。

コストの式

出力層のすべてのニューロンについて、差の二乗を足します。

C_0 = \sum_{j} \left( a^{(L)}_j - y_j \right)^2

z の式

j 番目のニューロンへの入力は、前の層すべてからの寄与を足したものです。

$latex z^{(L)}j = \sum{k} w^{(L)}_{jk} a^{(L-1)}_k + b^{(L)}_j $

活性化の式

a^{(L)}_j = \sigma \left( z^{(L)}_j \right)

重みの勾配

連鎖律の形は、まったく変わりません。

$latex \frac{\partial C_0}{\partial w^{(L)}_{jk}} = \frac{\partial z^{(L)}j}{\partial w^{(L)}{jk}} \cdot \frac{\partial a^{(L)}_j}{\partial z^{(L)}_j} \cdot \frac{\partial C_0}{\partial a^{(L)}_j} $

各因子を計算します。

$latex \frac{\partial z^{(L)}j}{\partial w^{(L)}{jk}} = a^{(L-1)}_k $

\frac{\partial a^{(L)}_j}{\partial z^{(L)}_j} = \sigma' \left( z^{(L)}_j \right)

\frac{\partial C_0}{\partial a^{(L)}_j} = 2 \left( a^{(L)}_j - y_j \right)

添え字が付いただけで、中身は同じです。

練習問題10

w^{(L)}_{23} は、どのニューロンからどのニューロンへの重みですか。また、この順序になっている理由を説明してください。

解答を示します。

L-1 層の3番目のニューロンから、第 L 層の2番目のニューロンへの重みです。

順序の理由は、重み行列の表記と一致させるためです。行列では行番号を先、列番号を後に書きます。そして重み行列では、行が出力側、列が入力側に対応します。

したがって、出力側の番号を先に書く形になります。

補足します。この順序は、多くの文献で共通しています。

慣れるまでは混乱しますが、行列で書いたときの整合性を考えると必然的な選択です。

8 和が現れる場所

一つだけ違うところ

ニューロンが増えて変わるのは、一箇所だけです。

前の層の活性化に対する感度です。

なぜ変わるのか

a^{(L-1)}_k というニューロンを考えます。

このニューロンは、次の層のすべてのニューロンに影響します。a^{(L)}_0 にも、a^{(L)}_1 にも、すべてに。

つまり、コストへ至る経路が複数あります。

経路をすべて足す

複数の経路がある場合、連鎖律は和になります。

$latex \frac{\partial C_0}{\partial a^{(L-1)}k} = \sum{j} \frac{\partial z^{(L)}_j}{\partial a^{(L-1)}_k} \cdot \frac{\partial a^{(L)}_j}{\partial z^{(L)}_j} \cdot \frac{\partial C_0}{\partial a^{(L)}_j} $

j について足し合わせています。

具体的に書く

最初の因子を計算します。

$latex \frac{\partial z^{(L)}_j}{\partial a^{(L-1)}k} = w^{(L)}{jk} $

代入します。

$latex \frac{\partial C_0}{\partial a^{(L-1)}k} = \sum{j} w^{(L)}_{jk} \cdot \sigma' \left( z^{(L)}_j \right) \cdot 2 \left( a^{(L)}_j - y_j \right) $

前回の記事とのつながり

前回、「10個の出力ニューロンの要望を足し合わせる」と説明しました。

その足し合わせが、この \sum_j です。

会議の比喩も使いました。複数の参加者が、それぞれの重みで意見を出し、合計が結論になる。その数式表現が、この和です。

変わったのはここだけ

整理します。

項目ニューロン1個ニューロン複数
重みの勾配同じ形添え字が付くだけ
バイアスの勾配同じ形添え字が付くだけ
前の活性化への感度単独和が入る

本質的な変化は、最後の一行だけです。

練習問題11

前の層の活性化に対する感度を求めるとき、なぜ和を取る必要があるのですか。

解答を示します。

そのニューロンが、次の層の複数のニューロンに影響するためです。

a^{(L-1)}_k は、z^{(L)}_0 z^{(L)}_1 、というように、次の層のすべての z に寄与します。そしてそれぞれが、コストに影響します。

コストへ至る経路が複数あるため、すべての経路の寄与を足し合わせる必要があります。

補足します。重みの勾配では、和は現れません。

w^{(L)}_{jk} という一つの重みは、z^{(L)}_j にしか影響しないためです。経路が1本しかないので、足し合わせる相手がありません。

この違いを押さえておくと、式の形が記憶に残ります。

練習問題12

出力層に3個のニューロンがあり、a^{(L-1)}_1 からの各経路の寄与が 0.3 -0.5 0.4 でした。\frac{\partial C_0}{\partial a^{(L-1)}_1} を求めてください。

解答を示します。

すべての経路を足します。

0.3 + (-0.5) + 0.4 = 0.2

補足します。2番目の経路は逆向きの寄与でした。

合計すると正になったため、このニューロンの活性化を下げる方向へ修正が働きます。

個々の出力ニューロンの要望が対立することは珍しくありません。合計が結論になります。

9 全体の手順

数式をまとめます。

順伝播

手順
1$latex z^{(l)}j = \sum_k w^{(l)}{jk} a^{(l-1)}_k + b^{(l)}_j $
2a^{(l)}_j = \sigma \left( z^{(l)}_j \right)

入力層から出力層へ、順に計算します。

逆伝播

手順
1出力層の誤差項を求める
2重みとバイアスの勾配を求める
3前の層への感度を求める
4一つ前の層で1に戻る

出力層の誤差項です。

\delta^{(L)}_j = \sigma' \left( z^{(L)}_j \right) \cdot 2 \left( a^{(L)}_j - y_j \right)

勾配です。

\frac{\partial C_0}{\partial w^{(L)}_{jk}} = a^{(L-1)}_k \delta^{(L)}_j

\frac{\partial C_0}{\partial b^{(L)}_j} = \delta^{(L)}_j

前の層の誤差項です。

$latex \delta^{(L-1)}k = \left( \sum_j w^{(L)}{jk} \delta^{(L)}_j \right) \sigma' \left( z^{(L-1)}_k \right) $

順伝播と逆伝播の対応

構造を比べます。

方向式の形
順伝播\sum_k w_{jk} a_k
逆伝播\sum_j w_{jk} \delta_j

足し合わせる添え字が入れ替わっています。

順伝播では k について足し、逆伝播では j について足します。

これが、行列で書いたときに転置が現れる理由です。同じ重みを、逆向きに読んでいます。

練習問題13

順伝播と逆伝播で、和を取る添え字がどう違うか説明してください。また、行列で書いたときに何が起きますか。

解答を示します。

順伝播では、\sum_k w_{jk} a_k のように k について足します。j を固定し、入力側を集約しています。

逆伝播では、\sum_j w_{jk} \delta_j のように j について足します。k を固定し、出力側を集約しています。

行列で書くと、順伝播が Wa 、逆伝播が W^{T}\delta になります。転置が現れます。

補足します。転置は、暗記すべき規則ではありません。

同じ重みの表を、行方向に読むか列方向に読むかの違いです。順伝播では入力から出力へ、逆伝播では出力から入力へ読みます。

10 研修での教え方

このテーマを扱う場合の設計案です。

90分の構成

時間内容形式
5分記号の確認。上付きは層番号講義
10分最小ネットワークの三つの式講義
15分連鎖律の分解。三つの因子講義
10分練習問題3と4個人
10分バイアスと前の層への感度講義
10分練習問題7と8個人
10分ニューロンが増えた場合。和の登場講義
10分練習問題11と12個人
10分順伝播と逆伝播の対応。まとめ講義

教える順序の考え方

三つ、意識してください。

一つ目は、記号の説明を省かないことです。

上付き文字が層の番号であることを、最初に明言してください。累乗と誤解されると、以降がすべて崩れます。

二つ目は、各層1ニューロンから始めることです。

いきなり添え字を二つ付けると、式が読めなくなります。まず単純な形で連鎖律を理解し、その後で添え字を足してください。

三つ目は、因子の意味を毎回確認することです。

式を並べるだけでは、記号の羅列になります。a^{(L-1)} が出てきたら「前の層の活発さ」、2(a - y) が出てきたら「間違いの大きさ」と、その都度言葉に戻してください。

つまずきやすい点

四つあります。

一つ目は、上付き文字の誤解です。前述の通りです。

二つ目は、重みの添え字の順序です。

w_{jk} が「k から j へ」であることは、直感に反します。行列表記との整合性が理由だと説明してください。

三つ目は、和が現れる場所です。

重みの勾配には和がなく、前の層への感度には和がある。この違いを、経路の数で説明すると伝わります。

四つ目は、1例分と全データの区別です。

C_0 C を明確に使い分けてください。記号が似ているため、混同されやすい部分です。

想定される質問

質問1 なぜコストに \frac{1}{2} を付けないのですか。

回答します。付ける流儀もあります。微分したときに2が消えて式が簡潔になるためです。この記事では付けていないため、2(a - y) という形になりました。どちらでも本質は変わりません。学習率を調整すれば、同じ結果が得られます。

質問2 二乗誤差以外のコスト関数もありますか。

回答します。分類問題では交差エントロピーがよく使われます。

C_0 = -\sum_j y_j \ln a^{(L)}_j

微分すると形が簡潔になり、勾配が大きく取れるため学習が速く進みます。二乗誤差を分類に使うと、シグモイドとの組み合わせで勾配が小さくなりやすいという問題があります。

質問3 計算量はどれくらいですか。

回答します。順伝播とほぼ同程度です。素朴に偏微分を一つずつ数値的に求めると、パラメータ数だけ順伝播を繰り返す必要があります。13,002回です。逆伝播なら、順伝播1回と逆伝播1回で済みます。

質問4 自動微分とは何が違うのですか。

回答します。誤差逆伝播法は、自動微分の一種です。正確には逆方向自動微分と呼ばれる手法にあたります。現代のライブラリは、この仕組みを汎用化して実装しています。自分で微分の式を書かなくても、計算のグラフから自動的に勾配が求まります。

まとめと次の学習ステップ

誤差逆伝播法を数式で追うと、連鎖律の繰り返しであることが見えてきます。

中心にあるのは、次の一行です。

\frac{\partial C_0}{\partial w^{(L)}} = a^{(L-1)} \cdot \sigma' \left( z^{(L)} \right) \cdot 2 \left( a^{(L)} - y \right)

三つの因子には、それぞれ意味があります。前の層の活発さ、活性化関数の反応、出力の間違いの大きさ。どれか一つでも0に近ければ、全体が小さくなります。

バイアスの勾配は、最初の因子が1に変わるだけです。前の層への感度は、最初の因子が w^{(L)} に変わるだけです。共通部分を \delta と名付ければ、三つの式が簡潔にまとまります。

ニューロンが増えても、構造は変わりません。添え字が増え、前の層への感度を求めるところで和が入る。それだけです。経路が複数あるから足し合わせる。この一点さえ押さえれば、添え字に惑わされずに済みます。

そして、順伝播と逆伝播では、和を取る添え字が入れ替わります。これが、行列表記で転置が現れる理由です。

次の学習ステップとして、三つを提案します。

一つ目は、小さなネットワークで手計算することです。入力2、中間2、出力1程度の構成で、順伝播と逆伝播を最後まで計算してください。更新後に損失が下がることを自分で確認すると、理解が確信に変わります。

二つ目は、数値微分と比較することです。手で求めた勾配と、パラメータを微小に動かして求めた値が一致すれば、計算は正しいと言えます。実装のときにも使える検証方法です。

三つ目は、交差エントロピーに進むことです。分類問題では、二乗誤差よりこちらが標準です。シグモイドと組み合わせたとき、勾配の形がどれだけ簡潔になるかを確認してみてください。対数を取ることの意味が、ここで実感できます。

四回にわたって、構造、学習、逆伝播の直感、そして数式を追ってきました。土台は、すでにできています。

セイ・コンサルティング・グループでは新人エンジニア研修のアシスタント講師を募集しています。

投稿者プロフィール

山崎講師
山崎講師代表取締役
セイ・コンサルティング・グループ株式会社代表取締役。
岐阜県出身。
海外放浪の末、2000年創業、2004年会社設立。
IT企業向け人材育成研修歴業界歴20年以上。
すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
この記事に間違い等ありましたらぜひお知らせください。

学生時代は趣味と実益を兼ねてリゾートバイトにいそしむ。長野県白馬村に始まり、志賀高原でのスキーインストラクター、沖縄石垣島、北海道トマム。高じてオーストラリアのゴールドコーストでツアーガイドなど。現在は野菜作りにはまっている。