You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

预训练CNN集成模型中不同Batch Size导致推理精度差异过大的问题咨询

为什么基于Softmax投票的集成模型在batch_size=1时精度骤降?

我尝试实现基于Softmax的基础投票机制:选取4个从chenyaofo/pytorch-cifar-models加载的CIFAR10预训练VGG模型,对各模型输出执行Softmax后求和取Argmax得到最终结果。但发现当batch_size设为128/256时精度能到94%,设为1时仅69%。

问题根源分析

这个现象主要由两个核心问题导致:

  • 模型未进入评估(eval)模式
    你加载的预训练VGG模型带有BatchNorm层,而PyTorch模型默认处于训练(train)模式。在训练模式下,BatchNorm层会使用当前批次的均值和方差做归一化,而非预训练阶段保存的全局running_meanrunning_var。当batch_size=1时,单样本的统计量和训练时的全局统计量偏差极大,直接让模型输出完全偏离预期;而大批次时,批次统计量刚好接近训练时的全局统计量,精度暂时正常,但这只是巧合,并非正确的评估方式。

  • 测试数据未做与训练一致的归一化
    你当前的测试变换仅包含transforms.ToTensor(),但这些预训练模型是在经过标准化的CIFAR10数据上训练的。ToTensor()仅把像素值从0-255缩放到0-1,没有减去均值、除以标准差,这会导致输入数据分布和模型训练时的分布不匹配,在小批次时这个问题的影响会被进一步放大。

修复方案

1. 强制模型进入评估模式

在构建集成模型后,务必调用model.eval(),让BatchNorm、Dropout等层切换到评估逻辑:

model = MyEnsemble(models[0], models[1], models[2], models[3])
model.to(device)
model.eval()  # 新增这一行,关键!

2. 添加训练一致的归一化变换

按照CIFAR10的标准归一化参数修改测试数据变换:

test_transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.4914, 0.4822, 0.4465], std=[0.2023, 0.1994, 0.2010])
])

3. 可选:简化集成模型实现

可以用循环批量处理模型,避免重复代码:

class MyEnsemble(nn.Module):
    def __init__(self, models_list):
        super(MyEnsemble, self).__init__()
        self.models = nn.ModuleList(models_list)

    def forward(self, x):
        total_output = None
        for model in self.models:
            logits = model(x)
            softmax_out = torch.softmax(logits, dim=1)
            total_output = softmax_out if total_output is None else total_output + softmax_out
        return total_output

初始化时直接传入模型列表即可:

model = MyEnsemble(models)

修改完成后,无论batch_size设置为1还是更大的值,模型精度都会稳定在94%左右,符合预期。

内容的提问来源于stack exchange,提问作者JojoHalastra

火山引擎 最新活动