第二章 Pytorch基础 Chapter 2-5 Tensor与Autograd
torch.autograd 包就是用于自动求导的。
Autograd包为张量上所有的操作提供了自动求导功能,而torch.Tensor和torch.Function为Autograd的两个核心类,它们相互连接并生成一个有向非循环图。
2.5.1 自动求导要点
PyTorch 采用计算图的形式,进行计算组织,该计算图为动态图,且在每一次前向传播时,将重新构建;该计算图为有向无环图。
叶子节点:由用户创建的,不依赖其它变量的变量
- 创建叶子节点的时候
Tensor
时,使用requires_grad
参数指定是否记录对该量的操作,以便之后利用backward()
方法进行梯度求解。该参数默认为False
,如果需要对其求导,需要设置为True
,然后与之有关的节点会自动变成True
。 - 可利用
.detach()
或with torch.no_grad()
包裹代码块的方式来阻止autograd
去跟踪那些标记为.requires_grad=True
的张量的历史记录,这点在评估模型,测试模型阶段经常用到。 - 反向传播过程的中间缓存会被清空,如果需要多次反向传播,需要指定
backward
的中间参数retain_graph=True
,多次反向传播过程中,梯度是累加的。 - 非叶子节点的梯度
backward
调用后即被清空。
2.5.2 计算图
计算图是一种有向无环图,用图形的方式表达算子和变量之间的关系。
对于表达式
y
=
w
x
+
b
y=wx+b
y=wx+b, x
, w
,b
为叶子节点,z
为根节点,mul
和add
为算子,这些变量和算子就构成了一个完整的计算过程(前向传播过程)。
计算图的目标是更新各叶子节点的梯度,根据复合函数导数的链式法则:
∂
z
∂
x
=
∂
z
∂
y
∂
y
∂
x
=
w
∂
z
∂
w
=
∂
z
∂
y
∂
y
∂
w
=
x
∂
z
∂
b
=
1
\frac{\partial z}{\partial x} = \frac{\partial z}{\partial y}\frac{\partial y}{\partial x}=w \\ \frac{\partial z}{\partial w} = \frac{\partial z}{\partial y}\frac{\partial y}{\partial w}=x \\ \frac{\partial z}{\partial b} = 1
∂x∂z=∂y∂z∂x∂y=w∂w∂z=∂y∂z∂w∂y=x∂b∂z=1
在反向传播过程中,autograd
沿着上图,从当前根节点z
反向溯源,计算所有叶子节点的梯度,其梯度值将累加到grad
属性中。
对非叶子节点的计算操作记录在gradf_fn
属性中,叶子节点的grad_gn
值为None
。
2.5.3 标量反向传播
2.5.4 非标量反向传播
目标张量一般是标量,如经常使用的损失值LOSS
,一般都是一个标量。
PyTorch 有个简单的规定:不让张量对张量求导,只允许标量对张量求导,因此,如果目标张量对一个非标量调用backward()
,则需要传入一个gradient
参数,该参数也为张量,而且需要与调用backward()
的张量保持形状相同。