2.4 数值方法与训练检查
核心问题: 数学公式正确时,计算为什么仍可能失败?
在线 Notebook
对应的交互式版本可在 Google Colab 打开,统一使用方式见 第0章说明。
浮点数不是实数
计算机用有限位表示数值,因此会出现舍入、上溢和下溢。两个常见例子是:
- 很大的数与很小的数相加,小数可能被舍弃;
- 直接计算
或 ,可能产生 inf或-inf。
Softmax 应使用减去最大值的稳定形式:
这不会改变结果,因为分子和分母乘了相同常数,但能降低指数上溢风险。
条件数
条件数描述输入小变化可能被问题本身放大的程度。对可逆矩阵
条件数大时,即使算法实现正确,测量噪声或舍入误差也可能导致解明显变化。特征缩放、正则化和重新参数化可改善部分问题,但不能消除数据本身的不可辨识性。
数值梯度检查
中心差分近似为:
它可用于检查反向传播实现,但不适合训练:每个参数都要重复前向计算,而且
比较解析梯度
梯度检查应关闭 dropout 等随机操作,并使用较高精度和小规模输入。
深层网络中的数值问题
链式法则会连续相乘 Jacobian。其尺度长期小于或大于 1 时,可能出现梯度消失或爆炸。常见控制手段包括:
- 合理初始化和输入标准化;
- 残差连接与归一化;
- 梯度范数监控和裁剪;
- 稳定的损失实现;
- 混合精度下的损失缩放或更合适的数据类型。
不同硬件对 FP16、BF16 和 FP32 的支持不同。混合精度的速度、显存和误差收益需要实际测量,不能固定写成某个倍数。
排查顺序
| 现象 | 首先检查 |
|---|---|
| 损失为 NaN/Inf | 首个非有限张量、学习率、除零、指数与对数 |
| 损失不下降 | 数据与标签、梯度是否存在、参数是否更新 |
| 梯度很大 | 损失尺度、异常样本、归一化与梯度范数 |
| 结果不可复现 | 随机种子、数据顺序、非确定算子和依赖版本 |
应定位“第一个出现异常的步骤”,而不是在训练结束后只看最终损失。
关联实验
bash
python code/ch02_optimization/lms_vs_adam.py
python code/ch02_optimization/linear_logistic_regression.py改变学习率或输入尺度,观察损失是否发散,并打印梯度范数与参数范围。实验结论只适用于当前精度、硬件和实现。
本节小结
- 浮点误差、问题条件数和算法实现是三个不同的误差来源。
- 稳定 Softmax、梯度检查和非有限值监控能提前暴露实现问题。
- 混合精度与梯度裁剪需要通过指标和日志验证,不能作为固定保证。
下一节: 2.5 线性回归与逻辑回归
