Pytorch can';t查找就地操作:梯度计算所需的变量之一已被就地操作修改

Pytorch can';t查找就地操作:梯度计算所需的变量之一已被就地操作修改,pytorch,backpropagation,Pytorch,Backpropagation,我试图计算网络的雅可比矩阵上的损失(即,执行双反投影),我得到以下错误: RuntimeError:梯度计算所需的一个变量已被就地操作修改 我在代码中找不到就地操作,所以我不知道要修复哪一行 *错误发生在最后一行: loss3.backward() grad\u输出。零(到位,grad\u输出[:,i-1]=0。就地表示“修改张量,而不是返回一个新的张量,该张量已应用修改”。一个未到位的示例解决方案是。用于将第一列归零的示例 import torch t = torch.randn(3, 3)

我试图计算网络的雅可比矩阵上的损失(即,执行双反投影),我得到以下错误: RuntimeError:梯度计算所需的一个变量已被就地操作修改

我在代码中找不到就地操作,所以我不知道要修复哪一行

*错误发生在最后一行: loss3.backward()

grad\u输出。零(
到位,
grad\u输出[:,i-1]=0
。就地表示“修改张量,而不是返回一个新的张量,该张量已应用修改”。一个未到位的示例解决方案是。用于将第一列归零的示例

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
如何保留它以前的值,而
归零的
具有您想要的值。

谢谢! 我将grad_输出中存在问题的就地操作代码替换为:

            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()

您可以使用
set\u detect\u normal
autograd
软件包来准确地查找导致错误的行


下面是使用上述函数描述相同问题和解决方案的示例

grad\u output.zero\u()
似乎是一个就地操作。您可能在
self.model
grad\u output.zero\u()
中有就地操作。在PyTorch中,就地操作以下划线结束。我想你想写'grad_output.zero_grad(),在我将新列(对应于我希望计算梯度的输出)设置为1之前,我需要将grad_output设置为0。因此,我将grad_output.zero_()更改为grad_output[:,I-1]=0,但没有任何帮助。实际上,我上面描述的是用另一个替换一个就地操作。请注意,
grad_output_curr[:,I]=1
行仍然是就地操作,可能(或可能不会)导致进一步的问题。
            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()