使用VGG、ResNet等预训练模型作为骨干网络时应选eval模式还是train模式?
结论
哪怕你已经完全冻结了VGG16的所有参数梯度,也需要在训练启动前调用vgg16.eval()。
核心原因
PyTorch中模型的train()/eval()模式开关,和参数requires_grad是否为True是两套完全独立的控制逻辑,两者作用的对象完全不同:
requires_grad控制的是反向传播时是否计算参数的梯度,决定参数会不会被优化器更新train()/eval()控制的是模型中特定层的前向传播行为,和梯度计算、参数更新没有直接关联
会受到模式开关影响的常见层包括:
- Dropout层:
train模式下会按设定概率随机失活神经元,引入随机性;eval模式下关闭失活逻辑,所有神经元参与计算,输出稳定 - BatchNorm层:
train模式下会用当前批次数据的均值、方差做归一化,同时更新内部存储的全局滑动均值、方差统计量;eval模式下直接使用预训练阶段固化的全局均值、方差做归一化,不会更新内部统计量
你的场景下不调用eval()的问题
你用预训练VGG16做固定特征提取,核心需求是拿到和预训练阶段分布一致的稳定特征,如果VGG16跑在train模式下会有两个问题:
- Dropout引入的随机波动会导致同一样本多次输入得到的特征不一致,不利于后续网络模块的学习
- 即使冻结了BatchNorm层的权重和偏置的梯度,
train模式下它还是会用你当前训练数据集的批次数据更新滑动均值、方差,最终VGG16的统计特征会慢慢偏离预训练状态,相当于变相修改了VGG16的行为。
特殊例外情况
如果你明确需要让VGG16的BatchNorm层适配你的自定义数据集的分布,可以单独把VGG16中的所有BatchNorm层设置为train模式,其余层保持eval模式,这属于针对性优化场景,常规固定特征提取需求不需要这么做。
内容的提问来源于stack exchange,提问作者Karl
相关产品推荐
相关产品推荐

