ResNet在Train与Eval模式下输出差异过大的技术咨询
Train/Eval模式下ResNet输出差异显著是否影响模型性能?
我正尝试在PyTorch中实现ResNet,但发现Train模式与Eval模式下的前向传播输出差异显著。由于Train和Eval模式仅会影响BatchNorm和Dropout,我不确定该结果是否合理。
测试代码
import torch from torch import nn from torchvision import models class resnet_lstm(torch.nn.Module): def __init__(self): super(resnet_lstm, self).__init__() resnet = models.resnet50(pretrained=True) self.share = torch.nn.Sequential() self.share.add_module("conv1", resnet.conv1) self.share.add_module("bn1", resnet.bn1) # Use BatchNorm3d self.share.add_module("relu", resnet.relu) self.share.add_module("maxpool", resnet.maxpool) self.share.add_module("layer1", resnet.layer1) self.share.add_module("layer2", resnet.layer2) self.share.add_module("layer3", resnet.layer3) self.share.add_module("layer4", resnet.layer4) self.share.add_module("avgpool", resnet.avgpool) self.fc = nn.Sequential(nn.Linear(2048, 512), nn.ReLU(), nn.Linear(512, 7)) def forward(self, x): x = x.view(-1, 3, 224, 224) x = self.share(x) return x model = resnet_lstm() input_ = torch.randn(1, 3, 224, 224) model.train() print("train mode output", model(input_)) model.eval() print("eval mode output", model(input_))
终端输出
train mode output tensor([[[[0.3603]], [[0.5518]], [[0.4599]], ..., [[0.3381]], [[0.4445]], [[0.3481]]]], grad_fn=<MeanBackward1>) eval mode output tensor([[[[0.1582]], [[0.1822]], [[0.0000]], ..., [[0.0567]], [[0.0054]], [[0.3605]]]], grad_fn=<MeanBackward1>)
解答
这种差异是完全正常且合理的,核心原因是BatchNorm在Train和Eval模式下的行为逻辑截然不同:
- 训练模式:BatchNorm会使用当前输入批次的均值和方差做归一化,同时持续更新内部维护的全局均值、方差统计量
- 评估模式:BatchNorm会直接调用训练阶段累计下来的全局均值和方差做归一化,不再更新统计量
你用的是预训练ResNet,它的BatchNorm统计量是基于ImageNet全量数据集累计得到的。而测试时你用的是随机生成的输入,训练模式下会用这个随机批次的统计量计算,和预训练的全局统计量偏差极大,自然会导致输出差异明显。
这种差异不会损害模型性能,只要严格遵循「训练时开model.train(),推理时开model.eval()」的规范即可:训练阶段用批次统计量能让模型更好地适配当前数据分布,推理阶段用全局统计量能保证输出的稳定性和一致性。
另外注意代码里的注释写了"Use BatchNorm3d",但ResNet的bn1实际是BatchNorm2d,这里别混淆,不过不影响当前问题的结论。
内容的提问来源于stack exchange,提问作者WillWu
相关产品推荐
相关产品推荐

