Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/144.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Pytorch 找不到导致“错误”的就地操作;RuntimeError:梯度计算所需的一个变量已被就地操作修改:“0”;_Pytorch_Autograd_Hessian Matrix - Fatal编程技术网

Pytorch 找不到导致“错误”的就地操作;RuntimeError:梯度计算所需的一个变量已被就地操作修改:“0”;

Pytorch 找不到导致“错误”的就地操作;RuntimeError:梯度计算所需的一个变量已被就地操作修改:“0”;,pytorch,autograd,hessian-matrix,Pytorch,Autograd,Hessian Matrix,我对PyTorch比较陌生,我试图从一篇学术论文中复制一个算法,该算法使用Hessian矩阵近似一个术语。我设置了一个玩具问题,这样我就可以比较完整Hessian的结果和近似值。我发现并一直在使用它来计算算法的完整Hessian部分 我得到了一个错误:“RuntimeError:梯度计算所需的一个变量被一个就地操作修改了。” 我已经浏览了简单的示例代码、文档和许多关于这个问题的论坛帖子,但找不到任何就地操作。任何帮助都将不胜感激 这是我的密码: import torch import torch

我对PyTorch比较陌生,我试图从一篇学术论文中复制一个算法,该算法使用Hessian矩阵近似一个术语。我设置了一个玩具问题,这样我就可以比较完整Hessian的结果和近似值。我发现并一直在使用它来计算算法的完整Hessian部分

我得到了一个错误:“RuntimeError:梯度计算所需的一个变量被一个就地操作修改了。”

我已经浏览了简单的示例代码、文档和许多关于这个问题的论坛帖子,但找不到任何就地操作。任何帮助都将不胜感激

这是我的密码:

import torch
import torch.autograd as autograd
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import numpy as np

torch.set_printoptions(precision=20, linewidth=180)

def jacobian(y, x, create_graph=False):
    jac = []
    flat_y = y.reshape(-1)     
    grad_y = torch.zeros_like(flat_y)     

    for i in range(len(flat_y)):         
        grad_y[i] = 1.
        grad_x, = torch.autograd.grad(flat_y, x, grad_y, retain_graph=True, create_graph=create_graph)
        jac.append(grad_x.reshape(x.shape))
        grad_y[i] = 0.
    return torch.stack(jac).reshape(y.shape + x.shape)           

def hessian(y, x):
    return jacobian(jacobian(y, x, create_graph=True), x)                                             

def f(x):                                                                                             
    return x * x

np.random.seed(435537698)

num_dims = 2
num_samples = 3

X = [np.random.uniform(size=num_dims) for i in range(num_samples)]
print('X: \n{}\n\n'.format(X))

mean = torch.Tensor(np.mean(X, axis=0))
mean.requires_grad = True
print('mean: \n{}\n\n'.format(mean))

cov = torch.Tensor(np.cov(X, rowvar=False))
print('cov: \n{}\n\n'.format(cov))

with autograd.detect_anomaly():
    hessian_matrices = hessian(f(mean), mean)
    print('hessian: \n{}\n\n'.format(hessian_matrices))
下面是堆栈跟踪的输出:

X: 
[array([0.81700949, 0.17141617]), array([0.53579366, 0.31141496]), array([0.49756485, 0.97495776])]


mean: 
tensor([0.61678934097290039062, 0.48592963814735412598], requires_grad=True)


cov: 
tensor([[ 0.03043144382536411285, -0.05357056483626365662],
        [-0.05357056483626365662,  0.18426130712032318115]])


---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-3-5a1c492d2873> in <module>()
     42 
     43 with autograd.detect_anomaly():
---> 44     hessian_matrices = hessian(f(mean), mean)
     45     print('hessian: \n{}\n\n'.format(hessian_matrices))

2 frames
<ipython-input-3-5a1c492d2873> in hessian(y, x)
     21 
     22 def hessian(y, x):
---> 23     return jacobian(jacobian(y, x, create_graph=True), x)
     24 
     25 def f(x):

<ipython-input-3-5a1c492d2873> in jacobian(y, x, create_graph)
     15     for i in range(len(flat_y)):
     16         grad_y[i] = 1.
---> 17         grad_x, = torch.autograd.grad(flat_y, x, grad_y, retain_graph=True, create_graph=create_graph)
     18         jac.append(grad_x.reshape(x.shape))
     19         grad_y[i] = 0.

/usr/local/lib/python3.6/dist-packages/torch/autograd/__init__.py in grad(outputs, inputs, grad_outputs, retain_graph, create_graph, only_inputs, allow_unused)
    155     return Variable._execution_engine.run_backward(
    156         outputs, grad_outputs, retain_graph, create_graph,
--> 157         inputs, allow_unused)
    158 
    159 

RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.FloatTensor [2]] is at version 4; expected version 3 instead. Hint: the backtrace further above shows the operation that failed to compute its gradient. The variable in question was changed in there or anywhere later. Good luck!
X:
[阵列([0.81700949,0.17141617])、阵列([0.53579366,0.31141496])、阵列([0.49756485,0.97495776])]
意思是:
张量([0.6167893409729062,0.48592963814735412598],需要_grad=True)
冠状病毒:
张量([[0.03043144382536411285,-0.05357056483626365662],
[-0.05357056483626365662,  0.18426130712032318115]])
---------------------------------------------------------------------------
运行时错误回溯(上次最近调用)
在()
42
43带自动标记。检测异常()
--->44 hessian_矩阵=hessian(f(平均值),平均值)
45打印('hessian:\n{}\n\n'.格式(hessian_矩阵))
2帧
黑森语(y,x)
21
22 def hessian(y,x):
--->23返回雅可比矩阵(雅可比矩阵(y,x,create_graph=True),x)
24
25 def f(x):
在雅可比矩阵中(y,x,创建_图)
15对于范围内的i(透镜(平面y)):
16 grad_y[i]=1。
--->17 grad\u x,=torch.autograd.grad(展平,x,grad\u y,保留图=真,创建图=创建图)
18 jac.追加(渐变x.整形(x.形状))
19 grad_y[i]=0。
/usr/local/lib/python3.6/dist packages/torch/autograd/_init_uuuuuuuuuuuuuuuu.py渐变(输出、输入、渐变输出、保留图、创建图、仅输入、允许未使用)
155返回变量。\u执行\u引擎。向后运行\u(
156个输出,渐变输出,保留图,创建图,
-->157输入,允许(未使用)
158
159
RuntimeError:梯度计算所需的一个变量已被就地操作修改:[torch.FloatTensor[2]]处于版本4;应该是版本3。提示:上面的回溯显示了无法计算其梯度的操作。所讨论的变量在那里或以后的任何地方发生了更改。祝你好运

我真诚地认为这是PyTorch中的一个bug,但在发布了一个bug之后,我从albanD那里得到了一个很好的答案。他还指出,这是可以用来提问的

问题的出现是因为我们一次又一次地遍历计算图。但我无法理解这里到底发生了什么

错误消息所指的就地编辑是显而易见的:
grad\u y[i]=1。
grad\u y[i]=0。
。在计算中反复执行
grad_y
是导致问题的原因。重新定义雅可比(…)如下对我很有用

定义雅可比矩阵(y,x,create_graph=False): jac=[] 平面y=y。重塑(-1) 对于范围内的i(len(flat_y)): grad_y=火炬。类零(平坦) grad_y[i]=1。 grad\u x,=torch.autograd.grad(展平,x,grad\u y,保留图=真,创建图=创建图) jac.append(渐变x重塑(x.shape)) 返回火炬。堆叠(jac)。重塑(y形+x形) 另一种可行的方法,但对我来说更像是黑魔法,就是保持雅可比(…)不变,而是重新定义
f(x)

def(x):
返回x*x*1

这也行

对于未来的读者来说,标题中提到的运行时错误可能会出现在比原作者更一般的环境中,例如,当在张量切片中移动和/或从列表理解中操作张量时,因为这正是我来到这里的背景(我的搜索引擎返回运行时错误的第一个链接)

为了防止这种运行时错误并确保梯度可以平滑流动,在上面的链接中提到了对我最有用的原理(但在解决方案消息中没有提到),它包括在移动它们(或其中的一些片段)时使用
torch.Tensor的
.clone()
方法

例如:

some_container[slice_indices] = original_tensor[slice_indices].clone()
其中,只有
原始\u tensor
具有
要求\u grad=True
,随后(可能成批)操作将在tensor
某些容器上执行

或:


似乎在C代码中发生了一些神奇的事情,
torch.autograd.grad
…将
f(x)
的定义从
x*x
更改为
x*x*torch
解决了这个问题。我不知道为什么…在我看来似乎是PyTorch中的一个bug…这确实让它神奇地发挥了作用。如果有人能解释一下原因,那就太好了。谢谢你的指导@Yunnosch,我已经试着做了更彻底的解释,并强调了我打算以何种方式添加到上一个sol中我希望它是合适的?如果我还漏掉一点,请告诉我…现在看起来更像是一个答案。我对“加宽”并不完全满意实际问题的范围。另一方面,来这里寻求标题的人可能会在这篇文章中找到帮助。我不知道Q/a对应该是什么样的,但我现在接受这一点作为答案。(严格来说,这不是我的技术领域,所以我不做判断,因为我可能太远了…)玩得开心。
some_container = [
    tensor.clone() 
    for tensor in some_tensor_list if some_condition_fn(tensor)
]
new_composed_tensor = torch.cat(some_container, dim=0)