一句话定义:损失缩放(Loss Scaling)是AI 词典:混合精度训练">混合精度训练里的一个技巧——先把损失(loss)人为放大若干倍再反向传播,等算出梯度后再按同样倍数缩回去,避免很小的梯度在 FP16 下被"抹成 0"。
为什么需要它
FP16(16 位半精度浮点)能表示的数值范围很窄,比它最小正规数还小的一批数字会直接变成 0,这叫下溢(underflow)。而深度学习里很多梯度天然就很小,比如某个权重每步只需要改动百万分之一量级。这个数用 FP16 存,结果就是 0:参数根本没动,训练看起来在跑,其实原地踏步。
打个生活化的比方
你要往汤里放 0.001 克盐,可手里的勺子最小刻度是 1 克,怎么量都是 0。办法是:先假设整包盐放大 1000 倍,用勺子舀出 1 克,最后再把这 1 克按 1000:1 折算回去。放大只是为了让"小"变成"能被量出来",最后必须除回来,否则结果就错了。
具体怎么走一遍
1. 前向传播照常算,得到一个正常的 loss。
2. 反向传播之前,把 loss 乘上缩放系数 S(常见做法是取 2 的若干次方倍)。
3. 反向传播算出的每个梯度,都是真实值的 S 倍,正好落在 FP16 能表示的区间里。
4. 参数更新前,先把梯度整体除以 S 还原。这一步通常叫 unscale,必须发生在梯度裁剪、梯度累积之前。
5. 真正保存的权重仍然是 FP32(主权重),只把计算过程交给 FP16。
缩放系数 S 有两种玩法:静态设定,简单但怕遇到极端情况;动态调整更常用——连续若干步没有出现 inf/NaN 就把 S 调大一点,一旦溢出就调小并跳过这一步。loss 突然变成 NaN,很多时候就是系数涨得太猛。
别和邻居搞混
| 概念 | 解决什么问题 | 典型手段 |
|---|---|---|
| 损失缩放 | 小梯度在 FP16 下下溢为 0 | loss 乘 S,梯度除 S |
| 梯度裁剪 | 梯度爆炸、数值过大 | 按范数截断梯度 |
| 混合精度 | 用低精度换速度和显存 | 低精度计算 + FP32 主权重 |
损失缩放是混合精度这套大框架里的一小块补丁,不是它的同义词;它治的是"太小",梯度裁剪治的是"太大",方向正好相反。
对从业者意味着什么
开混合精度时,损失缩放基本是标配,通常由框架的自动混合精度(AMP)自动完成,一般不用手写。但你要知道它的存在:训练 loss 无端变 NaN、参数不更新、梯度全为 0,都要往缩放系数上想一层。相比之下,BF16(bfloat16)的指数位和 FP32 一样宽,动态范围大得多,通常不需要损失缩放,代价是尾数精度更低——选哪种精度、要不要手动配置,以官方文档为准。
对非技术的职场人,这背后是一条通用经验:当工具刻度不够细时,先把量放大到可测量的尺度再换算回去,比换一把更贵的尺子便宜得多。
