PyTorch卷积神经网络(CNN)对图像尺寸的要求及预训练模型图像适配疑问
PyTorch卷积神经网络(CNN)对图像尺寸的要求及预训练模型图像适配疑问
嗨,我来帮你拆解这两个问题,先看你写的CNN代码,再聊预训练模型的事儿~
一、你的自定义CNN能不能适配任意图像尺寸?
答案是不能,问题出在最后的全连接层 self.fc = nn.Linear(64*7*7, num_classes)。咱们一步步算输入尺寸的变化逻辑:
假设你输入的图像是 (num_channels, H, W) 格式:
- 经过
conv1(padding=1、kernel=3),图像尺寸还是H×W,不会变; - 过
pool1(stride=2、kernel=2),尺寸直接减半,变成 (H//2) × (W//2); - 再经过
conv2,尺寸保持 (H//2) × (W//2) 不变; - 最后
pool2再减半,尺寸变成 (H//4) × (W//4);
这时候把特征图展平后,维度是 64 × (H//4) × (W//4),但你的全连接层硬编码了输入维度是64×7×7——这就意味着,只有当输入图像是28×28时(28//4=7),才能和全连接层匹配。如果换个尺寸,比如32×32,展平后的维度是64×8×8,和全连接层的输入维度不匹配,直接就会报错。
那怎么改成适配任意尺寸呢?给你两个常用的解决办法:
- 加自适应池化层:在
pool2之后加一层self.adaptive_pool = nn.AdaptiveAvgPool2d((1,1)),不管输入图像多大,这层都会把特征图压缩成1×1的固定尺寸,之后展平就是64×1×1,全连接层改成nn.Linear(64, num_classes)就行,完全不挑输入尺寸; - 把全连接层换成1×1卷积层:比如把
self.fc改成nn.Conv2d(64, num_classes, kernel_size=1),最后用torch.squeeze()去掉多余维度,这样也能适配任意尺寸,尤其适合语义分割这类需要保留空间信息的任务。
二、预训练模型的图像尺寸适配问题
预训练模型(比如在ImageNet上训练的ResNet、VGG)大多是在固定尺寸(比如224×224)的图像上训出来的,但不是说必须严格用这个尺寸,不过有几个点要注意:
- 全连接层的维度匹配:和你的自定义CNN一样,预训练模型的最后全连接层是固定输入维度的。如果换了输入尺寸,特征图经过池化后的尺寸会变,这时候要么修改全连接层的输入维度(比如原来ResNet50最后是2048×7×7,输入448×448的话,特征图是14×14,全连接层要改成2048×14×14),要么在全连接层前加自适应池化层(比如
nn.AdaptiveAvgPool2d((7,7))),把特征图固定到7×7,这样就不用改全连接层了; - 性能会受影响:预训练模型的权重是针对特定分辨率优化的,如果用的尺寸和训练时差太多(比如拿32×32的图像喂ResNet),性能大概率会打折扣——毕竟模型学的是224×224图像里的特征,小图像的特征分布和训练数据差得远;
- 预处理要和预训练模型对齐:不管你用什么尺寸,数据预处理的步骤必须和预训练模型一致,比如ImageNet的模型要求输入图像归一化的均值是[0.485, 0.456, 0.406]、方差是[0.229, 0.224, 0.225],还有图像的缩放、裁剪方式(比如保持比例后中心裁剪,还是随机裁剪),这些细节没做好,模型性能也会掉。
备注:内容来源于stack exchange,提问作者Baron Yugovich
相关产品推荐
相关产品推荐

