1.3_Pytorch自动求梯度原理介绍


文档摘要

Pytorch自动求梯度原理介绍 在深度学习模型训练中,在完成一次前向推理后,我们需要使用反向传播,依据每个参数的梯度,调整参数的取值来让模型往正确的方向前进。 PyTorch提供的autograd能力能够帮我们实现这一过程,极大的简化了模型训练的难度。其可以根据输入和前向传播过程自动构建计算图,并执行反向传播。 本文将简单介绍pytorch中与自动求导相关的内容。 反向传播的一般流程 pytorch为我们做了很好的封装,反向传播的实现细节已经被极大的隐藏,无论模型多么复杂,只需简单的几行代码即可完成。

Pytorch自动求梯度原理介绍

在深度学习模型训练中,在完成一次前向推理后,我们需要使用反向传播,依据每个参数的梯度,调整参数的取值来让模型往正确的方向前进。

PyTorch提供的autograd能力能够帮我们实现这一过程,极大的简化了模型训练的难度。其可以根据输入和前向传播过程自动构建计算图,并执行反向传播。

本文将简单介绍pytorch中与自动求导相关的内容。

1. 反向传播的一般流程

pytorch为我们做了很好的封装,反向传播的实现细节已经被极大的隐藏,无论模型多么复杂,只需简单的几行代码即可完成。

在pytorch中进行反向传播并更新模型参数的一般流程如下:

首先让我们导入两个包,torchtorchvision

然后构建一个经典的图像分类模型resnet18

import torch, torchvision model = torchvision.models.resnet18(pretrained=False)

如果你不了解这个模型,大可不必担心,后面的章节中我们会有进一步介绍。这里我们只需要知道,这个模型是一个图像分类模型,输入一个shape为(1,3,height,width)的张量,代表一张图像,其可以输出一个shape为(1,1000)的张量,代表预测的类别结果。

这里我们随机一个shape为(1,3,64,64)的张量data,作为模型输入。

然后随机一个shape为(1,1000)的张量label,假设其为数据data对应的标签,即模型应该预测出的结果。

data = torch.rand(1, 3, 64, 64) labels = torch.rand(1, 1000)

下一步,我们运行前向传播的过程,来获得模型对于这个输入data的预测结果

prediction = model(data) # forward pass

随后,我们计算预测结果prediction和标准结果label之间的差异,记为loss

通过调用backward()函数,便触发了反向传播的求导过程,autograd就会计算模型中每个参数的梯度,并将其存储在每个参数的.grad属性之中。

loss = (prediction - labels).sum() loss.backward() # backward pass

然后,我们加载一个优化器,这里我们使用SGD算法并设置相关参数lr和momentum,并将模型的所有参数注册到优化器中。

优化器对应着,当我们通过反向传播计算出每个参数关于loss的梯度之后,如何依据梯度值更新这些参数,来让模型表现更好的方法。这里我们使用的优化算法是SGD,即梯度下降算法,是最简单且常用的优化算法。

optim = torch.optim.SGD(model.parameters(), lr=1e-2, momentum=0.9)

最后,我们调用.step()来完成参数更新的过程,优化器根据每个参数的梯度(保存在.grad中)以及设定的优化算法,调整这些参数。

optim.step() #gradient descent

到这里,你就知道如何通过反向传播自动求导以及设置优化器来训练你的模型了,所有pytorch模型的训练均在这个简单的框架下进行。

后面,我们简单的来实验下一些自动求导相关的内容细节,如果你不感兴趣可以跳过,不会影响本教程后续任何内容的理解。

2. 自动求导的简单实验

这里我们进行一个简单的小实验,通过敲一些简单的命令,来对pytorch提供的自动求导功能有一个更好的认知。

首先,pytorch的自动求导是基于Tensor这样一个基础数据结构进行的。

一方面,它类似于numpy的ndarray,用户可以对Tensor进行各种数学运算,这个我们在上一小节中已经介绍过;

另一方面,当设置.requires_grad = True之后,pytorch就会在反向传播时,计算它的梯度。

>>> import torch >>> x1 = torch.ones((2,2)) >>> x1 tensor([[1., 1.], [1., 1.]]) >>> x2 = torch.ones((2,2), requires_grad=True) >>> x2 tensor([[1., 1.], [1., 1.]], requires_grad=True)

可以看到,.requires_grad默认是False。

此外,当设置.requires_grad = True之后,在其上进行的各种操作就会被记录下来,pytorch将开始追踪在其上的所有操作,从而利用链式法则进行梯度传播。

这里我们定义一个基于x2运算出的变量y2=x+2,可以看到,y2自动就被记录了梯度

>>> y2 = x2 + 1 >>> y2.requires_grad True

完成计算后,可以调用.backward()来自动完成所有梯度计算。

为了更加清晰,这里我们重新初始化两个仅含一个数的Tensorab,并定义y如下:

y = a^2 + 2b^3
>>> a = torch.tensor([2.], requires_grad=True) >>> b = torch.tensor([4.], requires_grad=True) >>> y = a**2 + 2*b**3

然后,调用y的.backward()函数来进行梯度计算

>>> y.backward() >>> a.grad tensor([4.]) >>> b.grad tensor([96.])

可以看到:

a.grad = 2a = 4

b.grad = 6b^2 = 96

符合预期,pytorch自动求导的结果是准确的。

如果某个张量不想要被继续追踪,可以调用.detach()将其从追踪记录中分离出来,可以防止将来的计算被追踪,这样梯度就传不过去了。

此外,还可以用with torch.no_grad()将不想被追踪的操作代码块包裹起来,这种方法在评估模型的时候很常用,因为在评估模型时,我们并不需要计算可训练参数的梯度。

贡献者

作者: 星尘,安晟

本文内容参考自(可作为补充材料阅读):
Dive-into-DL-Pytorch_2.3-autograd
A Gentle Introduction to torch.autograd


作者与出处
原作者: Datawhale
来源:Datawhale
许可证:GPL-3.0
整理: 灏天文库整理
由灏天文库结构化整理,提供目录导航、全文检索与在线阅读,便于系统化学习
发布者: 作者: Datawhale 转发
评论区 (0)
U