ResNet多分类模型过拟合调试遇RuntimeError,求解决方案
问题解决与过拟合应对方案
一、形状不匹配错误修复
你遇到的RuntimeError: mat1 and mat2 shapes cannot be multiplied错误,核心原因是自定义分类器Flowers中nn.Linear的in_features参数设置完全错误,与截断后ResNet输出的特征维度不匹配。
修正思路
- 先明确截断后模型的输出特征维度:ResNet的不同层级输出特征图的尺寸和通道数不同,比如ResNet50的layer3输出是14×14×1024(输入224×224图片时),layer4输出是7×7×2048。
- 给自定义分类器添加自适应池化层,将任意尺寸的特征图转为固定维度的向量,再接入全连接层。
修正后代码示例
import torch import torch.nn as nn class Flowers(nn.Module): def __init__(self, in_features): super().__init__() self.classifier = nn.Sequential( nn.AdaptiveAvgPool2d((1, 1)), # 将特征图转为1×1×in_features nn.Flatten(), nn.Linear(in_features=in_features, out_features=102), ) def forward(self, x): x = self.classifier(x) return x torch.manual_seed(42) # 加载预训练ResNet50 model = torch.hub.load("pytorch/vision", "resnet50", weights="IMAGENET1K_V2") # 截断ResNet到layer3(去掉layer4及后续层,降低模型复杂度) my_model = nn.Sequential(*list(model.children())[:7]) # 传入对应通道数1024作为全连接层输入维度 my_model.add_module('fc', Flowers(in_features=1024)) # 验证输入输出形状匹配 test_input = torch.randn(1, 3, 224, 224) output = my_model(test_input) print(output.shape) # 预期输出: torch.Size([1, 102])
如果只是想替换原ResNet的全连接层(而非大幅截断层数),可使用更简洁的写法:
torch.manual_seed(42) model = torch.hub.load("pytorch/vision", "resnet50", weights="IMAGENET1K_V2") # ResNet50的平均池化层输出为2048维,直接替换全连接层 model.fc = nn.Linear(in_features=2048, out_features=102)
二、通用过拟合解决方法
- 数据增强:对训练集图片执行随机翻转、裁剪、旋转、颜色抖动等操作,扩大有效训练样本量,增强模型泛化能力。可使用
torchvision.transforms中的RandomHorizontalFlip、RandomResizedCrop等工具。 - 正则化手段:
- L2正则化:在优化器中设置
weight_decay参数,给模型权重添加L2范数惩罚,限制参数规模。 - Dropout层:在全连接层或卷积层之间加入
nn.Dropout(p=0.5),随机失活部分神经元,避免模型依赖特定神经元组合。
- L2正则化:在优化器中设置
- 早停机制:训练时监控验证集的损失或准确率,当验证集性能连续多轮无提升时,提前终止训练,避免模型过度拟合训练集。
- 降低模型复杂度:减少网络层数、缩小卷积核数量或全连接层维度,比如用ResNet18替代ResNet50,或截断ResNet的高层特征提取模块。
- 迁移学习:使用预训练模型,冻结底层通用特征提取层,仅训练顶层分类器,利用预训练模型的泛化特征,避免从零训练导致的过拟合。
- 标签平滑:计算交叉熵损失时,给真实标签加入少量噪声(如
label_smoothing=0.1),避免模型对标签过度确信,提升泛化能力。 - 增加训练数据:收集更多真实样本,或通过数据合成技术生成新样本,提升数据多样性。
内容的提问来源于stack exchange,提问作者whrecker
相关产品推荐
相关产品推荐

