删除ResNet34最后fc层时如何保留原层名称匹配预训练权重?
解决ResNet删除最后fc层同时保留原层名称的问题
你的问题出在torch.nn.Sequential会自动用数字索引作为层的名称,而list(resnet34.children())只提取了模块对象,丢失了原有的层名信息,导致加载预训练权重时名称不匹配。以下两种方法可以解决:
方法一:直接修改原ResNet模型(推荐)
直接删除原模型的fc层,保留所有原有层的名称,操作最简单:
import torch import torchvision.models as models resnet34 = models.resnet34(pretrained=False) # 删除最后全连接层 del resnet34.fc # 此时模型保留了所有原层名称,如conv1、bn1、avgpool等 checkpoint = torch.load('./resnet18-f37072fd.pth') # strict=False忽略预训练权重中不存在的fc层参数 resnet34.load_state_dict(checkpoint, strict=False)
方法二:用OrderedDict构建带名称的Sequential
如果必须使用Sequential结构,可以通过collections.OrderedDict手动指定每个层的名称,确保和原模型一致:
import torch import torchvision.models as models from collections import OrderedDict resnet34 = models.resnet34(pretrained=False) # 遍历原模型的子模块,跳过fc层并保留名称 layer_dict = OrderedDict() for name, module in resnet34.named_children(): if name != 'fc': layer_dict[name] = module # 用带名称的OrderedDict构建Sequential mymodel = torch.nn.Sequential(layer_dict) checkpoint = torch.load('./resnet18-f37072fd.pth') mymodel.load_state_dict(checkpoint, strict=False)
说明
- 原方法中
list(resnet34.children())只获取模块实例,没有名称,Sequential会自动给层分配0、1、...、8这样的数字名称,和预训练权重里的avgpool等名称不匹配。 - 两种方法都能保留原层名称,确保加载预训练权重时名称对应,
strict=False用于忽略预训练权重中不存在的fc层参数。
内容的提问来源于stack exchange,提问作者ChenChao
相关产品推荐
相关产品推荐

