Pytorch问题:autograd与backward()

先给链接:

https://pytorch.org/tutorials/beginner/blitz/autograd_tutorial.html#sphx-glr-beginner-blitz-autograd-tutorial-py
https://linlinzhao.com/tech/2017/10/24/understanding-backward()-in-PyTorch.html

关于backward标量的问题

在pytorch的官方教程中,有这么一段

import torch
x = torch.randn(3, requires_grad=True)
y = x * 2
while y.data.norm() < 1000:
    y = y * 2
print(y)

# Now in this case y is no longer a scalar. torch.autograd could not compute the full 
# Jacobian directly, but if we just want the Jacobian-vector product, simply pass the
# vector to backward as argument:
v = torch.tensor([0.1, 1.0, 0.0001], dtype=torch.float)
y.backward(v)
print(x.grad)

其中大意是,如果不使用v这个向量,直接使用y.backward()就会报错,即:如果在这里运行y.backward(),会得到这样一个报错:RuntimeError: grad can be implicitly created only for scalar outputs。另外,我想说的是,这里y不是一个固定的运算,因为while y.data.norm() < 1000可能需要3次运算,也可能需要5次运算。
这里v相当于各个标量(共有3个标量,构成一个向量)的系数,如果要直接对所有标量进行backward,全部改成1.0即可。

先看一下标量的问题,当结果out是标量时,backward()是不报错的,

x = torch.randn(3, requires_grad=True)
y = x * 2
z = y * y * 3
out = z.mean()
print(z, out)
out.backward()

否则,像如下代码,z不是标量,会报错,

x = torch.randn(3, requires_grad=True)
y = x * 2
z = y * y * 3
z.backward() #RuntimeError: grad can be implicitly created only for scalar outputs

关于detach,retain_graph是作什么的

参考了贴子(https://blog.csdn.net/douhaoexia/article/details/78821428)的解释,如下

detach()

如果 x 为中间输出,y = x.detach 表示创建一个与 x 相同,但requires_grad==False 的tensor, 实际上就是把y 以前的计算图 grad_fn 都消除,y自然也就成了叶节点。原先反向传播时,回传到x时还会继续,而现在回到y处后,就结束了,不继续回传求到了。另外值得注意, x和y指向同一个Tensor ,即 x.data 。而detach_() 表示不创建新变量,而是直接修改 x 本身。

retain_graph()

如果retain_graph=true,就会每次运行时重新生成图。也就是说,每次 backward() 时,默认会把整个计算图free掉。一般情况下是每次迭代,只需一次 forward() 和一次 backward() , 前向运算forward() 和反向传播backward()是成对存在的,一般一次backward()也是够用的。但是不排除,由于自定义loss等的复杂性,需要一次forward(),多个不同loss的backward()来累积同一个网络的grad来更新参数。于是,若在当前backward()后,不执行forward() 而可以执行另一个backward(),需要在当前backward()时,指定保留计算图,即backward(retain_graph)。
 

猜你喜欢

转载自blog.csdn.net/tanmx219/article/details/86141024