【问题标题】:Modifying a pytorch tensor and then getting the gradient lets the gradient not work修改一个pytorch张量然后获取梯度让梯度不起作用
【发布时间】:2018-10-29 18:44:01
【问题描述】:

我是 pytorch 的初学者,我面临以下问题:

当我得到以下张量的梯度时(请注意,我以某种方式使用了一些变量 x,如下所示),我得到了梯度:

import torch
myTensor = torch.randn(2, 2,requires_grad=True)
with torch.enable_grad():
    x=myTensor.sum() *10
x.backward()
print(myTensor.grad)

现在,如果我尝试修改 myTensor 的元素,则会收到 leaf variable has been moved into the graph interior 的错误。请参阅此代码:

import torch
myTensor = torch.randn(2, 2,requires_grad=True)
myTensor[0,0]*=5
with torch.enable_grad():
    x=myTensor.sum() *10
x.backward()
print(myTensor.grad)

我后面的代码有什么问题?我该如何纠正?

任何帮助将不胜感激。非常感谢!

【问题讨论】:

  • 非常感谢。我刚刚添加了一条评论,表明您的答案效果很好。再次感谢!在另一个相关说明中,您能否查看一下我最近发布但尚未收到任何回复的相关内容?:stackoverflow.com/questions/53507346/…

标签: python pytorch gradient


【解决方案1】:

这里的问题是,这条线代表了一个就地操作:

myTensor[0,0]*=5

PyTorch 或更准确地说是 autograd 在处理 in-place 操作方面并不是很好,尤其是在那些带有 requires_grad 的张量上标志设置为True

你也可以看这里:
https://pytorch.org/docs/stable/notes/autograd.html#in-place-operations-with-autograd

一般情况下,您应该尽可能避免 就地 操作,在某些情况下它可以工作,但您应该始终避免对您的张量进行 就地 操作将requires_grad 设置为True

不幸的是,没有多少 pytorch 函数可以帮助解决这个问题。因此,在这种情况下,您必须使用辅助张量来避免 in-place 操作:

代码:

import torch

myTensor = torch.randn(2, 2,requires_grad=True)
helper_tensor = torch.ones(2, 2)
helper_tensor[0, 0] = 5
new_myTensor = myTensor * helper_tensor # new tensor, out-of-place operation
with torch.enable_grad():
    x=new_myTensor.sum() *10 # of course you need to use the new tensor
x.backward()                 # for further calculation and backward
print(myTensor.grad)

输出:

tensor([[50., 10.],
        [10., 10.]])

不幸的是,这不是很好,如果有更好或更好的解决方案,我将不胜感激。
但据我所知,在当前版本 (0.4.1) 中,对于具有梯度的张量,您将不得不使用这种解决方法。 requires_grad=True

希望未来的版本会有更好的解决方案。


顺便说一句。如果你稍后激活渐变,你会发现它工作得很好:

import torch
myTensor = torch.randn(2, 2,requires_grad=False) # no gradient so far
myTensor[0,0]*=5                                 # in-place op not included in gradient
myTensor.requires_grad = True                    # activate gradient here
with torch.enable_grad():
    x=myTensor.sum() *10
x.backward()                                     # no problem here
print(myTensor.grad)

但这当然会产生不同的结果:

tensor([[10., 10.],
        [10., 10.]])

希望这会有所帮助!

【讨论】:

  • 效果很好!非常感谢您非常清晰和正确的回答!
  • 完成,投票并接受,非常感谢:-)。是的,希望你能看到另一个。非常感谢!
猜你喜欢
  • 2019-04-12
  • 1970-01-01
  • 2016-08-20
  • 2021-06-08
  • 1970-01-01
  • 2020-11-04
  • 2020-02-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多