返回专辑
·Johan·5 分钟阅读

beta=0.999 与 eval 权重

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

beta=0.999 与 eval 权重

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 对齐:

python
@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 建议同时存 modelema_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_betalast_ema_step,resume 时校验一致。多阶段训练(先 freeze 再 unfreeze)若重置 EMA,须在 run card 标注 reset 时刻,否则历史实验 val 曲线不可比。

EMA 的 beta=0.999 与每 step update 是基本契约。改 beta 或 update 频率时固定其余配置,才分得清平滑收益还是 eval 协议错误。训练框架若支持 EMA decaystep 挂钩,文档须写清 global step 还是 epoch 内 step,resume 后 step 计数重置会导致 EMA 行为突变。半监督 Mean Teacher 与监督 EMA 共用公式但 eval 对象不同——复制代码时勿把 teacher eval 逻辑误用到纯监督 deploy。

← 全部文章

johan's blog