Neural network 创建一个权重为两个不同神经网络权重之和的模型
我正在做一个迁移学习的实验。 我训练了两个结构完全相同的CNN,一个用于MNIST,一个用于SVHN。 我获得了两个模型的参数(权重和偏差)。 现在,我想组合(求和或其他操作)这些权重。像这样的事情:Neural network 创建一个权重为两个不同神经网络权重之和的模型,neural-network,pytorch,conv-neural-network,mnist,transfer-learning,Neural Network,Pytorch,Conv Neural Network,Mnist,Transfer Learning,我正在做一个迁移学习的实验。 我训练了两个结构完全相同的CNN,一个用于MNIST,一个用于SVHN。 我获得了两个模型的参数(权重和偏差)。 现在,我想组合(求和或其他操作)这些权重。像这样的事情: modelMNIST.parameters() modelSVHN.parameters() #now the new model model3 = MyCNN(1) model3.parameters = modelMNIST.parameters()+modelSVHN.parameters
modelMNIST.parameters()
modelSVHN.parameters()
#now the new model
model3 = MyCNN(1)
model3.parameters = modelMNIST.parameters()+modelSVHN.parameters()
如果我这样做,我会得到以下错误:
语法错误:无法分配给函数调用
通过这种方式:
model3.block_1[0].weight = modelMNIST.block_1[0].weight + modelSVHN.block_1[0].weight
我得到这个错误:
TypeError: cannot assign 'torch.cuda.FloatTensor' as parameter 'weight' (torch.nn.Parameter or None expected)
有没有办法组合不同型号的权重?您需要更新参数的
.data
属性<代码>参数不是浮点张量,因此是错误的
由于这两个网络是相同的,您可以使用下面的代码来更新权重
for param1, param2 in zip(modelMNIST.parameters(), modelSVHN.parameters()):
param1.data += param2.data
我的解决办法是:
class VGG16SUM(nn.Module):
def __init__(self, model1, model2, num_classes):
super(VGG16SUM, self).__init__()
# calculate same padding:
# (w - k + 2*p)/s + 1 = o
# => p = (s(o-1) - w + k)/2
self.block_1 = nn.Sequential(
nn.Conv2d(in_channels=1,
out_channels=64,
kernel_size=(3, 3),
stride=(1, 1),
# (1(32-1)- 32 + 3)/2 = 1
padding=1),
nn.BatchNorm2d(64),
nn.ReLU(),
nn.Conv2d(in_channels=64,
out_channels=64,
kernel_size=(3, 3),
stride=(1, 1),
padding=1),
nn.BatchNorm2d(64),
nn.ReLU(),
nn.MaxPool2d(kernel_size=(2, 2),
stride=(2, 2))
)
self.block_2 = nn.Sequential(
nn.Conv2d(in_channels=64,
out_channels=128,
kernel_size=(3, 3),
stride=(1, 1),
padding=1),
nn.BatchNorm2d(128),
nn.ReLU(),
nn.Conv2d(in_channels=128,
out_channels=128,
kernel_size=(3, 3),
stride=(1, 1),
padding=1),
nn.BatchNorm2d(128),
nn.ReLU(),
nn.MaxPool2d(kernel_size=(2, 2),
stride=(2, 2))
)
self.block_3 = nn.Sequential(
nn.Conv2d(in_channels=128,
out_channels=256,
kernel_size=(3, 3),
stride=(1, 1),
padding=1),
nn.BatchNorm2d(256),
nn.ReLU(),
nn.Conv2d(in_channels=256,
out_channels=256,
kernel_size=(3, 3),
stride=(1, 1),
padding=1),
nn.BatchNorm2d(256),
nn.ReLU(),
nn.Conv2d(in_channels=256,
out_channels=256,
kernel_size=(3, 3),
stride=(1, 1),
padding=1),
nn.BatchNorm2d(256),
nn.ReLU(),
nn.MaxPool2d(kernel_size=(2, 2),
stride=(2, 2))
)
self.block_4 = nn.Sequential(
nn.Conv2d(in_channels=256,
out_channels=512,
kernel_size=(3, 3),
stride=(1, 1),
padding=1),
nn.BatchNorm2d(512),
nn.ReLU(),
nn.Conv2d(in_channels=512,
out_channels=512,
kernel_size=(3, 3),
stride=(1, 1),
padding=1),
nn.BatchNorm2d(512),
nn.ReLU(),
nn.Conv2d(in_channels=512,
out_channels=512,
kernel_size=(3, 3),
stride=(1, 1),
padding=1),
nn.BatchNorm2d(512),
nn.ReLU(),
nn.MaxPool2d(kernel_size=(2, 2),
stride=(2, 2))
)
self.classifier = nn.Sequential(
nn.Linear(2048, 4096),
nn.ReLU(True),
nn.Dropout(p=0.25),
nn.Linear(4096, 4096),
nn.ReLU(True),
nn.Dropout(p=0.25),
nn.Linear(4096, num_classes),
)
for p_out, p_in1, p_in2 in zip(self.parameters(), model1.parameters(), model2.parameters()):
p_out.data = nn.Parameter(p_in1 +p_in2);
def forward(self, x):
x = self.block_1(x)
x = self.block_2(x)
x = self.block_3(x)
x = self.block_4(x)
# x = self.avgpool(x)
x = x.view(x.size(0), -1)
x = self.classifier(x)
return x
#logits = self.classifier(x)
#probas = F.softmax(logits, dim=1)
# probas = nn.Softmax(logits)
#return probas
# return logits
它工作 谢谢。我必须在实例化新模型后编写它?像
model3=VGG16(1)
这样修改代码:对于zip中的param1、param2、param3(modelmnit.parameters()、modelSVHN.parameters()、model3.parameters()):param3.data=param1.data+param2.data
你认为这样的解决方案好吗?是的,这是有意义的。我找到了另一种可行的方法。再次谢谢你好的,当然!不过,您不需要在解决方案中使用nn.Parameter
。