这是我在阅读《深度学习入门—基于Python的理论与实现》(作者斋藤康毅)时遇到的一个问题,以下是AI总结的要点。
目录
问题的由来:为什么书中用中心差分而不是前向差分
标准偏导数方法(解析法)
数值近似:前向差分 vs 中心差分(以及后向差分补充)
泰勒展开的完整公式(单变量与多变量局部展开)
用泰勒展开说明中心差分更高精度及其其他优势
代码示例:误差对比
总结速查表
1. 问题的由来:作者为何使用中心差分?
在书中,numerical_gradient(f, x) 用的是中心差分法:
$$\frac{f(x+h)-f(x-h)}{2h}$$
而不是前向差分法:
$$\frac{f(x+h)-f(x)}{h}$$
作者的“有意”选择,核心原因:
| 维度 | 前向差分 | 中心差分 | 书中选择中心差分的理由 |
|---|---|---|---|
| 截断误差阶 | \(O(h)\) | \(O(h^2)\) | 更高精度,减少系统性偏差 |
| 公式对称性 | 单边取样 | 左右对称 | 抵消奇数阶误差项,提高稳定性 |
| 梯度检查可靠性 | 偏差大 | 偏差小 | 用于验证反向传播实现更放心 |
| 代码复杂度 | 较低 | 略高(多一次函数调用) | 成本可接受,收益明显 |
| 教学目的 | 仅演示概念 | 体现更“正确”的数值估计 | 让读者看到接近真实梯度的效果 |
书中此处的目标并不是“最快速度”或“用于真正训练”,而是帮助读者感性认识梯度并做数值验证。在这种语境下,中心差分的高精度与对称性更符合教学诉求。
2. 标准偏导数方法(解析法)
对于多元函数:
$$f: \mathbb{R}^n \to \mathbb{R}, \quad f(x_1, x_2, \dots, x_n)$$
对第i个变量的偏导数定义为:
$$\begin{eqnarray} \frac{\partial f}{\partial x_i}=\lim_{h\to 0} \frac{f(x_1,\dots,x_i+h,\dots,x_n)-f(x_1,\dots,x_i,\dots,x_n)}{h} \end{eqnarray}$$
梯度(gradient)是全部偏导数组成的向量:
$$\nabla f(x) = \left( \frac{\partial f}{\partial x_1}, \frac{\partial f}{\partial x_2}, \dots, \frac{\partial f}{\partial x_n} \right)$$
解析求导优点:
精确无近似误差(假设函数可微且可符号化)
计算快速,适合集成到训练过程(反向传播本质即链式法则的系统化应用)
解析法的局限:
需要函数可写出明确公式
对高度复杂组合函数(深度网络的整体表达)人工推导繁琐
不适用于“黑盒”函数(只能评价函数值而无内部结构)
3. 数值近似:前向差分 vs 中心差分(补充后向差分)
3.1 前向差分(Forward Difference)
单变量: \( f’(x) \approx \frac{f(x+h)-f(x)}{h} \)
多变量(对 \(x_i\)): \(\frac{\partial f}{\partial x_i} \approx \frac{f(x_1,\dots,x_i+h,\dots,x_n)-f(x_1,\dots,x_i,\dots,x_n)}{h}\)
3.2 后向差分(Backward Difference)
\(f’(x) \approx \frac{f(x)-f(x-h)}{h}\)
3.3 中心差分(Central Difference)
单变量: \( f’(x) \approx \frac{f(x+h)-f(x-h)}{2h}\)
多变量对 \(x_i\): \(\frac{\partial f}{\partial x_i}(x) \approx \frac{f(\dots,x_i+h,\dots)-f(\dots,x_i-h,\dots)}{2h}\)
3.4 截断误差阶次
| 方法 | 误差主阶 | 精度等级 |
|---|---|---|
| 前向差分 | \(O(h)\) | 一阶 |
| 后向差分 | \(O(h)\) | 一阶 |
| 中心差分 | \(O(h^2)\) | 二阶(更准) |
4. 泰勒展开的完整公式
4.1 单变量泰勒展开(在 \(x\) 附近)
$$f(x+h)=f(x)+h f’(x)+\frac{h^2}{2} f’’(x)+\frac{h^3}{6} f^{(3)}(x)+\frac{h^4}{24} f^{(4)}(x)+O(h^5) $$
$$f(x-h)=f(x)-h f’(x)+\frac{h^2}{2} f’’(x)-\frac{h^3}{6} f^{(3)}(x)+\frac{h^4}{24} f^{(4)}(x)+O(h^5)$$
4.2 单变量导出的差分近似
前向差分:
$$\frac{f(x+h)-f(x)}{h} = f’(x)+\frac{h}{2}f’’(x)+\frac{h^2}{6}f^{(3)}(x)+O(h^3)$$
中心差分:
$$\frac{f(x+h)-f(x-h)}{2h} = f’(x)+\frac{h^2}{6}f^{(3)}(x)+\frac{h^4}{120}f^{(5)}(x)+O(h^6)$$
4.3 二元函数一阶近似(只动一个变量)
对 \(f(x,y)\) 在 \((x_0, y_0)\) ,仅改变 \(x\):
$$f(x_0+h,y_0)=f(x_0,y_0)+h\frac{\partial f}{\partial x}+\frac{h^2}{2}\frac{\partial^2 f}{\partial x^2}+O(h^3)$$
同理得到 \(f(x_0-h,y_0)\) ,然后构造中心差分。
5. 为什么中心差分更高精度及其优势
5.1 误差阶次更低
从展开式可见:
前向差分主误差项: \(\frac{h}{2}f’’(x)\) → 误差随 \(h\) 线性缩小
中心差分主误差项: \(\frac{h^2}{6}f^{(3)}(x)\) → 误差随 \(h^2\) 缩小(更快)
5.2 奇数阶项抵消
把 \(f(x+h)\) 与 \(f(x-h)\) 相减时, \(h f’(x)\) 保留而 \(h^3 f^{(3)}(x)\) 等奇数阶对称项出现系数变化(更高阶),导致一阶误差项消失 → 提升精度。
5.3 减少系统性偏差
前向差分“只看右侧”会带来方向性偏差;中心差分对称采样更像“居中估计”,在统计上更稳定。
5.4 梯度检查更可靠
用于验证反向传播实现时,需要一个足够准确的“参考梯度”——否则你无法区分实现错误 vs 数值误差。中心差分是实践中的首选。
5.5 与步长选择的协同
由于截断误差更低,可以用稍微“更大一点的 h”维持精度,同时避免浮点减法灾难( \(f(x+h)-f(x)\) 当 \(h\) 太小可能产生严重舍入误差)。
5.6 局限与注意事项
成本略高(每维需要两次函数扰动)
对高噪声函数(数值震荡)时,双端采样可能放大噪声 → 需平衡 h
不适用于函数不平滑或含大量非连续点(此时任何差分都会失真)
6. 代码示例:误差对比
下面用函数 \(f(x)=\sin(x)\) 在某点比较三种差分的误差;再做一个多变量例子。
1 | import numpy as np |
可能输出(示例):
1 | h=1e-01 | forward_err=1.30e-03 | central_err=1.08e-05 | backward_err=1.30e-03 |
你可以看到中心差分误差随 h 的衰减显著更快。
多变量例子 ( \(f(x,y)=x^2+y^2\) 梯度解析为 \((2x,2y)\)):
1 | def f2(v): |
结语
作者选用中心差分,不是因为不知道“标准偏导定义”,而是在教学场景下刻意选择一个更高精度、对称、易理解、便于梯度检查的数值近似方法。理解了偏导的解析本质与数值近似的误差来源,你就能清晰区分“理论梯度”和“数值梯度”的角色——前者用于训练,后者用于验证与直觉建立。