我想先弄清楚什么

学习深度学习时,最容易把“会调用 backward()”误认为“理解了反向传播”。这篇记录只做一件事:把一个很小的计算图写出来,手算它的梯度,再让 PyTorch 验证同一个结果。

先用直觉看计算图

设输入为 x,中间变量为 u,最后的损失为 L

x → u = 2x + 1 → L = u²

xL 有两段局部变化。链式法则把它们乘起来:

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()、不同学习率和激活函数对梯度的影响。实验结果会继续放在这篇记录下面,而不是只留下一个最终结论。

参考资料

END OF ARTICLE

把结论留下,也把下一次实验的入口留下。

Back to blog ↗