混合精度训练通过以下机制解决 FP16 的问题:
FP16 权重 → 计算梯度 → 转成 FP32 → 更新 FP32 权重FP32 权重
↓
复制到 FP16
↓
前向传播 (FP16)
↓
计算 Loss
↓
Loss × scale
↓
反向传播 (FP16)
↓
梯度 / scale
↓
更新 FP32 权重torch.cuda.amp(推荐)import torch
from torch.cuda.amp import autocast, GradScaler
model = model.cuda()
optimizer = torch.optim.Adam(model.parameters())
scaler = GradScaler()
for x, y in dataloader:
x, y = x.cuda(), y.cuda()
optimizer.zero_grad()
with autocast(): # 自动混合精度
y_pred = model(x)
loss = criterion(y_pred, y)
scaler.scale(loss).backward() # loss scaling
scaler.step(optimizer)
scaler.update()✅ 关键点
autocast():自动决定哪些操作用 FP16GradScaler:自动管理 loss scalingwith autocast():
outputs = model(inputs)
loss = loss_fn(outputs, targets)
scaler.scale(loss).backward()
scaler.unscale_(optimizer)
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
scaler.step(optimizer)
scaler.update()mixed_float16from tensorflow.keras.mixed_precision import set_global_policy
set_global_policy('mixed_float16')然后正常写模型即可:
model = tf.keras.Sequential([
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(10)
])
model.compile(
optimizer='adam',
loss='sparse_categorical_crossentropy'
)✅ TensorFlow 会自动:
✅ 适合
❌ 不适合
| 问题 | 解决方法 |
|---|---|
| loss 变成 nan | 调小 loss scale 或关闭 AMP |
| 精度下降 | 检查是否所有参数都参与 AMP |
| BN 不稳定 | 使用 torch.nn.SyncBatchNorm |
| 自定义算子不支持 FP16 | 强制用 FP32 |
混合精度训练 = FP16 计算 + FP32 主权重 + Loss Scaling
如果你愿意,我可以:
你现在是用的 PyTorch 还是 TensorFlow?