我想先弄清楚什么
学习深度学习时,最容易把“会调用 backward()”误认为“理解了反向传播”。这篇记录只做一件事:把一个很小的计算图写出来,手算它的梯度,再让 PyTorch 验证同一个结果。
先用直觉看计算图
设输入为 x,中间变量为 u,最后的损失为 L:
x → u = 2x + 1 → L = u²
从 x 到 L 有两段局部变化。链式法则把它们乘起来:
dL/dx = dL/du · du/dx = 2u · 2
这就是反向传播最小的形状:从结果开始,沿着计算图反向累积局部导数。
用 PyTorch 做同一件事
import torch
x = torch.tensor(3.0, requires_grad=True)
u = 2 * x + 1
loss = u ** 2
loss.backward()
print(u.item()) # 7.0
print(loss.item()) # 49.0
print(x.grad.item()) # 28.0
手算得到 2 × 7 × 2 = 28,和自动微分的结果一致。这个小实验的价值不在于数值本身,而在于把“变量、依赖关系、梯度”和“实验输出”对应起来。
记录一次实验时我会保留什么
- 假设:我认为哪一个变量会影响损失?
- 最小实现:能否用十几行代码复现?
- 检查:手算、自动微分和有限差分是否一致?
- 失败:梯度为零、爆炸或没有清零时发生了什么?
- 下一步:这个结论如何迁移到一个真实网络?
下一步实验
把标量换成一个两层 MLP,分别比较 zero_grad()、不同学习率和激活函数对梯度的影响。实验结果会继续放在这篇记录下面,而不是只留下一个最终结论。
