反向传播的数学本质
本章将手算一个两层神经网络的反向传播全过程。
反向传播 = 计算图上的链式法则系统化应用。
概念解析
计算图:前向和反向
一个简单两层网络:输入 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₂ 的梯度 → L 对 w₂:\( \frac{\partial \hat{y}}{\partial w_2} = a_1 = 1.0 \),\( \frac{\partial L}{\partial w_2} = (-6) \times 1.0 = -6 \)
L 对 a₁ 的梯度(继续向前传):\( \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 \)
L 对 w₁:\( \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("=== RUNOOB 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)")
# 梯度下降一步
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"损失减小了!")
=== RUNOOB 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 损失减小了!
反向传播 = 三条线汇合
前向传播 = 矩阵运算
z = Wx + b
反向传播 = 链式法则
∂L/∂w = ∂L/∂z · ∂z/∂w
参数更新 = 梯度下降
θ = θ - η∇J
损失设计 = MLE + 交叉熵
L = -log P(y|x)
反向传播本质上就做了三件事:前向用矩阵运算算输出,反向用链式法则算梯度,拿到梯度后用梯度下降更新参数。
概率统计和信息论为损失函数的选择提供了理论依据。
