基本数据Tensor可以保证完成前向传播,想要完成神经网络的训练,接下来还需要进行反向传播与梯度更新,而PyTorch提供了自动求导机制,autograd,将前向传播的计算记录成计算图,自动完成求导
在PyTorch 0.4 版本之前,Tensor仅仅是对多维数组到的抽象,使用自动求导机制需要将Tensor封装成torch.autograd.Variable类型,才能构建计算图。PyTorch 0.4 版本则将Tensor与Variable进行了整合,以前Variable的使用情景都可以直接使用Tensor,变得更加简单实用。
- Tensor的自动求导:Autograd
自动求导机制记录了Tensor的操作,以便自动求导与反向传播。可以通过requires_grad参数来创建支持自动求导机制的Tensor
import torch
a = torch.randn(2,2,requires_grad=True)
requires_grad参数表示是否需要对该Tensor进行求导,默认为False;设置为True则需要求导,并且依赖于该Tensor的之后的所有节点都需要求导,在PyTorch 4.0 对于Tensor的自动求导中,volatile参数已经被其他torch.no_grad()等函数取代了。torch.no_grad() 是一个上下文管理器,被该语句包含起来的部分将不会计算梯度。torch.no_grad()详解
Tensor有两个重要的属性,分别记录了该Tensor的梯度与经历的操作
- grad:该Tensor对应的梯度,类型为Tensor,并与Tensor同维度
- grad_fn:指向function对象,即该Tensor经历过了什么样的操作,用反向传播的梯度计算,如果该Tensor由用户自己创建,则该 grad_fn为None
注意:早些版本使用.data属性来获取数据,PyTorch 0.4 中建议使用Tensor.detach()函数,因为.data属性在某些情况下不安全,原因在于对.data生成的数据进行修改不会被autograd追踪。Tensor.detach()函数生成的数据默认requires_grad为False
detach()、detach_()、.data区别
-
计算图
计算图是PyTorch对于神经网络的具体表现形式,包括每一个数据Tensor及Tensor之间的函数function。再此我们以z = wx + b为例,通常在神经网络中,x为输入,w与b为网络需要学习的参数,z为输出,在这一层,计算图构建方法如下图:
在上图中,x、w和b都是用户自己创建的,因此都为叶节点,wx首先经过乘法算子产生中间节点y,然后与b经过加法算法产生最终输出z,并作为根节点
Autograd的基本原理是随着每一步Tensor的计算操作,逐渐生成计算图,并将操作的function记录在Tensor的grad_fn中。在前向计算完后,只需对根节点进行backward函数操作,即可从当前根节点自动进行反向传播与梯度计算,从而得到每一个叶子节点的梯度,梯度计算遵循链式求导法则
-
Autograd注意事项
PyTorch的Autograd机制使得其可以灵活地进行前向传播与梯度计算,在实际应用中需要注意以下3点:
1. 动态图特性:PyTorch建立的计算图是动态的,这也是PyTorch的一大特点。动态图是指程序运行时,每次前向传播时从头开始构建计算图,这样不同的前向传播就可以有不同的计算图,也可以在前项传播时插入各种Python控制语句,不需要事先把所有的图都构建出来,并且可以很方便地查看中间过程变量
2. backward()函数还有一个需要传入的参数grad_variabels,其代表了根节点的导数,也可以看做根节点各部分的权重系数。因为PyTorch不允许Tensor对Tensor求导,求导时都是标量对于Tensor进行求导,因此,如果根节点是向量,则应配以对应大小的权重,并求和得到标量,再反传。如果根节点的值是标量,则该参数可以省略,默认为1
3. 当有多个输出需要同时进行梯度反传时,需要将retain_graph设置为True,从而保证在计算多个输出的梯度时互不影响