PyTorch训练VGG时出现Target与input size维度不匹配报错如何解决
根因定位
你遇到的维度不匹配问题本质不是VGG网络输出维度主动变化,核心原因有两个:
- 批次维度动态变化:你固定写死了域标签的长度为128,但训练到最后一个批次时,如果数据集总样本数不是128的整数倍,DataLoader默认会返回不足128的剩余样本(你这里是112个),输入VGG的batch第一维从128变成112,VGG输出的第一维自然同步变为112,和固定长度的标签维度不匹配。
- VGG结构存在设计隐患:你注释掉了VGG的平均池化层,如果训练过程中输入图像的尺寸发生波动,经过4个VGG块后的特征图尺寸会变化,
torch.flatten后的特征维度也会同步变化,只是你目前的场景中第二维刚好稳定为2048没触发问题而已。
解决方案
按优先级可选以下方案处理:
- 动态生成域标签(优先级最高)
不要固定写死标签长度,每次根据当前输入的batch维度生成对应长度的标签,同时保证标签和输入在同一个设备上,避免后续设备不匹配报错:
# 替换原来固定写死的d_labels_a、d_labels_b定义 d_labels_a = torch.zeros(input_a.shape[0], device=input_a.device) d_labels_b = torch.ones(input_b.shape[0], device=input_b.device)
- 配置DataLoader丢弃不满批次
初始化训练集的DataLoader时添加drop_last=True参数,自动丢弃最后一个不足128的批次,保证所有训练批次的样本量都是128:
train_loader = DataLoader(train_dataset, batch_size=128, shuffle=True, drop_last=True)
- 补全VGG的自适应池化层
添加自适应平均池化层,固定输出特征图的尺寸,避免输入图像尺寸波动导致的特征维度变化:
class VGG16(nn.Module): def __init__(self, input_size, batch_norm=False): super(VGG16, self).__init__() self.in_channels,self.in_width,self.in_height = input_size self.block_1 = VGGBlock(self.in_channels,64,batch_norm=batch_norm) self.block_2 = VGGBlock(64, 128,batch_norm=batch_norm) self.block_3 = VGGBlock(128, 256,batch_norm=batch_norm) self.block_4 = VGGBlock(256,512,batch_norm=batch_norm) # 新增自适应平均池化,固定输出特征图尺寸为7*7 self.avgpool = nn.AdaptiveAvgPool2d((7, 7)) @property def input_size(self): return self.in_channels,self.in_width,self.in_height def forward(self, x): x = self.block_1(x) x = self.block_2(x) x = self.block_3(x) x = self.block_4(x) # 启用池化层 x = self.avgpool(x) x = torch.flatten(x,1) return x
- 检查数据预处理逻辑
如果存在异常样本过滤、跳过的逻辑,要么关闭该逻辑,要么过滤后补全样本到batch_size,避免主动缩减批次样本量。
内容的提问来源于stack exchange,提问作者CasellaJr
相关产品推荐
相关产品推荐

