十四个开关 · 第 07 份 · Linnainmaa 1970 / Rumelhart–Hinton–Williams 1986

梯度开关

训练一个神经网络,要知道每一个参数该往哪边动。最笨的办法是逐个参数试探一下——这叫数值微分,它给的答案是对的。反向传播给的是同一个答案,代价却只有一次前向加一次反向。下面两边花的前向传播次数一模一样

总闸

两个螺旋 · 同样的前向传播预算

两边同一个初始权重、同一批数据、同一个学习率

损失 vs 花掉的前向传播次数

横轴不是「第几步」,是「花了多少算力」—— 这才是公平的横轴
反向传播(每步 2 次前向) 数值微分(每步 2P 次前向)

ε 该取多大 · 一条真跑出来的 U 型曲线

正在逐个 ε 实测…
数值梯度相对反向传播的最大误差 ∛机器精度 ≈ 6×10⁻⁶(中心差分的理论最优点)

关掉的是哪一行

backward() 换成中心差分:对每一个参数分别算 (L(w+ε) − L(w−ε)) / 2ε其余一个字不动——同一个初始权重、同一批数据、同一个学习率、同一个优化器。

关键是横轴:上面那张损失曲线的横轴不是「第几步」,是「已经花掉多少次前向传播」。按步数比,两条曲线几乎重合(因为梯度一样);按算力比,才看得见那 P 倍的差距。

数值微分没有算错

这一点必须说清楚:它给的梯度是对的。ε 取 10⁻⁴ 时,它和反向传播算出来的梯度最大相对误差只有 7.6×10⁻¹⁰——纯粹是浮点舍入。

所以这不是「一个对一个错」的对照,是同一个答案,两个价钱。反向传播赢的全部理由只有一句:反向走一遍的代价,和正向走一遍同阶。而这句话就是链式法则。

⚠ 我预期错了:最优 ε 不是 10⁻⁸

动手前我写下「U 型的底在 √机器精度 ≈ 1.5×10⁻⁸」——实测在 10⁻⁴ ~ 10⁻⁵。因为这里用的是中心差分,截断误差是 O(ε²) 不是 O(ε),最优点是 ∛机器精度 ≈ 6×10⁻⁶。√εₘ 那个数是前向差分的。

⚠ 而实测最低点落在 10⁻⁴,比理论点 6×10⁻⁶ 还大一档半——因为这个网络的三阶导很小(截断误差常数只有 0.076)。而底部很平:从 10⁻⁴ 到 10⁻⁶ 误差都在 10⁻⁹ 量级 ⇒ 「最优 ε」本来就不是一个点,是一段。

U 型两侧的斜率能直接从图上读出来验证:左支 ε 每降一个数量级,误差降 两个(O(ε²) 的签名);右支 ε 每降一个数量级,误差涨 一个(舍入误差 O(1/ε) 的签名)。

它什么时候不赢

参数少的时候差距就小。P = 205 时只差 205 倍;真正吓人的是外推:把右边那根滑块推到 10¹²(GPT 规模),差 10¹² 倍——把地球上所有 GPU 拿来从宇宙诞生开始算也不够。

② 反向传播的代价是内存:它必须把前向的每一层中间激活都存下来才能往回走。这正是训练比推理吃显存得多的原因,也是 gradient checkpointing(拿时间换显存)存在的理由。数值微分反而几乎不占内存。