反向传播
反向传播是训练神经网络的核心算法。它用链式法则计算损失函数对每个参数的梯度。
flowchart LR A[输入 x] --> B[层1<br/>W₁] B --> C[层2<br/>W₂] C --> D[损失 L] D -->|∂L/∂W₂| C C -->|∂L/∂W₁| B前向传播计算输出,反向传播计算梯度。
对于复合函数 :
import torchimport torch.nn as nn
# 一个简单的两层网络class SimpleNet(nn.Module): def __init__(self): super().__init__() self.fc1 = nn.Linear(10, 5) self.fc2 = nn.Linear(5, 1)
def forward(self, x): h = torch.relu(self.fc1(x)) return self.fc2(h)
model = SimpleNet()x = torch.randn(3, 10) # batch=3y = torch.randn(3, 1) # 目标值
# 前向传播pred = model(x)loss = nn.MSELoss()(pred, y)
# 反向传播loss.backward()
# 查看梯度print(f"fc1.weight 梯度形状: {model.fc1.weight.grad.shape}")print(f"fc2.weight 梯度形状: {model.fc2.weight.grad.shape}")手动计算梯度
Section titled “手动计算梯度”# 手动实现一个计算图的反向传播x = torch.tensor([2.0], requires_grad=True)w = torch.tensor([3.0], requires_grad=True)b = torch.tensor([1.0], requires_grad=True)
# 前向: y = w * x + b, loss = y²y = w * x + bloss = y ** 2
# 反向loss.backward()
# 手动验证: ∂loss/∂w = 2y * xy_val = (3.0 * 2.0 + 1.0) # = 7expected_grad = 2 * y_val * 2.0 # = 28print(f"自动求导: {w.grad.item()}, 手动计算: {expected_grad}")梯度消失与爆炸
Section titled “梯度消失与爆炸”flowchart TD A[梯度 < 1] -->|反复相乘| B[梯度消失<br/>≈ 0] C[梯度 > 1] -->|反复相乘| D[梯度爆炸<br/>→∞]| 问题 | 原因 | 表现 | 解决 |
|---|---|---|---|
| 梯度消失 | 深层网络梯度过小 | 浅层不更新 | ReLU、残差连接、LayerNorm |
| 梯度爆炸 | 深层网络梯度过大 | 参数变为 NaN | 梯度裁剪、学习率调低 |
# 梯度裁剪torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)