26.6.12更新(新增混合精度训练伪代码)
低精度的优点:
1)计算速度提升
2)显存占用变小
3)数据传输带宽占用小
低精度的缺点:
1)表示范围问题,表示不了太大太小的值
2)大数吃小数问题:将小数转换成和大数的进制一样的表达方式,但是由于过小,超出了大数的范围,所以溢出了
前向传播和损失计算
第一步,master weights(FP32) --weights(FP16)
主权重存储在FP32格式中
前向传播之前,会将FP32权重转换为FP16格式
第二步,weights(FP16)--loss(FP32)
使用FP16权重前向传播计算,得到预测值,计算得到LOSS,使用FP32进行存储,因为LOSS过小的话无法精确表示
存储高精度,前向传播低精度,loss高精度
损失缩放
第三步,Loss (FP32) → Scaled Loss (FP32)
通过人为放大loss,反向传播计算出的梯度会相应放大N倍,从而让梯度值落在FP16的安全范围内

loss缩放
反向传播和梯度处理
第四步,Scaled Loss (FP32) → Scaled Gradients (FP16)
梯度相应放大,但是还是在FP16可表示范围内
第五步,Scaled Gradients (FP16) → Scaled Gradients (FP32)
后续梯度更新要有高精度
梯度缩放,梯度精度还原
梯度还原和更新
第六步,Scaled Gradients (FP32) → Gradients (FP32)
将放大的梯度恢复正常
第七步,Gradients (FP32) → Master Weights (FP32)
用梯度更新主权重
梯度缩放还原,主权重更新
第八步,Master Weights (FP32) → weights(FP16)
进行下一次训练
这个过程巧妙地解决了:
速度和显存;精度和稳定性
在现代深度学习框架(如 PyTorch、PaddlePaddle)中,开启混合精度训练非常简单,通常只需要几行代码。以 PyTorch 为例,主要依靠 torch.cuda.amp 模块中的两个核心组件:
autocast:自动为你选择合适的精度。在这个上下文管理器里的运算,框架会自动判断哪些该用 FP16,哪些必须用 FP32。GradScaler:自动帮你完成上述的“损失缩放”操作,防止梯度下溢。
# 伪代码示例
# 0. 导入工具
from torch.cuda.amp import GradScaler, autocast
# 1. 初始化(训练开始前 1 次)
scaler = GradScaler()
# 2. 训练循环(每个 batch)
for data, label in dataloader:
optimizer.zero_grad() # 梯度清零
# 3. 前向传播 + 自动混合精度
with autocast():
output = model(data)
loss = criterion(output, label)
# 4. 反向传播:缩放 loss + 计算梯度
scaler.scale(loss).backward()
# ============= 可选(梯度裁剪)=============
# 如果要裁剪梯度,必须先反缩放!
scaler.unscale_(optimizer)
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
# ==========================================
# 5. 更新参数
scaler.step(optimizer)
# 6. 更新缩放因子
scaler.update()
参考视频:
1万+

被折叠的 条评论
为什么被折叠?



