上溢、下溢与数值稳定技巧
层级:A|建议先修:03-12、09-01
概率模型常把很多小概率相乘,神经网络常计算很大的指数。直接照抄数学公式,可能得到 0、无穷或 NaN。数值稳定的核心是改写成数学等价、计算范围更安全的形式。
1. 上溢与下溢
- 上溢:结果绝对值超过浮点格式最大有限值,常变成 ;
- 下溢:结果绝对值过小,逐渐进入次正规区或变成 0。
例如 在常用格式中上溢;连续相乘几百个小于 1 的概率可能下溢为 0。
2. 在对数域计算乘积
若
则
对数把极小乘积变成中等大小的负数之和。极大似然训练通常最大化 log-likelihood,而不是直接最大化 likelihood。
比较两个正数乘积大小时,只比较它们的对数即可,无需再指数还原。
3. log-sum-exp
要计算
令 ,则
由于所有 ,指数项不超过 1,避免上溢;至少一个指数项为 1,也降低全部下溢为 0 的风险。
4. 稳定 Softmax
Softmax 为
对所有 logits 减去同一常数不改变结果:
通常取 。若需要 log-softmax,直接计算
比先求 再取对数稳定。
5. 稳定 sigmoid 与 softplus
Sigmoid
在 时 可能上溢。可分支计算:
Softplus 可稳定写成
6. 二元交叉熵直接用 logits
令标签 、logit 为 。与 sigmoid 后二元交叉熵等价的稳定形式为
这避免了先得到精确 0 或 1 的概率再取对数。工程中应使用 binary_cross_entropy_with_logits 一类融合接口。
7. log1p 与 expm1
当 很小时:
log(1+x)中的 可能先舍入成 1;使用log1p(x);exp(x)-1中两个接近 1 的数相减会消去;使用expm1(x)。
这些库函数用专门近似保持小量精度。
8. 概率归一化
若只有对数权重 ,归一化对数概率为
只有最终确实需要普通概率时才指数化。这适用于 HMM、Bayesian 推断、混合模型和采样权重。
9. 避免除以极小数
分母接近 0 会放大误差。常见方法:
- 对范数、方差分母加入与尺度匹配的 ;
- 对概率做合理裁剪后再取对数;
- 使用正则化改善线性系统;
- 重新参数化保证正数,如用 softplus 表示方差。
加入 会改变数学问题,必须说明其量级和影响,不能作为掩盖错误的万能补丁。
10. 归一化与缩放
输入特征尺度差异过大,会造成梯度和线性系统条件恶化。标准化、中心化、白化和合理参数初始化可让数值落在更安全的范围。
混合精度训练常用 loss scaling:反向前放大损失和梯度,避免低精度梯度下溢;更新前再除回尺度,并检测无穷值动态调整。
11. 检测异常值
训练循环应尽早检测:
- 输入、参数、激活、损失和梯度是否有限;
- 第一次出现 NaN/Inf 的层和操作;
- 梯度范数、激活范围和学习率;
- 数据中是否存在非法值或除零。
NaN 会沿计算图迅速传播,定位“第一次出现”比只看最终损失更有效。
12. 梯度裁剪
梯度范数裁剪将 缩放为
它可缓解爆炸梯度,却不能修复错误模型、过大学习率或持续数值不稳定。裁剪阈值应被记录和验证。
13. 易错点
- Softmax 前减最大值不会改变精确数学结果。
- 给所有概率无脑加固定 epsilon 会破坏归一化和概率语义。
log(softmax(z))应由log_softmax(z)替代。- NaN 不总是上溢造成,也可能来自无效运算、数据缺失或梯度爆炸。
常见问答
Q1:概率已经下溢为 0,再取对数能恢复吗?
不能。必须从一开始就在对数域计算,避免信息先丢失。
Q2:为什么减去最大 logit 后 Softmax 不变?
分子分母都乘以同一个 ,比例保持不变。
Q3:概率裁剪会不会让梯度有偏?
会改变原目标,尤其在边界附近。优先使用稳定 logits 公式;裁剪应作为有意识的近似。
Q4:用了 float64 就不需要稳定公式了吗?
仍需要。float64 范围更大、精度更高,但指数和长概率乘积仍可能溢出或下溢。
练习
- 稳定计算 。
- 证明 Softmax 对所有 logits 加同一常数保持不变。
- 为什么小 时应使用
log1p(x)? - 写出 log 权重 归一化为 log 概率的公式。
答案与提示
- 。
- 每项指数都乘 ,在分子分母中相消。
- 普通计算会先形成 ,小量 可能在舍入中消失;专用函数直接保留小量信息。
- 。