返回 M01~M90 教材库
M02 · 预习教材教材已备 ≠ 学习已完成

M02:不用 autograd 手写反向传播

手写反向传播就是为计算图中每个基本运算写出局部导数,再按反向拓扑顺序传播并累加梯度。

2026-08-25链式法则、局部导数、计算图、手写反向传播

内容类型:预习教材(不代表已完成)
日期:2026-08-25
阶段:P1 · AI Model Engineering 90
周次:W1 · 张量、梯度、autograd
节奏:周二最小实现
状态:教材已备;学习未完成
标签:链式法则、局部导数、计算图、手写反向传播

一句话定义

手写反向传播就是为计算图中每个基本运算写出局部导数,再按反向拓扑顺序传播并累加梯度。

学习目标

  1. 把一个复合表达式拆成可检查的计算节点。
  2. 手算乘法、加法、平方和 ReLU 的局部梯度。
  3. 理解梯度累加和反向拓扑顺序为什么必要。
  4. 写出不依赖 autograd 的最小反向传播实现。

核心知识

反向传播的入口是 ∂L/∂L = 1。对于节点 z = a+b,上游梯度记为 g,则传给 a、b 的梯度都是 g;对于 z = ab,传给 a 的梯度是 gb,传给 b 的梯度是 ga;对于 z = a²,传给 a 的梯度是 2ag;对于 z = ReLU(a),a>0 时传回 g,否则为 0,在 a=0 处通常约定一个次梯度。

“上游梯度 × 局部梯度”是核心操作。如果一个参数通过多条路径影响损失,各路径贡献必须相加而不是覆盖。例如 L = w² + 3w,w 同时进入平方和线性分支,因此 ∂L/∂w = 2w + 3。代码里的 grad += contribution 正是这一数学事实。

实现时可让每个节点保存 value、parents、local backward 函数和 grad。正向构图后,对节点做拓扑排序,再从输出节点逆序执行 backward。即使只实现标量,也能看清现代框架的基本骨架。

机制与推导

选择表达式:a = wx,b = a+c,ŷ = b²,L = (ŷ-y)²。反向依次为:

  • ∂L/∂ŷ = 2(ŷ-y)
  • ∂ŷ/∂b = 2b
  • ∂b/∂a = 1,∂b/∂c = 1
  • ∂a/∂w = x,∂a/∂x = w

所以 ∂L/∂w = 2(ŷ-y)·2b·x,∂L/∂c = 2(ŷ-y)·2b。推导时要把每个节点的正向值保留下来,因为局部导数经常依赖它,例如乘法需要另一个输入,平方需要原输入。

有限差分可做独立检查:把 w 改成 w+ε 和 w-ε,近似梯度为 [L(w+ε)-L(w-ε)]/(2ε)。它不是训练方法,但能检查解析反向传播是否漏乘、符号错误或忘记累加。

最小练习

  1. 先给 w、x、c、y 指定很小的标量值,在纸上完成所有正向节点。
  2. 从 L 的梯度 1 开始,逆序填写每个节点的梯度。
  3. 用十几到几十行代码表示节点和四种运算,禁止调用 autograd。
  4. 对 w 做中心有限差分,比较方向和数量级;未运行前不写结果。
  5. 故意把某处 grad += 改成赋值,思考共享参数会出现什么问题。

常见误区

  • 直接对整个长公式求导,容易漏掉共享路径,分节点更可靠。
  • 反向传播不等于梯度下降;前者求导,后者使用导数更新。
  • 多分支梯度应求和,不是求平均,也不能后来的覆盖前面的。
  • 有限差分的 ε 不是越小越好,太小会受浮点舍入影响。
  • ReLU 的导数简单,但大量负区间可能让对应单元不再更新。

场景连接

金融模型常把多个损失组合为总目标,例如分类损失加稳定性惩罚。手写小图能帮助理解每个损失分支如何共同影响共享参数,也能看出“给某项更高权重”会直接放大它对更新方向的贡献。

自检问题

  1. 为什么输出节点的初始梯度设为 1?
  2. 同一个参数被使用三次时,梯度如何处理?
  3. 为什么反向传播需要与正向依赖相反的顺序?
  4. 有限差分与解析梯度差异很大时,应先检查哪些地方?

专业课程对齐

  • Stanford CS229 Materials:对应线性模型、链式法则与梯度下降推导。重点不是抄结论,而是辨认每个局部导数的输入、输出和维度。
  • MIT 6.S191:对应神经网络基础中的前向传播与反向传播,适合把标量手算扩展到层和参数矩阵。
  • PyTorch Autograd 教程:作为手推结果的实现参照,理解自动微分复用的仍是同一条链式法则。

深入学习提示

先精读 CS229 中梯度下降和链式法则相关材料,完整手算一个两层复合函数;再看 6.S191 如何把局部导数组合成网络反传;最后选读 autograd 页面核对实现。公式观察点是分支节点的梯度求和、矩阵乘法的转置位置,以及 batch 求和与求平均带来的比例差异。建议用有限差分 (L(w+ε)-L(w-ε))/(2ε) 检查一个参数。反例要覆盖饱和激活导致局部导数接近零、把导数相乘顺序写对但维度写错、以及重复使用变量时漏掉一条路径;这些比得到一次正确数值更能检验是否真正理解反传。

学后填写区

  • 手算表达式与数值:____
  • 我的最小实现路径:____
  • 梯度检查观察:____
  • 仍可能出错的节点:____
  • 实际学习日期与用时:____
学完后,请把自己的理解、练习结果和仍不确定的问题写入文末“学后填写区”,再到唯一进度账本更新状态。预先阅读后续教材不会自动增加完成数。