如何在PyTorch中连接两个模型并将第一个模型设置为不可训练

5

我有两个网络需要在我的完整模型中连接。然而,我的第一个模型是预训练的,在训练完整模型时需要将其设置为不可训练。我该如何在PyTorch中实现这一点。

我可以使用 this answer 来连接两个模型。

class MyModelA(nn.Module):
    def __init__(self):
        super(MyModelA, self).__init__()
        self.fc1 = nn.Linear(10, 2)
        
    def forward(self, x):
        x = self.fc1(x)
        return x
    

class MyModelB(nn.Module):
    def __init__(self):
        super(MyModelB, self).__init__()
        self.fc1 = nn.Linear(20, 2)
        
    def forward(self, x):
        x = self.fc1(x)
        return x


class MyEnsemble(nn.Module):
    def __init__(self, modelA, modelB):
        super(MyEnsemble, self).__init__()
        self.modelA = modelA
        self.modelB = modelB
        
    def forward(self, x):
        x1 = self.modelA(x)
        x2 = self.modelB(x1)
        return x2

# Create models and load state_dicts    
modelA = MyModelA()
modelB = MyModelB()
# Load state dicts
modelA.load_state_dict(torch.load(PATH))

model = MyEnsemble(modelA, modelB)
x = torch.randn(1, 10)
output = model(x)

基本上,我想加载预训练的 modelA 并在训练Ensemble模型时使其无法训练。
2个回答

8

一种简单的方法是detach想要保持不更新的模型的输出张量,从而使其不会向连接的模型反向传播梯度。在您的情况下,您可以在MyEnsemble模型的前向函数中与x1拼接之前简单地分离x2张量,以保持modelB的权重不变。

因此,新的前向函数应该像以下代码一样:

def forward(self, x1, x2):
        x1 = self.modelA(x1)
        x2 = self.modelB(x2)
        x = torch.cat((x1, x2.detach()), dim=1)  # Detaching x2, so modelB wont be updated
        x = self.classifier(F.relu(x))
        return x

2

您可以通过将requires_grad设置为false来冻结不想训练的模型所有参数。 像这样:

for param in model.parameters():
    param.requires_grad = False

这应该适合你的需求。
另一种方法是在你的训练循环中处理这个问题:
modelA = MyModelA()
modelB = MyModelB()

criterionB = nn.MSELoss()
optimizerB = torch.optim.Adam(modelB.parameters(), lr=0.001)

for epoch in range(epochs):
    for samples, targets in dataloader:
        optimizerB.zero_grad()

        x = modelA.train()(samples)
        predictions = modelB.train()(samples)
    
        loss = criterionB(predictions, targets)
        loss.backward()
        optimizerB.step()

所以你将modelA的输出传递给modelB,但你只优化modelB。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接