VGG16默认输出1000类,需替换classifier[6]为适配新类别的线性层,并严格使用ImageNet均值标准差归一化,训练时调用model.train()确保Dropout生效。

为什么直接加载VGG16会报 RuntimeError: size mismatch
默认用 torchvision.models.vgg16(pretrained=True) 加载的模型,其最后的全连接层 classifier[6] 输出维度是 1000(对应 ImageNet 类别),但你要识别的是自定义类别(比如猫/狗/车共3类)。如果直接用 model.fc = nn.Linear(...) 就会出错——VGG16 没有 fc 属性,它的分类头叫 classifier,且结构是 Sequential,不能像 ResNet 那样简单替换 fc。
怎么改 VGG16 的 classifier 才能适配新任务
必须显式替换 classifier 中最后一层,而不是整个 Sequential。否则中间层输出尺寸不匹配,forward 会崩。
- 先冻结所有参数:
for param in model.parameters(): param.requires_grad = False - 获取原
classifier的输入维度:它来自model.classifier[6].in_features(注意不是[5]或[4]) - 构造新分类头:
nn.Sequential(nn.Linear(in_features, 512), nn.ReLU(), nn.Dropout(0.5), nn.Linear(512, num_classes)) - 赋值回去:
model.classifier[6] = new_classifier(不是model.classifier = ...)
图像预处理必须和 VGG16 训练时一致
VGG16 在 ImageNet 上训练时用了固定均值和标准差,torchvision.transforms 里 normalize 必须用 mean=[0.485, 0.456, 0.406] 和 std=[0.229, 0.224, 0.225],否则特征提取失效。常见错误是手写 Normalize(mean=[0.5], std=[0.5]),模型几乎不收敛。
完整 transform 示例:
立即学习“Python免费学习笔记(深入)”;
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
验证集准确率上不去?检查是否漏掉了 classifier 的 dropout 训练模式
VGG16 的 classifier 包含 Dropout 层,默认在 eval 模式下被关闭。但如果只对 features 冻结、只训练 classifier,务必在训练循环中调用 model.train(),否则 Dropout 不生效,验证指标虚高,实际推理却波动大。
- 训练时:
model.train()→ Dropout 开启,BatchNorm 更新统计量 - 验证/推理时:
model.eval()→ Dropout 关闭,BatchNorm 使用运行均值 - 别只对部分模块调
.train(),要整模型统一设
迁移学习里最容易被忽略的,就是模型模式切换和 classifier 结构细节——这两处一错,训半天也看不到 loss 下降。


















