如何训练一个模型,损失由pytorch中的另一个模型计算?

How to train a model with loss calculated by another model in pytorch?

有两个模型A和B,模型A输出一个城市所有站点的自行车投放计划,模型B以此计划为输入,给出每个站点的评价。

现在模型B已经预训练好了,我想用模型B给出的评价作为loss来优化模型A的参数

这里是示例代码。

A = modelA()
B = modelB()

optimizer = torch.optim.Adam(A.parameters())

def my_loss(deploy):
  shape = deploy.size()
  state = torch.zeros((shape[0], shape[1], 2 + shape[1]), dtype=torch.long)

  # Notice: this step will copy deploy
  state[:, :, 2:] = torch.reshape(deploy, (shape[0], 1, shape[1]))
  state[:, :, 0] = torch.arange(0, shape[1])

  state = torch.reshape(state, (-1, 2 + shape[1]))
  eval = B(state)
  eval = torch.reshape(eval, (shape[0], shape[1]))

  return torch.mean(eval)

# Train model A
for epoch in range(EPOCHS):
  for batch_idx, (x, useless_y) in enumerate(dataloader):
    optimizer.zero_gard()
    pred = A(x)
    loss = my_loss(pred)
    loss.backward()
    optimizer.step()

但实际上,在训练过程中,没有任何反应,模型A的参数并没有更新。 我也试过了

optimizer = torch.optim.Adam([{'params': A.parameters()}, {'params': B.parameters(), 'lr':0}])

也没有任何反应。

有什么想法吗?

A的参数没有update是因为loss,我的my_loss的结果没有附在计算图上, 到模型 A 的输出。如果你看一下你的实现,情况显然是这样的:

    state = torch.reshape(state_tensors, (-1, 2 + shape[1]))
    eval = B(state)
    eval = torch.reshape(eval, (shape[0], shape[1]))

变量 state 是从 state_tensors 定义的,而您的示例中没有定义它,因此它要么是拼写错误,要么是从 state 定义的。无论如何,生成的张量 my_loss 输出应该附加一个 grad_fn。请确保是这种情况。这里的最后一个操作是一个平均值,所以你必须有这样的东西:

>>> my_loss(loss)
tensor(0.7742, grad_fn=<MeanBackward0>)

修复此问题后,您的梯度应该能够反向传播到模型 A 的参数。

计算图在state处被截断,因此损失不会反向传播到A。

尝试;

state = torch.zeros((shape[0], shape[1], 2 + shape[1]), dtype=torch.long)
->
state = torch.zeros((shape[0], shape[1], 2 + shape[1]), requires_grad=True) # add requires_grad=True, dtype=torch.long may throw error

但是,我仍然认为它不适用于您的代码。 可选建议;

  • 我认为state_tensors没有定义。
  • 就地操作state[:, :, 2:] = 可能不好。 (在我的例子中,这个抛出错误)要复制张量,.expand().repeat(), 并扩展 dim,.unsqueeze() 可能有助于避免这种情况。