记录一下那天晚上的排查过程。显存只够跑 batch size 1,于是把梯度累积设成 16,训练稳定性却明显不如别人 batch size 16 的结果。
刚开始盯着「随机性来源不同,样本顺序影响梯度方向」,折腾了半个多小时,排掉了。
把日志和配置对完,能解释这个现象的基本就这几处。批归一化类层对真实批大小敏感。也可能是累积时损失没有按步数归一化,等效学习率偏移。
还有一种情况,梯度裁剪在累积过程中被提前执行。
先确认模型是否含批相关层
python -c "print([n for n,_ in model.named_modules() if 'Norm' in type(_).__name__])"
损失除以累积步数保持尺度一致
loss = loss / accum_steps
梯度累积期间不要提前裁剪
if (step + 1) % accum_steps == 0: clip_grad_norm_(model.parameters(), 1.0)
适当调大学习率补偿小批次的噪声
python train.py --learning_rate 3e-4 --grad_accum 16
改完先别撤,确认这几项。训练曲线与大批次实验接近,loss 波动收窄,验证指标差距缩小到可接受范围。
数学上梯度是等价的,但优化器状态更新频率和随机性并不相同,小批次加累积不能完全替代真实大批次。监控比日志更早给出信号,事后回看经常能提前半小时发现异常。