深度学习自然语言处理实战
上QQ阅读APP看书,第一时间看更新

2.3 PyTorch自动求梯度

深度学习的过程中,在对代价函数(loss)进行优化时需要计算梯度(gradient),Py-Torch提供的autograd(自动求梯度)包能够根据输入的数据和前向传播过程自动构建计算图,并执行反向传播。

2.3.1 基本概念

在PyTorch中,torch.Tensor是autograd包的核心类,如果将其属性.requires_ grad设置为True,它将开始追踪对Tensor的所有操作,即可以利用链式法则(Chain Rule)进行梯度传播(Gradient Propagation)。完成计算后,可以调用.backward()来自动完成所有梯度的计算。这个Tensor的梯度将累积到.grad属性中。例如,如果x是一个Tensor,x.requires_grad=True,然后x.grad是另一个Tensor,x.grad将累计x的所有的梯度。

如果在后期需要停止对Tensor历史记录的追踪,可以调用.detach()函数,它会将Tensor与其计算的历史记录做分离,并防止将来的计算被继续追踪,此时,梯度就不会进行传播了。如果需要设置一些操作代码使其不被跟踪,可以用with torch.no_grad()将具体的代码块包装起来。这种方法在评估(Evaluate)模型时用处很大,这是因为在评估模型的阶段不需要用到可训练参数(require_grad = True)部分的梯度。

Function也是autograd包中很重要的一个类。通过将Tensor和Function进行连接可以构建一个保存整个计算过程历史信息的有向无环图(Directed Acyclic Graph,DAG)。每个Tensor都会有一个.grad_fn属性,这个属性会保存创建该Tensor的Function,即说明这个Tensor是否由某些运算得到。如果是用户自己创建的Tensor,那么.grad_fn属性将是None。

2.3.2 Tensor样例

创建一个Tensor,通过设置requires_grad = True来跟踪与它相关的计算。

输出的结果为

对Tensor x做加法运算

输出的结果为

在这里可以看到,Tensor x是直接创建的(又可以称为叶子节点),因此x没有grad fn;Tensor y是通过加法创建出来的,因此y有一个名为<AddBackward0>的grad_fn。

对Tensor y做更复杂的运算,如下所示:

输出的结果为

.requires_grad_(...)会改变张量的requires_grad标记。如果没有提供相应的参数,输入的标记默认为False。

输出的结果为

2.3.3 梯度计算

我们根据上述内容建立一个稍微复杂的网络来进行梯度计算。

然后进行反向传播

输出的结果为

下面,我们来计算一个简单的雅可比的梯度。

输入的结果为

现在在这种情况下,y不再是一个标量。torch.autograd不能直接计算整个雅可比,但是如果我们只想要雅可比向量积,只需要简单地把向量传递给backward作为参数。

输出的结果为

可以通过将代码包裹在with torch.no_grad()中,来停止对从跟踪历史中的.requires_grad=True的张量自动求导。

输出的结果为