はじめに
Deep Learning では、モデルの性能を向上させるために、損失関数(予測と正解のズレ)を最小化するようにパラメータ(重みやバイアス)を調整します。このパラメータ調整には、損失関数に対する各パラメータの勾配(どれだけパラメータを変化させると損失が変化するかを示す値)が必要です。
この勾配計算には、一般的に誤差逆伝播法 (Backpropagation) が用いられます。では、なぜ入力側から出力側へ向かって計算していく順伝播的な勾配計算は非効率なのでしょうか?
ここでは、単純な 2 層ニューラルネットワークを例に、その理由と誤差逆伝播法の効率性を解説します。
例で使用するネットワークと仮定:
-
ネットワーク: $x \xrightarrow{w_1} z_h \rightarrow h \xrightarrow{w_2} z_y \rightarrow y \rightarrow L$
- $x$: 入力, $h$: 隠れ層出力, $y$: 最終出力
- $z_h = w_1 x$ (簡単のためバイアスは省略)
- $h = f(z_h)$ ($f$: 隠れ層の活性化関数)
- $z_y = w_2 h$ (簡単のためバイアスは省略)
- $y = g(z_y)$ ($g$: 出力層の活性化関数)
- $L$: 損失関数
- 目標: 損失 $L$ に関するパラメータ $w_1, w_2$ の勾配 $\frac{\partial L}{\partial w_1}, \frac{\partial L}{\partial w_2}$ を計算する。
-
仮定(簡単のため):
- 活性化関数 $f, g$ は恒等関数 ($f(z)=z, g(z)=z$) とする。つまり $\frac{\partial h}{\partial z_h} = 1, \frac{\partial y}{\partial z_y} = 1$。
- 損失関数 $L$ は平均二乗誤差 (MSE) の一部 $L = \frac{1}{2}(y - \text{正解})^2$ とする。つまり $\frac{\partial L}{\partial y} = y - \text{正解}$。
順伝播的な勾配計算とその非効率性
順伝播的な勾配計算は、入力に近いパラメータから順に、連鎖律(Chain Rule)を用いて勾配を計算していく方法です。
上記の 2 層ネットワークの場合、連鎖律による勾配は以下のようになります。
- $\frac{\partial L}{\partial w_1} = \frac{\partial L}{\partial y} \times \frac{\partial y}{\partial z_y} \times \frac{\partial z_y}{\partial h} \times \frac{\partial h}{\partial z_h} \times \frac{\partial z_h}{\partial w_1}$
- $\frac{\partial L}{\partial w_2} = \frac{\partial L}{\partial y} \times \frac{\partial y}{\partial z_y} \times \frac{\partial z_y}{\partial w_2}$
この計算では、$\frac{\partial L}{\partial w_1}$ と $\frac{\partial L}{\partial w_2}$ の両方で、共通の計算部分 $\frac{\partial L}{\partial y} \times \frac{\partial y}{\partial z_y}$ が出現します。
層が増えると、この重複はさらに深刻になります。例えば、4 層のネットワーク $x \xrightarrow{w_1} h_1 \xrightarrow{w_2} h_2 \xrightarrow{w_3} h_3 \xrightarrow{w_4} y \rightarrow L$ を考えると、各パラメータの勾配は以下のようになります。
$\frac{\partial L}{\partial w_1} = (\frac{\partial L}{\partial y} \frac{\partial y}{\partial z_y} \frac{\partial z_y}{\partial h_3} \frac{\partial h_3}{\partial z_{h3}} \frac{\partial z_{h3}}{\partial h_2} \frac{\partial h_2}{\partial z_{h2}} \frac{\partial z_{h2}}{\partial h_1} \frac{\partial h_1}{\partial z_{h1}}) \times \frac{\partial z_{h1}}{\partial w_1}$
$\frac{\partial L}{\partial w_2} = (\frac{\partial L}{\partial y} \frac{\partial y}{\partial z_y} \frac{\partial z_y}{\partial h_3} \frac{\partial h_3}{\partial z_{h3}} \frac{\partial z_{h3}}{\partial h_2} \frac{\partial h_2}{\partial z_{h2}}) \times \frac{\partial z_{h2}}{\partial w_2}$
$\frac{\partial L}{\partial w_3} = (\frac{\partial L}{\partial y} \frac{\partial y}{\partial z_y} \frac{\partial z_y}{\partial h_3} \frac{\partial h_3}{\partial z_{h3}}) \times \frac{\partial z_{h3}}{\partial w_3}$
$\frac{\partial L}{\partial w_4} = (\frac{\partial L}{\partial y} \frac{\partial y}{\partial z_y}) \times \frac{\partial z_y}{\partial w_4}$
(※ $\times$ を省略して並べています)
このように、各パラメータの勾配を順伝播的に計算すると、出力層に近い部分の計算(括弧内の共通部分)がパラメータごとに何度も繰り返し現れ、層が深くなるほど計算量が爆発的に増加してしまいます。これが順伝播的な勾配計算の非効率性です。
誤差逆伝播法(Backpropagation)の効率性
誤差逆伝播法は、この計算の重複を避けるために考案されました。出力層から入力層に向かって、誤差信号 $\delta$ (各層の活性化関数への入力 $z$ に関する最終的な損失 $L$ の勾配 $\frac{\partial L}{\partial z}$)を計算し、それを再利用して各パラメータの勾配を効率的に求めます。
1. 出力層の誤差信号 $\delta_y$ の計算:
まず、出力層の活性化関数への入力 $z_y$ に対する損失 $L$ の勾配 $\delta_y = \frac{\partial L}{\partial z_y}$ を計算します。
$\delta_y = \frac{\partial L}{\partial z_y} = \frac{\partial L}{\partial y} \times \frac{\partial y}{\partial z_y}$
(仮定より $\frac{\partial L}{\partial y} = y - \text{正解}$, $\frac{\partial y}{\partial z_y} = 1$ なので、 $\delta_y = (y - \text{正解}) \times 1 = y - \text{正解}$ となります。)
2. 出力層のパラメータ $w_2$ の勾配計算:
計算済みの $\delta_y$ を使って、出力層の重み $w_2$ の勾配 $\frac{\partial L}{\partial w_2}$ を計算します。
$\frac{\partial L}{\partial w_2} = \frac{\partial L}{\partial z_y} \times \frac{\partial z_y}{\partial w_2} = \delta_y \times \frac{\partial (w_2 h)}{\partial w_2} = \delta_y \times h$
(ここで $\frac{\partial L}{\partial z_y}$ の計算結果 $\delta_y$ を再利用しています。)
3. 隠れ層の誤差信号 $\delta_h$ の計算:
次に、誤差信号 $\delta_y$ を隠れ層へ逆伝播させ、隠れ層の活性化関数への入力 $z_h$ に対する損失 $L$ の勾配 $\delta_h = \frac{\partial L}{\partial z_h}$ を計算します。
$\delta_h = \frac{\partial L}{\partial z_h} = \frac{\partial L}{\partial z_y} \times \frac{\partial z_y}{\partial h} \times \frac{\partial h}{\partial z_h} = \delta_y \times \frac{\partial (w_2 h)}{\partial h} \times \frac{\partial h}{\partial z_h}$
(仮定より $\frac{\partial h}{\partial z_h} = 1$ なので、 $\delta_h = \delta_y \times w_2 \times 1 = \delta_y w_2$ となります。)
(ここでも $\delta_y$ を再利用しています。)
4. 隠れ層のパラメータ $w_1$ の勾配計算:
計算済みの $\delta_h$ を使って、隠れ層の重み $w_1$ の勾配 $\frac{\partial L}{\partial w_1}$ を計算します。
$\frac{\partial L}{\partial w_1} = \frac{\partial L}{\partial z_h} \times \frac{\partial z_h}{\partial w_1} = \delta_h \times \frac{\partial (w_1 x)}{\partial w_1} = \delta_h \times x$
(ここで $\frac{\partial L}{\partial z_h}$ の計算結果 $\delta_h$ を再利用しています。)
このように、誤差逆伝播法では、出力層から順に誤差信号 $\delta$ を計算し、その $\delta$ を次の層の $\delta$ 計算や、その層のパラメータ勾配計算に再利用します。これにより、順伝播的な勾配計算で発生した計算の重複が解消され、効率的に全パラメータの勾配を求めることができます。
結論
- 順伝播的な勾配計算 は、各パラメータの勾配を計算する際に、出力に近い部分の計算を何度も繰り返してしまうため、特に層が深いネットワークでは計算量が非常に多くなり非効率です。
- 誤差逆伝播法 (Backpropagation) は、出力層から逆向きに「誤差信号 $\delta$」($\frac{\partial L}{\partial z}$)を計算し、その結果を再利用することで、計算の重複を避け、全てのパラメータの勾配を効率的に計算できます。
多くのパラメータを持つ深いニューラルネットワークの学習において、勾配計算の効率は極めて重要です。そのため、現在広く使われている Deep Learning フレームワークでは、誤差逆伝播法が標準的な勾配計算手法として採用されています。