beta=0.999 与 eval 权重
训练时对参数做指数滑动平均,验证和部署常用 EMA 权重——曲线更顺,有时泛化更好,但要与 optimizer 步和 checkpoint 策略一致。

1. val 曲线抖,deploy 用哪套权重
训练时 val metric 上下抖,选 best checkpoint 像抽奖——尤其小 val 集、检测 mAP 多阈值平均时。EMA(指数滑动平均)对参数做平滑,验证曲线常更顺,有时泛化更好。检测与分割任务我几乎默认开 EMA;部署和 eval 应用 EMA 权重,不是 training 权重。若 checkpoint 只存 training 权重而 deploy 误用,会出现「val 很好、线上很差」的割裂。
EMA 不替代 regularization——它平滑参数轨迹,不改变 loss landscape。与 SWA、Mean Teacher 不同 technique,别混用概念。run config 须写明 eval/deploy 用 EMA 还是 training weights。EMA 有效窗口约 步: 约 1000 step 量级, 约 10000 step——数据集很小、每 epoch 仅数十 step 时,过大 beta 会让 EMA 几乎不动,val 与 training 权重无差别。
2. EMA 更新机制
每 optimizer step 后 update,不是每 epoch。grad accumulation 时应在 accumulation 结束、optimizer.step() 之后 update 一次 EMA,与 effective step 对齐:
@torch.no_grad()
def update_ema(ema, model, beta=0.999):
for p_ema, p in zip(ema.parameters(), model.parameters()):
p_ema.data.mul_(beta).add_(p.data, alpha=1 - beta)beta=0.999 常见——effective window 约 step,千步量级。Eval 用 ema_model.eval();checkpoint 建议同时存 model 与 ema_model state_dict,deploy 导出 EMA。resume 时 EMA 状态必须 restore,否则平滑历史丢失,val 曲线 discontinuity。
实现上 ema_model 多为 deepcopy(model) 且 requires_grad=False,只参与 forward 做 val,不参与 backward。optimizer 若含 weight decay,EMA 跟踪 post-step 的 即可。多 param group 时 EMA 仍对所有参数同一 beta——若希望 head 更快进入 EMA,可对 head 单独更高 ,多数场景统一 beta 足够。单元测试应断言:optimizer.step() 后 update_ema() 被调用一次,accumulation 中间 step 不 update。
3. EMA vs SWA vs Mean Teacher
SWA 在 late training 对多个 checkpoint 均匀平均,与 EMA 每 step 指数滑动不同。可组合:EMA 全程 + 最后 10% epoch SWA。Mean Teacher 的 teacher 是 EMA of student,用途是产 pseudo label;eval 用 teacher 还是 student 协议要写清——半监督常 eval teacher,监督检测常 eval EMA copy of student。
BN 层:EMA 模型若 deepcopy 整网,BN running stats 在 update_ema 时通常 不 滑动平均,仍跟 training forward 更新;eval EMA 时 BN stats 来自 training 轨迹,部分框架单独维护 EMA BN stats,须读实现文档。Detectron2、MMDetection 等封装里 ModelEMA 行为略有差异——有的同步 BN buffer,有的不 sync。混用时 val EMA 与 deploy EMA 必须同一套实现。SWA 需额外存储多个 checkpoint 或在 late phase 低 LR 训,与 EMA 并行时以 deploy 协议Pick 其一,避免 export 混用 SWA 权重与 EMA BN stats。
4. beta 与 warmup
beta 越大平滑越强、对 recent 权重越不敏感。极小 dataset 或极大 LR 时 0.999 可能 lag,可试 0.99 或 step-based ramp(前几 epoch beta 从 0.9 到 0.999)。EMA 与 LR warmup 正交——warmup 阶段 EMA 仍应 update,否则 early 权重未进入 EMA。
检测 mAP 对 score 阈值敏感,EMA 平滑有时 略降 training best 峰值但升 median val——选 checkpoint 应用 EMA 曲线上的 best,而非 training 曲线。分割 dice 曲线同理:汇报时应注明 eval_weights=ema|train,避免复现时选错曲线。
step-based ramp 示例:前 500 step 用 ,之后切 0.999——避免 initial random 权重长期污染 EMA。fine-tune 初期若 backbone 冻结、只训 head,EMA 对全网 update 仍合理;解冻 backbone 时可重置 EMA 或提高 让新阶段快速进入平滑。eval 频率高的小 val 集,EMA 曲线平滑后 early stopping 更稳,减少「training best 过拟合一步、EMA best 泛化更好」的分歧。
5. 案例:deploy 误用 training 权重掉三 pt
某检测模型,val mAP training best 0.71、EMA 0.73,导出 ONNX 误用 training weights,线上 A/B 0.68。根因 export 脚本只序列化 model.state_dict()。fix 后 export ema_model,线上与 val 对齐。说明 EMA 不仅是训练技巧,是 deploy 契约。
修复清单:export 脚本加 --use-ema 默认 true;CI 对 export 产物跑 val 子集 parity(fp32/onnx mAP 与训练 log 中 EMA val 差 <0.5pt);文档写明线上版本号对应 EMA 还是 training。A/B 回退时若只回滚代码未回滚 export 权重类型,会出现「代码旧、权重新」的 ghost 回归——发布物应捆绑 {code_hash, ema|train, checkpoint_step}。
6. 验收
- 同 run EMA vs non-EMA val——EMA 更平滑,metric 常略好或 parity。
- 每 optimizer step(含 grad accumulation 边界)后 update_ema 被调用。
- Deploy 导出 EMA,target 硬件 acc/latency 与 val 一致。
- resume 前后 EMA val 连续。
- checkpoint 含 ema state;export 脚本单元测试覆盖 EMA 分支。
额外建议:在 checkpoint 元数据写入 ema_beta 与 last_ema_step,resume 时校验一致。多阶段训练(先 freeze 再 unfreeze)若重置 EMA,须在 run card 标注 reset 时刻,否则历史实验 val 曲线不可比。
EMA 的 beta=0.999 与每 step update 是基本契约。改 beta 或 update 频率时固定其余配置,才分得清平滑收益还是 eval 协议错误。训练框架若支持 EMA decay 与 step 挂钩,文档须写清 global step 还是 epoch 内 step,resume 后 step 计数重置会导致 EMA 行为突变。半监督 Mean Teacher 与监督 EMA 共用公式但 eval 对象不同——复制代码时勿把 teacher eval 逻辑误用到纯监督 deploy。
相关
也可以看看
- ·3 分钟阅读
grad_norm spike 与 misclass grid
只看 train loss 不够——要 log lr、grad norm、val slice、GPU 利用率和样例可视化,异常通常是 loss 曲线先以外的信号。
- ·5 分钟阅读
use_reentrant=False 粒度
Gradient checkpointing 用重算 forward 换显存——训练大模型或高分辨率输入时 OOM 的常用解法,wall-clock 涨 20–40% 要算进预算。
- ·3 分钟阅读
梯度裁剪:爆炸刹车
clip_grad_norm 能止住 NaN 连锁,但根因常是 LR 过大、loss scale 或 bad batch——裁剪是买时间,不是根治。
johan's blog