PyTorch中预训练VGG-19模型深拷贝失效问题求助
问题原因及解决方法
核心原因
你遇到的问题并非copy.deepcopy失效,而是后续结构划分时复用了原模型的子模块引用,导致两个模型共享了参数张量:
copy.deepcopy(vgg)确实会生成一个与原模型完全独立的拷贝,但你后续对原vgg进行结构重构(截断为前31层的nn.Sequential)后,在构建Encoder的分层结构时,错误地使用了原vgg的子模块引用(通过list(vgg.children())获取)来创建Encoder的layer。- PyTorch中
children()返回的是模块的直接子模块引用,而非拷贝。这意味着原vgg和Encoder的对应子模块指向同一个对象,它们的参数张量完全共享——此时修改原模型参数的requires_grad属性,自然会同步影响到Encoder的参数。
解决方法
对Encoder进行结构划分时,必须基于Encoder自身的子模块,而非原vgg的子模块,确保两个模型的参数完全独立:
修正后的代码示例
import copy import torch import torch.nn as nn # 加载原VGG模型 vgg = model.vgg vgg.load_state_dict(torch.load(args.vgg)) # 深拷贝得到Encoder Encoder = copy.deepcopy(vgg) Encoder.train() Encoder.to(device) optimizer_E = torch.optim.Adam(Encoder.parameters(), lr=args.e_lr) # ---------------------- 处理原VGG(用于特征提取,固定参数) ---------------------- vgg_feature = nn.Sequential(*list(vgg.children())[:31]) # 基于原VGG自己的子模块划分层 feat_extractor_vgg = list(vgg_feature.children()) self.vgg_layer1 = nn.Sequential(*feat_extractor_vgg[:4]) self.vgg_layer2 = nn.Sequential(*feat_extractor_vgg[4:11]) self.vgg_layer3 = nn.Sequential(*feat_extractor_vgg[11:18]) self.vgg_layer4 = nn.Sequential(*feat_extractor_vgg[18:31]) # 固定原模型所有参数 for param in vgg_feature.parameters(): param.requires_grad = False # ---------------------- 处理Encoder(用于微调,可训练) ---------------------- encoder_feature = nn.Sequential(*list(Encoder.children())[:31]) # 基于Encoder自己的子模块划分层 feat_extractor_encoder = list(encoder_feature.children()) self.encoder_layer1 = nn.Sequential(*feat_extractor_encoder[:4]) self.encoder_layer2 = nn.Sequential(*feat_extractor_encoder[4:11]) self.encoder_layer3 = nn.Sequential(*feat_extractor_encoder[11:18]) self.encoder_layer4 = nn.Sequential(*feat_extractor_encoder[18:31]) # 设置Encoder参数可训练 for param in encoder_feature.parameters(): param.requires_grad = True
额外提示
如果不需要拆分结构后单独操作某几层,直接遍历整个模型的参数设置requires_grad会更简洁,避免因子模块引用导致的参数共享问题。
内容的提问来源于stack exchange,提问作者Luca
相关产品推荐
相关产品推荐

