最快方法是直接用torchvision.models.resnet50(pretrained=true)加载预训练权重并替换fc层为nn.linear(2048, num_classes),同时严格按imagenet规范做resize(256)+centercrop(224)和normalize([0.485,0.456,0.406],[0.229,0.224,0.225])。

直接用 torchvision.models.resnet50 加 torch.nn.Linear 替换分类头,是最稳妥的起点;别自己重写 ResNet 结构,也别在预训练权重加载前修改网络——否则 load_state_dict() 会报 Missing key 或 Unexpected key 错误。
替换 ResNet 分类层时,必须保持输入维度匹配
原 resnet50 的 fc 层输入是 2048 维(对应最后一个残差块输出),输出默认为 1000 类。你要做迁移学习,就得按新任务类别数重置输出维度:
- 先实例化模型:
model = torchvision.models.resnet50(pretrained=True) - 再替换:
model.fc = torch.nn.Linear(2048, num_classes)(num_classes是你的数据集类别数) - 如果用的是
resnet18,输入维度是 512,别写成 2048——查model.fc.in_features最保险 - 别漏掉
pretrained=True,否则加载的是随机初始化权重,迁移效果归零
冻结 backbone 时,要设 requires_grad = False 而非只改 model.eval()
model.eval() 只影响 Dropout 和 BatchNorm 行为,不阻止梯度计算;真正冻结参数得遍历参数并关梯度:
调用 Cutout.Pro 视觉处理 API 进行背景移除、人像抠图和照片增强,支持文件上传与图片 URL 输入。
- 冻结全部 backbone:
for param in model.parameters(): param.requires_grad = False - 只冻结到某一层(比如只微调最后两个残差块):
for name, param in model.named_parameters(): if "layer4" not in name and "fc" not in name: param.requires_grad = False - 冻结后务必检查:
sum(p.requires_grad for p in model.parameters())应该远小于总参数量 - 冻结状态下仍要调用
model.train()(尤其用了 BatchNorm),否则 BN 统计值不会更新,验证时指标崩塌
数据增强和归一化必须复用预训练模型的统计值
PyTorch 官方 ResNet 预训练权重基于 ImageNet 统计值(均值 [0.485, 0.456, 0.406],标准差 [0.229, 0.224, 0.225])。你用自己的均值/标准差做归一化,会导致特征偏移,模型“认不出”输入:
- 训练时增强可加:
transforms.RandomHorizontalFlip()、transforms.ColorJitter() - 但归一化必须严格用:
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) - 验证/测试阶段同样要归一化,且不能加随机增强(如去掉
Random*) - 如果你用 OpenCV 读图或自定义 Dataset,确保通道顺序是 RGB(不是 BGR),否则归一化值错位
最容易被忽略的是:BatchNorm 层里的 running_mean / running_var 在微调时会继续更新,哪怕你冻结了权重。这意味着即使冻结了 backbone,BN 层依然在“悄悄适应”你的数据分布——这通常是好事,但若你的训练集极小(model.eval() 并在验证前 model.train() 切换,或者把 BN 层替换成 GroupNorm。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










