数值微分与自动微分:机器怎么求导

06-实践历史与应用 进阶 约 25 分钟 #数值微分#自动微分#前向模式#反向模式 更新 2026-10-02
当前状态:未学
本文基于模型知识整理(生成时未联网核对),AD 原理建议对照 Griewank & Walther《Evaluating Derivatives》复核。

一句话定义

机器求导有三条路线:数值微分(差商近似 $\frac{f(x+h)-f(x)}h$——简单但精度灾难:步长太小被浮点噪声淹没、太大被截断误差污染);符号微分(解析表达式求导——精确但表达式爆炸);自动微分(AD)——把程序分解为基本运算并按链式法则精确传播导数(无截断误差、无表达式爆炸),前向模式与反向模式分别适配"多输入单输出"(J列)与"单输入多输出"(Jᵀ行),后者就是反向传播。

为什么重要

深度学习之所以可训练,靠的是反向模式 AD 以"两次前向的成本"拿到百万维梯度;科学计算的敏感性分析靠前向模式。同时数值微分的精度陷阱(kp-023 的姊妹篇)是调试与验证 AD 实现(梯度检查)的必备常识——这是"微积分×计算机"交叉点的核心工程知识。

前置知识

kp-006(导数定义)、kp-008(截断误差)、kp-022/024(链式)。

核心概念

  • 数值微分(有限差分):

- 前向:$\frac{f(x+h)-f(x)}h$,误差 O(h)(截断)+ O(ε/h)(浮点舍入放大)→ 总误差最优在 $h\approx\sqrt\varepsilon$,精度只剩半机器精度(~1e-8); - 中心:$\frac{f(x+h)-f(x-h)}{2h}$,截断 O(h²)、总误差最优 $h\approx\varepsilon^{1/3}$(~1e-5 级仍有限); - 两难本质:h→0 时截断↓但 $\frac{f(x+h)-f(x)}h$ 是"相近数相减",舍入误差被除以 h 放大——泰勒截断与浮点噪声的拔河(kp-023 同源病)。

  • 符号微分:对表达式树做求导法则(kp-007)——无近似,但中间表达式指数膨胀(链式套链式的积化和)。
  • 自动微分(AD):程序→基本运算序列(每个节点只有 +×/sin 等已知导数)→ 链式法则沿图传播。精确到机器精度、无表达式膨胀(只存中间数值)。

- 前向模式:随计算同时传播 $\dot w=\frac{\partial w}{\partial x}$——一次扫描得 f 对一个输入的导数;对偶数 $x+\varepsilon\dot x$ 携带导数平行运算(代价:n 输入要 n 遍)。 - 反向模式:前向算完值后,反序传播伴随量 $\bar w=\frac{\partial f}{\partial w}$——一次扫描得 f 对所有输入的梯度(链式法则的矩阵化,kp-024 的网络版);代价:需存前向中间值(内存换导数)。

  • 梯度检查:用中心差分(数值)抽查 AD 梯度的正确性——两者都对的实现才敢上线(kp-033 调试清单的主力工具)。

原理与机制

为什么中心差分是最优 h 处也只有半精度:总误差 $E(h)=\frac{M_2h}6+\frac{2\varepsilon|f|}h$(截断↓ vs 舍入↑)——对 h 求最小得 $h^*\propto\varepsilon^{1/3}$,$E_{\min}\propto\varepsilon^{2/3}$;double 的 ε≈1e-16 → 精度上限 ~1e-11。差商的天花板是数学结构性的,不是实现不努力——这是 AD 存在的理由。

反向模式为什么便宜:一次函数 $f$ 对 n 个输入的梯度 = Jacobian $J$ 的一行(1×n)。反向模式一次传播给出"1 个输出对全部输入"($J^\top$ 的列操作),成本 O(1) 倍前向;前向模式给"1 个输入对所有输出"(J 的列)。输出少输入多(损失 vs 百万参数)→ 反向模式赢麻——这正是神经网络 L:参数→损失 的形状,BP=AD 反向模式(kp-031)。

AD 为什么精确:它不近似 f——它计算的导数是"该程序所定义的函数"的精确导数(到舍入误差);与符号微分的区别只在"对数值而非表达式操作"。

图示

数值微分: f′ ≈ [f(x+h)−f(x)]/h
  误差 = 截断O(h) + 舍入O(ε/h)  → h* ≈ √ε, 上限~√ε精度
  中心差分: O(h²)+O(ε/h) → h*≈ε^{1/3}
AD 前向: (v, v̇) 平行传播 → J 的列 (输入少)
AD 反向: 前向存值, 反向传伴随 v̄=∂f/∂w → Jᵀ行 (输出少=ML)
梯度检查: 中心差分抽查 AD — 两者一致性 = 实现正确性证据

直观类比

数值微分像"用秒表测瞬时速度":秒表不够快(h 太小计时误差相对放大)、太慢又测不准瞬时(截断)——永远差口气。自动微分像"赛车自带遥测":每次踩油门的导数被传感器精确记录——不测近邻差值,直接读取仪表背后的因果链。

实例或案例

  • PyTorch/TensorFlow/JAX:全部基于反向模式 AD;backward() 一行得到百万维梯度(kp-031 的引擎)。
  • JAX 的前向模式(jacfwd/jacrev):按输入输出维度比例自动选模式——理论直接工程化。
  • 梯度检查代码:np.allclose(grad_ad, grad_central_diff)——每个自研层的必做验收(kp-033 清单)。

常见误区

  • 误区一:"h 取越小越准"。舍入放大项反转结论(1e-10 时误差反升);h 有最优值且与 ε^指数相关——"取 h=1e-10 显得严谨"恰是错误。
  • 误区二:"AD=数值微分的高级版"。AD 无截断误差(精确链式),与有限差分是完全不同的物种;混淆会导致"梯度检查容差"设错(数值法只有 1e-6 级可信度)。
  • 误区三:"反向模式内存无忧"。存前向中间值是大模型的显存大头——梯度检查点(重算换内存)是标准对策(kp-031 的工程面)。

与其他知识点的关系

  • kp-006/008/023:差商、余项、浮点的三角。
  • kp-024/031:链式法则网络化=BP。
  • kp-017:数值积分的姊妹篇(同属"机器算微积分")。

自测题

  1. 前向差分取 h=1e-20 会发生什么?

答:f(x+h) 与 f(x) 在浮点下可能相等,差商=0 或完全噪声——舍入项 ÷h 爆炸;精度远劣于 h≈√ε。

  1. 为什么神经网络用反向模式而非前向?

答:损失是"百万输入→1 输出"——反向模式一次传播得全部梯度(成本与 n 无关);前向要跑百万遍。

  1. 梯度检查应容差设多少、用什么差分?

答:中心差分 + 相对误差容差 ~1e-6(受数值微分精度上限约束)——设 1e-10 会把正确的 AD 误判为错。

延伸阅读

  • Griewank & Walther《Evaluating Derivatives》(AD 圣经)。
  • Baydin 等, "Automatic Differentiation in Machine Learning: a Survey"(JMLR 2018)。
  • Karpathy 的 micrograd 视频(100 行 Python 手写反向 AD——本条的最佳实习)。