M3-007M3: Deep Learning FoundationsBackprop & AutodiffMedium
Mastery:

Backprop & Autodiff: 解释梯度检验(gradient checking)的原理与实现细节。

📐 Mathematical Definition
∂L∂θi≈L(θ+ϵei)−L(θ−ϵei)2ϵ\frac{\partial L}{\partial\theta_i}\approx\frac{L(\theta+\epsilon e_i)-L(\theta-\epsilon e_i)}{2\epsilon}
⚡ Executive Summary
Core Concept: 用有限差分近似数值梯度,与解析梯度比对;关键是中心差分、相对误差判据与 double 精度。

📌 Key Takeaways

  • •
    必须用中心差分(误差 O(ε²))而非前向差分(O(ε))
  • •
    相对误差判据:|a−n|/max(1,|a|,|n|) < 1e-5 量级
  • •
    必须在 double 精度、且关闭 dropout/BN 更新等随机性

📐 Mathematical Derivations

数学机理:由泰勒展开 L(θ+εe_i)=L(θ)+εL'+(ε²/2)L''+O(ε³),两式相减得 L(θ+ε)−L(θ−ε)=2εL'+O(ε³),故中心差分 (L(θ+ε)−L(θ−ε))/(2ε) 的误差为 O(ε²)——比前向差分的 O(ε) 高<strong>一阶</strong>精度。但<strong>数值下界</strong>由浮点舍入决定:计算两相近数之差会损失有效位,误差量级约 η/ε(η 为机器精度,FP64 约 2.2e-16),故总误差 ≈ (ε²/6)|L'''| + 2η/ε。两者平衡给出<strong>最优步长</strong> ε*≈(3η)^{1/3}≈1e-5(FP64 下),此时总误差约 1e-10。因此实践用 ε=1e-4~1e-6;<strong>太小</strong>(如 1e-12)会被舍入噪声淹没、数值梯度全是噪声;<strong>太大</strong>(如 1e-1)截断误差主导。判据用<strong>相对误差</strong>:rel=|g_analytic−g_numeric|/max(1,|g_a|,|g_n|),<1e-7 完美、<1e-5 可接受、>1e-3 几乎一定有 bug。

🏭 Production Trade-offs

深度剖析与工程权衡:① <strong>kink 问题</strong>——ReLU/max/排序等分段线性算子在折点处不可导,中心差分跨越折点时会得到两侧斜率的平均,与任一侧的解析次梯度都不等,造成假阳性失败;对策是避开折点或接受该处的偏差。② <strong>随机性必须冻结</strong>——dropout、BN 的 batch 统计、数据增强都会让两次前向的损失不同,使数值梯度无意义;标准做法是 model.eval() + 固定随机种子 + 关闭 BN 更新,或用同一 batch 的确定性路径。③ <strong>成本</strong>——数值梯度需对<strong>每个参数</strong>做两次前向,参数为 N 则成本 2N 次前向,对大模型完全不可行;故梯度检验只用于<strong>小规模单元测试</strong>(如自实现一个算子后验证其 backward)。④ <strong>FP32 不够</strong>——FP32 机器精度约 1e-7,最优误差降到约 1e-5 量级,常与真实 bug 的误差重叠;故梯度检验一律用 <strong>double</strong>。⑤ <strong>与 autograd 的关系</strong>——PyTorch 的 torch.autograd.gradcheck 即实现此逻辑,内部用 double + 中心差分,是写自定义 Function 后的标准验证手段。⑥ <strong>工程习惯</strong>——把梯度检验写进自定义算子的单元测试(CI 中跑),是避免'反向传播静默错误'(前向正确但梯度错,训练照跑但学不好)的最有效防线。
⚠️ Common Interview Pitfalls
  • ✕
    用前向差分做检验(精度低一阶,易把正常误差误判为 bug)
  • ✕
    在 FP32 或带 dropout 的情况下做检验(噪声淹没信号)
🎯 Interviewer Follow-ups
  • ?
    ε 取多大合适?为什么不能太小?
  • ?
    为什么 ReLU 网络的梯度检验在 kink 附近会失败?
📚

Associated Knowledge Base Guides & Mindmaps

Explore the comprehensive technical article, exam cards, and global architecture tree.

← PreviousM3-006: Backprop & Autodiff: 什么是可微编程?它改变了哪些系统设计?📋Back to BankNext →M3-008: Weight Initialization: 为什么不能全零初始化?