微调ResNet18用于CIFAR10:两种修改最后层方式为何结果不同?
问题根源与解决方法
为什么两种方式结果不同?
- ResNet18的原生结构里,最后几层是
AvgPool2d→ 手动展平 →fc线性层。当你用list(ResModel.children())[:-1]截取前半部分时,得到的最后一层是AvgPool2d,它输出的张量形状是(batch_size, 512, 1, 1)(CIFAR10的32x32图片经过卷积池化后,最后特征图是1x1)。 - 直接把这个4维张量喂给
nn.Linear(512,10)时,Linear层不会自动展平,它会把输入当成(batch_size*512*1, 1)来计算,也就是报错里的32768x1(假设batch size是32,32*512=32768),而Linear需要的是(N, 512)的输入,形状不匹配导致报错。 - 而修改
ResModel.fc的方式能正常运行,是因为原ResNet的forward方法中,在传入fc层前会自动执行torch.flatten(x, 1)把4维张量展平成(batch_size,512),替换fc层后这个展平逻辑依然生效,所以输入形状完全符合Linear层的要求。
用Sequential实现的正确写法
如果坚持用nn.Sequential的方式,需要手动添加一个展平层:
ResModel = resnet18(weights=ResNet18_Weights) model = nn.Sequential( *list(ResModel.children())[:-1], nn.Flatten(), # 把(bs,512,1,1)展平为(bs,512) nn.Linear(512,10) )
内容的提问来源于stack exchange,提问作者zz z
相关产品推荐
相关产品推荐

