我写了一些小例子来理解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
不会)
我无法解释上述结果。有人能给我指个方向吗?多谢了!
2条答案
按热度按时间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
我也试试下面的代码
它会抛出相同的运行时错误!
希望我的回答能对你有所帮助
hrysbysz2#
这个
a.grad
是None,并且在第一次调用backward()
时成为一个Tensor。然后
grad
属性将包含计算的梯度,未来对backward()
的调用将累积(添加)梯度。如果你使用
with torch.no_grad():
,那么PyTorch autograd引擎被禁用,所以你不会有错误。requires_grad = True
是记录Tensor梯度的指示器。你在最后一个例子中得到的错误是告诉你不能使用
a.grad
进行就地操作,但你可以使用a=a-a.grad
来进行这个例子:输出: