使用PyTorch训练CNN时不同batch size准确率差异悬殊的原因探究
使用PyTorch训练CNN图像分类器时,发现batch size设为4和32时,模型准确率存在20%以上的显著差异,具体训练结果如下:
batch_size = 4
100%|██████████| 10/10 [02:50<00:00, 17.04s/it, TestAcc=71%, TrainAcc=74%, loss=0.328]
batch_size = 32
100%|██████████| 10/10 [02:38<00:00, 15.85s/it, TestAcc=53%, TrainAcc=57%, loss=0.208]
模型定义:
import torch import torch.nn as nn import torch.nn.functional as F class Net(nn.Module): def __init__(self, num_classes): super().__init__() self.conv1 = nn.Conv2d(3, 6, 5) self.pool = nn.MaxPool2d(2, 2) self.conv2 = nn.Conv2d(6, 16, 5) self.fc1 = nn.Linear(16 * 5 * 5, 120) self.fc2 = nn.Linear(120, 84) self.fc3 = nn.Linear(84, num_classes) def forward(self, x): x = self.pool(F.relu(self.conv1(x))) x = self.pool(F.relu(self.conv2(x))) x = torch.flatten(x, 1) # flatten all dimensions except batch x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = self.fc3(x) return x
学习率未随batch size缩放
大部分优化器的学习率是基于小batch size调优的。当batch size从4涨到32(扩大8倍),如果学习率不变,每次参数更新的步长会相对过大,模型容易在训练中震荡,难以收敛到泛化性好的权重。小batch size的梯度噪声反而能帮模型跳出局部最优,而大batch size固定学习率容易陷入“看起来loss低但泛化差”的尖锐极小值,正好对应你看到的情况。BatchNorm的统计量偏差
如果你的模型实际使用了BatchNorm(代码未体现但CNN常用),不同batch size会直接影响均值和方差的计算:小batch的统计量波动大,相当于给模型加了更强的正则化,防止过拟合;大batch的统计量更稳定,正则化效果减弱,模型容易记住训练样本细节,泛化能力下降。梯度估计的噪声差异
小batch的梯度是少量样本的平均,噪声大,但这种噪声能引导模型探索更多权重空间,找到泛化性更好的平缓极小值;大batch的梯度更接近真实梯度,但容易收敛到泛化性差的尖锐极小值——这类极小值在训练集上loss低,但测试集上准确率暴跌,和你的实验结果完全匹配。数据加载与预处理的一致性问题
检查两种batch size下的数据加载逻辑:比如大batch时数据增强的随机性是不是被削弱了,或者数据采样时的类别分布有没有偏差。如果数据集本身不大,大batch会让每个epoch里样本重复出现的模式更固定,模型更容易死记硬背训练数据,而非学习通用特征。优化器参数未适配大batch
不同优化器对batch size敏感度不同。比如Adam的β1、β2参数,在大batch下可能需要调整,不然动量积累的方向容易跑偏;SGD的动量系数也可能需要配合batch size调整。如果你的优化器参数是针对小batch设的,直接放大batch size会打乱训练动态。
内容的提问来源于stack exchange,提问作者anon_1011

