pytorch 找不到就地操作:梯度计算所需的变量之一已被就地操作修改

mzmfm0qo  于 2023-01-26  发布在  其他
关注(0)|答案(5)|浏览(176)

我试图计算网络雅可比行列式上的损耗(即执行双支撑),但得到以下错误:运行时错误:梯度计算所需的变量之一已被就地操作修改
我在代码中找不到inplace操作,所以我不知道要修复哪一行。

  • 错误发生在最后一行:向后损失
inputs_reg = Variable(data, requires_grad=True)
            output_reg = self.model.forward(inputs_reg)

            num_classes = output.size()[1]
            jacobian_list = []
            grad_output = torch.zeros(*output_reg.size())

            if inputs_reg.is_cuda:
                grad_output = grad_output.cuda()
                jacobian_list = jacobian.cuda()

            for i in range(10):

                zero_gradients(inputs_reg)
                grad_output.zero_()
                grad_output[:, i] = 1
                jacobian_list.append(torch.autograd.grad(outputs=output_reg,
                                                  inputs=inputs_reg,
                                                  grad_outputs=grad_output,
                                                  only_inputs=True,
                                                  retain_graph=True,
                                                  create_graph=True)[0])

            jacobian = torch.stack(jacobian_list, dim=0)
            loss3 = jacobian.norm()
            loss3.backward()
ss2ws0br

ss2ws0br1#

您可以使用autograd包中提供的set_detect_anomaly函数来准确地查找哪一行导致了错误。
这里是link,它描述了相同的问题和使用上述函数的解决方案。

ipakzgxi

ipakzgxi2#

grad_output.zero_()是原地的,grad_output[:, i-1] = 0也是原地的。原地意味着“修改Tensor而不是返回应用了修改的新Tensor”。非原地的示例解是torch.where。示例用于将第1列清零

import torch
t = torch.randn(3, 3)
ixs = torch.arange(3, dtype=torch.int64)
zeroed = torch.where(ixs[None, :] == 1, torch.tensor(0.), t)

zeroed
tensor([[-0.6616,  0.0000,  0.7329],
        [ 0.8961,  0.0000, -0.1978],
        [ 0.0798,  0.0000, -1.2041]])

t
tensor([[-0.6616, -1.6422,  0.7329],
        [ 0.8961, -0.9623, -0.1978],
        [ 0.0798, -0.7733, -1.2041]])

注意t如何保留它以前的值,zeroed如何具有您想要的值。

uoifb46i

uoifb46i3#

谢谢!我将grad_output中inplace操作的问题代码替换为:

inputs_reg = Variable(data, requires_grad=True)
            output_reg = self.model.forward(inputs_reg)
            num_classes = output.size()[1]

            jacobian_list = []
            grad_output = torch.zeros(*output_reg.size())

            if inputs_reg.is_cuda:
                grad_output = grad_output.cuda()

            for i in range(5):
                zero_gradients(inputs_reg)

                grad_output_curr = grad_output.clone()
                grad_output_curr[:, i] = 1
                jacobian_list.append(torch.autograd.grad(outputs=output_reg,
                                                         inputs=inputs_reg,
                                                         grad_outputs=grad_output_curr,
                                                         only_inputs=True,
                                                         retain_graph=True,
                                                         create_graph=True)[0])

            jacobian = torch.stack(jacobian_list, dim=0)
            loss3 = jacobian.norm()
            loss3.backward()
8zzbczxx

8zzbczxx4#

我希望你的问题得到解决。我遇到过这个问题,解决方法像使用函数clone()对我不起作用。但是当我安装pytorch1.4版本时,它解决了。
我认为这个问题是step()函数中的一个bug,奇怪的是这个bug是在pytorch 1.5版本中出现的,而在v1.4中却没有。
你可以在link中看到pytorch的所有发布版本。

sbtkgmzw

sbtkgmzw5#

我在做PPO(Proximal Policy Optimization)的时候遇到了这个错误,我通过定义目标网络和主网络来解决这个问题,目标网络在开始的时候和主网络有相同的参数值,在训练的时候,目标网络的参数每隔一个固定的时间步长就被赋给主网络,具体可以在代码中找到:https://github.com/nikhilbarhate99/PPO-PyTorch/blob/master/PPO_colab.ipynb

相关问题