迁移学习中如何冻结TensorFlow的BatchNormalization层?
结论先行
你应该直接选第一种操作,第二种操作没有任何实际作用。绝大多数场景下,冻结BatchNormalization层是更稳妥的最优选择。
具体原因解释
两种操作的有效性分析
- 第二种操作完全无效:手动调用
layer.call(layer.input, training=False)只是当场对输入做了一次推理模式的计算,完全不会修改层的默认运行逻辑,后续你训练模型的时候,BatchNormalization层还是会按照默认状态运行,这段代码等于白写,没有任何实用价值。 - 第一种操作符合Keras的设计逻辑:对于
BatchNormalization层,trainable属性和运行模式是绑定的,只要你设置layer.trainable = False,层就会自动切换到推理模式,不会更新跟踪的滑动均值、方差,也不会更新gamma和beta可训练参数,完全符合TensorFlow官方指南的要求,效果稳定可预期。
冻结BatchNormalization层的适用场景
默认情况下优先选择冻结所有BatchNormalization层,原因如下:
- 预训练模型的
BatchNormalization层已经在大规模数据集(比如ImageNet)上学习到了非常稳定的归一化统计量,微调阶段贸然更新这些参数,很容易破坏预训练阶段已经学到的有效特征。 - 大部分开发者微调时的batch size都不会太大(普遍小于32),小batch下统计的单批均值、方差噪声极高,用这些值更新
BatchNormalization的统计量只会让模型效果暴跌。
特殊场景的例外情况
只有同时满足以下所有条件时,你才可以考虑不冻结BatchNormalization层,甚至单独训练BatchNormalization层的参数(就是你看到的第三方文章的写法):
- 你的微调数据集规模足够大,和预训练模型的训练数据集分布差异非常明显
- 你可以支撑足够大的训练batch size(至少32以上,最好64+)
- 你已经测试过冻结BN层的效果,确认效果不佳
内容的提问来源于stack exchange,提问作者Nickname11
相关产品推荐
相关产品推荐

