pytorch 关于在torch.no_grad()中使用.grad的问题

bnl4lu3b  于 2023-10-20  发布在  其他
关注(0)|答案(2)|浏览(187)

我写了一些小例子来理解torch.no_grad()是如何工作的:

# example 1
import torch
a = torch.randn(10, 5, requires_grad = True)
z = a * 3
l = z - 0.5
l.sum().backward()
with torch.no_grad():
  a -= a.grad
  print(a.requires_grad)
# True

因此,with torch.no_grad()内部的a -= a.grad将保持a.requires_grad= True

# example2
import torch
a = torch.randn(10, 5, requires_grad = True)
z = a * 3
l = z - 0.5
l.sum().backward()
with torch.no_grad():
  a = a - a.grad
  print(a.requires_grad)
# False

但是,with torch.no_grad()内部的a -= 1将设置.requires_grad= False

# example3
import torch
a = torch.randn(10, 5, requires_grad = True)
z = a * 3
l = z - 0.5
l.sum().backward()
a -= a.grad
print(a.requires_grad)
# RuntimeError: a leaf Variable that requires grad is being used in an in-place operation.

没有with torch.no_grad()a -= a.grad将抛出RuntimeError(但a -= 1不会)
我无法解释上述结果。有人能给我指个方向吗?多谢了!

bxgwgixi

bxgwgixi1#

我认为上面的答案没有明确解释这三个案例。

案例一

a -= a.grad是一个就地操作,所以它不会改变a的属性require_grad。因此a.require = True

案例二

a = a - a.grad不是就地操作,因此它在内存空间中创建一个新的Tensor对象。由于在无grad模式下,a.require = False

案例三

你不能在no grad模式外用require grad = True改变叶Tensor。
参见discuss
我也试试下面的代码

import torch
a = torch.tensor([1.1], requires_grad=True)
b = a ** 2
b.backward()
a -= 1

它会抛出相同的运行时错误!
希望我的回答能对你有所帮助

hrysbysz

hrysbysz2#

这个a.grad是None,并且在第一次调用backward()时成为一个Tensor。
然后grad属性将包含计算的梯度,未来对backward()的调用将累积(添加)梯度。
如果你使用with torch.no_grad():,那么PyTorch autograd引擎被禁用,所以你不会有错误。
requires_grad = True是记录Tensor梯度的指示器。
你在最后一个例子中得到的错误是告诉你不能使用a.grad进行就地操作,但你可以使用a=a-a.grad来进行这个例子:

# example3
import torch
a = torch.randn(10, 5, requires_grad = True)
z = a * 3
l = z - 0.5
l.sum().backward()
a = a -a.grad
print(a.grad)
print(a.requires_grad)

输出:

None
True

/usr/local/lib/python3.7/dist-packages/torch/_tensor.py:1013: UserWarning: The .grad attribute of a Tensor that is not a leaf Tensor is being accessed. Its .grad attribute won't be populated during autograd.backward(). If you indeed want the .grad field to be populated for a non-leaf Tensor, use .retain_grad() on the non-leaf Tensor. If you access the non-leaf Tensor by mistake, make sure you access the leaf Tensor instead. See github.com/pytorch/pytorch/pull/30531 for more informations. (Triggered internally at  aten/src/ATen/core/TensorBody.h:417.)
  return self._grad

相关问题