PyTorch为CNN模型设置固定卷积权重时出现额外可训练参数如何解决
问题根因
- 你对卷积层的权重赋值逻辑存在错误:PyTorch中
nn.Conv2d的权重默认是四维张量,维度格式为(输出通道数, 输入通道数, 卷积核高度, 卷积核宽度)。你在初始化时nn.Conv2d已经生成了符合格式的权重参数,后续直接给self.layer1.weight赋值二维张量,相当于给layer1这个Sequential容器新增了一个独立的weight属性,Conv2d内部的原始权重并没有被修改,依然保留在模型参数列表中且默认开启梯度更新,这就是你看到额外参数的原因。 - 赋值时没有正确指定权重的维度,也没有关闭原有卷积参数的梯度更新开关,导致运行时参数会被随机初始化、甚至训练过程中被修改,最终输出结果不稳定。
正确的实现方案
你需要直接修改Sequential容器内卷积层的内部权重,同时将所有权重的requires_grad设为False即可,修改后的完整代码如下:
import torch import torch.nn as nn class CNN(nn.Module): def __init__(self): super(CNN, self).__init__() self.layer1 = nn.Sequential( nn.Conv2d(in_channels=1, out_channels=1, kernel_size=(2, 2), stride=1, padding=1, bias=False), nn.AvgPool2d(kernel_size=(2, 2), stride=(2, 2)) ) # 直接修改卷积层的内部权重,将二维权重扩展为符合Conv2d要求的四维 with torch.no_grad(): weights1 = torch.tensor([[0.2390, 0.1593], [0.5377, 0]]).unsqueeze(0).unsqueeze(0) self.layer1[0].weight = nn.Parameter(weights1, requires_grad=False) self.layer2 = nn.Sequential( nn.Conv2d(in_channels=1, out_channels=1, kernel_size=(2, 2), stride=1, padding=1, bias=False), nn.AvgPool2d(kernel_size=(2, 2), stride=(2, 2)) ) with torch.no_grad(): weights2 = torch.tensor([[-0.2390, -0.3585], [-0.5377, 0.2390]]).unsqueeze(0).unsqueeze(0) self.layer2[0].weight = nn.Parameter(weights2, requires_grad=False) # 全局遍历确认所有参数梯度都关闭,额外保险 for param in self.parameters(): param.requires_grad = False def forward(self, x): x = self.layer1(x) x = self.layer2(x) return x
验证方法
你可以通过如下命令查看模型参数,确认只有两个固定权重、且requires_grad均为False:
model = CNN() for name, param in model.named_parameters(): print(name, param.shape, param.requires_grad)
修改后输出应该为:
layer1.0.weight torch.Size([1, 1, 2, 2]) False layer2.0.weight torch.Size([1, 1, 2, 2]) False
不存在额外的可训练参数,运行时输出结果也会保持固定。
内容的提问来源于stack exchange,提问作者이재환
相关产品推荐
相关产品推荐

