freeze_bn 与 target 域 stats
小 batch 微调时 BatchNorm 统计量噪声大——freeze backbone BN、换 SyncBN 或 GroupNorm 往往比盲目加大 batch 更实际。

1. 小 batch 微调,BN stats 乱飘
八百张缺陷图 fine-tune ResNet,per-GPU batch=4——train loss 抖、val 不稳定。不是 LR 问题,是 BatchNorm 用 batch=4 的 mean/var 更新 running stats,噪声大且与 ImageNet pretrain 的 stats 分布差。盲目加大 batch 受显存限制;更实际的是 freeze BN 或换 normalization。
2. Freeze BN 的做法
微调时让 BN 层保持 eval 行为:用 running stats,不更新。只训 conv weight 和 linear,BN 的 可选冻或微调。
def freeze_bn(m):
if isinstance(m, (nn.BatchNorm1d, nn.BatchNorm2d, nn.BatchNorm3d)):
m.eval()
model.apply(freeze_bn)注意 model.train() 会重新打开 BN train mode——需在每 epoch 对 backbone BN 再 eval(),或 requires_grad=False 只冻 BN 参数。head 若新建 BN 层,可正常 train mode 更新 stats。
3. 替代方案
GroupNorm / LayerNorm 不依赖 batch 统计,batch=1 也稳定——新 head 或全网络替换 BN 成本高,但小 batch 长期训练可考虑。SyncBatchNorm 多卡聚合 batch 统计,等效更大 batch——需多卡且通信开销。重估 running stats:在 target 域 data 上 forward-only 跑一遍更新 running mean/var,再 freeze——domain 与 pretrain 差大时有效。
4. 何时 freeze,何时更新
数据少、batch 小、domain 与 pretrain 近 → freeze backbone BN 通常够。数据多、batch 大(≥32)、domain 差大 → 可在 target 域更新 BN 或 re-estimate stats。head 新建 BN 层应正常训练——没有 pretrain stats 可依赖。
与逐层解冻配合:先 freeze 全 backbone + 训 head;解冻 layer4 时仍 freeze 浅层 BN,只动深层。
5. 失败模式
小 batch 不 freeze → 训练不稳定、val 随机抖。freeze 后忘记 head BN 需要 train → head 欠拟合。eval 部署时用错了 train 时更新的 noisy stats——export 前在 target 域 calibrate running stats。
6. 案例:freeze 后 val 稳定
某 batch=4 微调 loss 曲线锯齿状——freeze backbone BN 后平滑,val 涨两个点。小 batch 微调默认应考虑 freeze,不是先加 batch。
7. 验收
- 小 batch 微调有 explicit BN 策略(freeze / GN / SyncBN)。
- train loop 里 backbone BN 保持 eval 行为(若 freeze)。
- target 域 val 稳定,loss 曲线无 batch-noise 式抖动。
- 与 blind 增大 LR 或 batch 的 baseline 对比有记录。
- export 前 running stats 来源明确(pretrain / re-estimate / trained)。
8. 落地与衔接
微调配置显式声明批归一化策略:冻结骨干、同步批归一化、组归一化或目标域重估四选一,写进实验元数据。训练循环若冻结,每轮对骨干批归一化再切评估模式,避免误开批次统计。新建分类头中的批归一化层单独允许训练模式更新。导出前在目标域仅前向更新滑动统计时单独升版本,与权重同发布。小批量微调默认先冻结,再考虑加大批次或换组归一化。文档说明各策略适用边界。
9. 案例复盘
某每卡批量四缺陷微调损失锯齿、验证抖,冻结骨干批归一化后曲线平滑且验证涨两点。复盘把每卡批量小于八必须写明批归一化策略写进审查清单。另一项目域差距大,在目标数据上重估滑动统计再冻结,比盲目更新更稳。团队不再默认微调就等于继续更新预训练统计。该规则与逐层解冻手册交叉引用,避免只冻批归一化却全解冻大学习率。
8. 与逐层解冻的衔接
批归一化策略须与 dl-transfer-learning 的分阶段解冻同步写进配置:仅训头时冻结全骨干统计量;解冻深层时可只对新建头允许更新滑动均值方差。发版材料注明 running stats 来自预训练、目标域重估或微调更新,Serving 不得混用不同来源的 checkpoint 与统计量版本。
微调 BatchNorm 的契约是:小 batch 别用 noisy stats 更新 pretrain 表示。Freeze 是默认稳妥项;换 GN 或 re-estimate 按 domain gap 和算力选。把 BN 策略与 running stats 来源写进发版材料;目标域差距大时可在仅前向遍历上重估滑动统计后再冻结,该步骤须单独版本化并与权重同步发布。小批量微调默认推荐冻结骨干批归一化。审查训练脚本时确认每轮开头对骨干统计层仍保持评估模式,避免误用批次统计覆盖预训练滑动均值。
相关
也可以看看
- ·5 分钟阅读
peft target_modules 与 merge
LoRA 只训低秩增量矩阵,省显存防 catastrophic——rank 和 target modules 决定 capacity,全量微调仍可能在数据足时更强。
- ·3 分钟阅读
微调:冻哪些层
数据少时一次解冻全网易过拟合+毁 pretrained 特征——先训 head、再逐层解冻是稳妥默认,LR 分组随解冻调整。
- ·4 分钟阅读
BatchNorm:训练推理模式
model.train() 与 model.eval() 切换 BatchNorm 的统计量来源——忘了 eval 或 batch=1 时 running stats 与当前 batch 混用,推理结果会随机飘。
johan's blog