逆伝播の数学的本質
この章では、2層ニューラルネットワークの逆伝播の全過程を手計算します。
逆伝播 = 計算グラフ上のチェーン則の体系的な適用です。
概念解説
計算グラフ:順伝播と逆伝播
シンプルな2層ネットワーク:入力 x → 隠れ層(ReLU)→ 出力 → MSE損失。
順伝播は左から右へ出力を計算します。逆伝播は右から左へ各パラメータの損失に対する勾配を計算します。
完全な例を手計算する
x=2、y=4(真のラベル)とし、パラメータは w₁=0.5、b₁=0、w₂=1、b₂=0 とします。
順伝播
| ステップ | 計算 | 值 |
|---|---|---|
| z₁ = w₁x + b₁ | 0.5×2 + 0 | 1.0 |
| a₁ = ReLU(z₁) | max(0, 1.0) | 1.0 |
| ŷ = w₂a₁ + b₂ | 1×1.0 + 0 | 1.0 |
| L = (ŷ - y)² | (1-4)² | 9.0 |
逆伝播(チェーン則)
ŷ に対する損失の勾配:\( \frac{\partial L}{\partial \hat{y}} = 2(\hat{y}-y) = 2(1-4) = -6 \)
w₂ に対する ŷ の勾配 → w₂ に対する L:\( \frac{\partial \hat{y}}{\partial w_2} = a_1 = 1.0 \),\( \frac{\partial L}{\partial w_2} = (-6) \times 1.0 = -6 \)
a₁ に対する L の勾配(さらに前へ伝播):\( \frac{\partial L}{\partial a_1} = \frac{\partial L}{\partial \hat{y}} \cdot w_2 = -6 \times 1 = -6 \)
ReLU を通過:\( \frac{\partial a_1}{\partial z_1} = 1 \)(z₁=1>0 のため)、\( \frac{\partial L}{\partial z_1} = -6 \)
w₁ に対する L:\( \frac{\partial L}{\partial w_1} = \frac{\partial L}{\partial z_1} \cdot x = -6 \times 2 = -12 \)
勾配をまとめて更新
| パラメータ | 勾配 | 更新 (lr=0.1) |
|---|---|---|
| w₁ | -12 | 0.5 + 1.2 = 1.7 |
| b₁ | -6 | 0 + 0.6 = 0.6 |
| w₂ | -6 | 1 + 0.6 = 1.6 |
| b₂ | -6 | 0 + 0.6 = 0.6 |
勾配がすべて負である——現在の予測が小さすぎる(1 < 4)ことを示しており、すべてのパラメータを大きくする必要があります。
w₁ の勾配(-12)は w₂(-6)より大きい:w₁ は損失からより遠く、チェーン伝播の経路が長く、さらに x=2 が掛けられているためです。
Python での検証
実例
x = torch.tensor([2.0])
y = torch.tensor([4.0])
w1 = torch.tensor([0.5], requires_grad=True)
b1 = torch.tensor([0.0], requires_grad=True)
w2 = torch.tensor([1.0], requires_grad=True)
b2 = torch.tensor([0.0], requires_grad=True)
# 順伝播
a1 = torch.relu(w1 * x + b1)
y_pred = w2 * a1 + b2
loss = (y_pred - y) ** 2
loss.backward()
print("=== サンプル PyTorch 検証 ===")
print(f"∂L/∂w1 = {w1.grad.item():.1f} (手計算: -12)")
print(f"∂L/∂b1 = {b1.grad.item():.1f} (手計算: -6)")
print(f"∂L/∂w2 = {w2.grad.item():.1f} (手計算: -6)")
print(f"∂L/∂b2 = {b2.grad.item():.1f} (手計算: -6)")
# 勾配降下法で1ステップ
lr = 0.1
with torch.no_grad():
w1 -= lr * w1.grad; b1 -= lr * b1.grad
w2 -= lr * w2.grad; b2 -= lr * b2.grad
new_loss = ((w2 * torch.relu(w1*x+b1) + b2 - y)**2).item()
print(f"\n元の損失: {loss.item():.1f} → 新しい損失: {new_loss:.2f}")
print(f"損失が減少しました!")
=== サンプル PyTorch 验证 === ∂L/∂w1 = -12.0 (手算: -12) ∂L/∂b1 = -6.0 (手算: -6) ∂L/∂w2 = -6.0 (手算: -6) ∂L/∂b2 = -6.0 (手算: -6) 原损失: 9.0 → 新损失: 1.03 损失减小了!
逆伝播 = 3つの線が合流
順伝播 = 行列演算
z = Wx + b
逆伝播 = チェーン則
∂L/∂w = ∂L/∂z · ∂z/∂w
パラメータ更新 = 勾配降下法
θ = θ - η∇J
損失設計 = MLE + 交差エントロピー
L = -log P(y|x)
逆伝播は本質的に3つのことを行います:順伝播で行列演算により出力を計算し、逆伝播でチェーン則により勾配を計算し、得られた勾配で勾配降下法によりパラメータを更新します。
確率統計と情報理論は、損失関数の選択に理論的根拠を提供します。
その他の拡張