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

早停:盯验证集

Early stopping 防过拟合,但没有独立验证集或 val 泄漏时,早停只是在随机时刻停——split 诚实比 patience 数值更重要。

早停:盯验证集

1. 没有 honest val,早停是算命

train loss 还在降,val 从 epoch 30 起缓慢上升——classic 过拟合。Early stopping 在 val 最优时停训、存 checkpoint,比训满固定 epoch 更省算力也更泛化。但若 val 与 train 共享 scene、相邻帧泄漏,或 val 被用来调参后再当「独立 eval」,早停只是在随机时刻停,patience=5 还是 20 没本质区别。Split 诚实比 patience 数值更重要。

2. 标准实现

监控 val metric(loss 或 task metric),连续 patience 个 epoch 无改善则停;改善时存 best checkpoint,不是最后一轮

python
best_val = float('inf')
patience, counter = 10, 0
for epoch in range(max_epochs):
    train(...)
    val_loss = validate(...)
    if val_loss < best_val:
        best_val = val_loss
        counter = 0
        torch.save(model.state_dict(), 'best.pt')
    else:
        counter += 1
        if counter >= patience:
            break

min_delta 过滤噪声级改善;metric 方向(loss 越小越好 vs acc 越大越好)要一致。多 metric 时定 primary(如 val mAP),secondary 作 tie-break。

3. val 的角色:调参 vs 最终 eval

val 用于 early stopping 和 hyperparam 选择 → test set 必须留到最后只评一次。在 val 上试二十组超参再报告 val 最优,等于 test 泄漏。honest 流程:train/val split → val 上 early stop + 选超参 → 固定 config 在 test 上评一次。

K-fold 时 early stop 每 fold 独立,report mean ± std。时间序列数据按时间 split,不 random shuffle 跨时间泄漏。

4. patience 与 min_epochs

patience 太小 → 停太早,underfit。太大 → 浪费算力,过拟合已发生。常见 5–20 epoch,取决于 dataset 大小和 epoch 长度。设 min_epochs 避免 warmup 阶段误触发——前 10 epoch val 抖动不应停。

cosine schedule 常训满 budget、靠 checkpoint 选 best——early stop 与 schedule 配合:stop 时 LR 可能已很小,best checkpoint 常在 LR 较高阶段,需实验验证。

5. 与监控的衔接

early stopping 依赖 val metric 可信——见 dl-monitor-train 的 slice 监控。某 slice val 恶化但总 val 仍改善,early stop 可能选错 checkpoint。primary metric 选与业务对齐的 slice-weighted 或 aggregate,事先定规则。

6. 案例:泄漏 val 上的早停

某视频 数据 random 帧 split,早停选出的「最优」epoch 在 honest group split 上并非最优——场景泄漏让 val 虚假乐观。先 fix split 再谈 patience。

7. 验收

  • best checkpoint 按 val 最优存,非 last epoch。
  • train/val split 无 scene/frame 泄漏(见 dl-data-leakage)。
  • test 未参与 early stop 和超参选择。
  • patience/min_delta/min_epochs 有记录。
  • 停训后 load best.pt 做 final eval,不 load last。

8. 落地与衔接

训练脚本把 best checkpoint 路径、patience、min_delta、min_epochs 写进 config 与 run 元数据。early stop 只盯 honest val;test 集脚本权限只读,不参与超参搜索。时间序列与视频数据在 split 文档里写死 group key,与 dl-data-leakage 对齐。停训后自动 load best.pt 跑 final eval,last epoch 权重仅作 debug 存档。多 metric 时 primary 与 tie-break 规则发版前签字确认。团队不得用测试集曲线调耐心,否则早停失去意义。

9. 案例复盘

某视频项目 random 帧 split,早停选的 epoch 在 group split 上并非最优——相邻帧泄漏让 val 虚假乐观。改按 video_id split 后 early stop 与 pilot 对齐。复盘把 group split 列为开训前置条件,patience 调参排在 split 审计之后。团队不再在泄漏 val 上争论 patience 5 还是 20,因为 split 错了停哪一轮都是算命。该流程已写入训练启动清单,未审计切分不得开训。

10. 与监控、校准的衔接

早停选出的最佳轮次应作为后续温度缩放与阈值搜索的唯一起点,不要在最后一轮权重上校准。验证指标若按业务切片定义,早停的 primary metric 须与切片一致,否则总指标最优可能对关键场景不利。训练平台宜在 patience 触发时自动归档验证曲线与当前超参快照,便于复盘「若多训五轮会否更好」而不必重跑全量实验。

Early stopping 是 val 诚实性的试金石。Split 错了,patience 再精细也没用。存 best、test 一次、split 无泄漏——这三条比调 patience 优先。最佳权重文件名建议含验证分数与切分版本;训练平台应禁止测试集被早停或超参脚本读取。时间序列须按时间切分后再谈 patience,否则早停只是在泄漏验证上选轮次。耐心值与最少训练轮数应写入配置模板,避免 warmup 阶段误触发停训。发版说明须注明早停所依验证集是否与上线域一致。

← 全部文章

johan's blog