【教程|60分钟快速入门】02-Autograd:自动微分
文章目录
原文地址:https://pytorch.org/tutorials/beginner/blitz/autograd_tutorial.html
PyTorch:1.5.0
autograd
库是使用 PyTorch 构建神经网络的核心。首先让我们简要地浏览一下,之后我们将会训练第一个神经网络。
autograd
库提供了 Tensors 上自动微分的所有操作,它是一个按照定义运行的框架,这意味着通过你的运行代码来定义反向传播,但是每一次迭代却可以是不相同的。
让我们通过示例来了解一些简单的术语。
1. 张量(Tensor)
torch.Tensor
是 PyTorch 中的核心类,如果你设置 Tensor 的 .require_grad
为 True
,那么 Tensor 上的所有操作将会被追踪。当完成计算时,你可以调用 .backward()
方法,PyTorch 将会帮你自动计算出所有的梯度。关于该 Tensor 的梯度将会被累加到 .grad
属性中。
为了停止 Tensor 进行历史中追踪,你可以调用 .detach()
方法来将它从计算历史记录中分离出来,并防止将来的计算被跟踪。
要停止 Tensor 停止跟踪历史记录(和使用内存),你可以使用 with torch.no_grad()
方法来将代码块包裹起来。这在模型评估时是非常有用的,因为在模型训练阶段可以使用具备 requires_grad=True
的参数进行调参,但是在模型评估阶段我们并不需要梯度。
另外,还有一个类(Function
)对于 autograd
的实现非常重要。
Tensor
和 Function
相互连接并构建一个非循环图,它保存了完整计算过程的历史信息。对于每个 tensor
都有 .grad_fn
属性保存着创建 Tensor 的 Function
引用(如果用户自己创建的张量,则 grad_fn
是 None
)。
你可以在 Tensor 上调用 .backward()
方法来计算导数。如果 Tensor 是一个标量(即包含一个数据元素的 Tensor),则不需要指定 backward()
的 任何参数。但是如果包含更多元素的 Tensor,则需要指定一个 gradient
参数来指定 Tensor 的维度。
import torch
创建一个 Tensor,并设置 requires_grad=True
来跟踪它的相关计算。
x = torch.ones(2, 2, requires_grad=True)
print(x)
输出结果:
tensor([[1., 1.],
[1., 1.]], requires_grad=True)
针对 Tensor 做一个操作:
y = x + 2
print(y)
输出结果:
tensor([[3., 3.],
[3., 3.]], grad_fn=<AddBackward0>)
y
是由 Tensor 操作结果创建,所以它有一个 grad_fn
属性。
print(y.grad_fn)
输出结果:
<AddBackward0 object at 0x7f1d35f45ef0>
让我们在 y
上做更多的操作:
z = y * y * 3
out = z.mean()
print(z, out)
输出结果:
tensor([[27., 27.],
[27., 27.]], grad_fn=<MulBackward0>) tensor(27., grad_fn=<MeanBackward0>)
使用 .requires_grad_(...)
方法将会改变一个已经存在 Tensor 的 requires_grad
属性。默认情况下,如果不做指定,一个 Tensor 的 requires_grad
属性为 False
。
import torch
a = torch.randn(2, 2)
a = ((a * 3) / (a - 1))
print(a.requires_grad)
a.requires_grad_(True)
print(a.requires_grad)
b = (a * a).sum()
print(b.grad_fn)
输出结果:
False
True
<SumBackward0 object at 0x7f1d35f5bb38>
2. 梯度
让我们看一下后向传播,因为 out
包含了一个单个标量,out.backward()
等同于 out.backward(torch.tensor(1.))
。
out.backward()
打印出 out
对于 x
的梯度:
print(x.grad)
输出结果:
tensor([[4.5000, 4.5000],
[4.5000, 4.5000]])
你将会得到一个元素均为 4.5 的矩阵,这里我们将 out
Tensor 称为 o
。则有:
因此:
从数学公式上来看,如果有一个 价值函数,那么 关于 是一个雅克比矩阵:
总而言之,torch.autograd
是一个计算雅克比向量内积的引擎。也就是给定任意向量 ,计算出 的内积。如果 碰巧是标量函数 的梯度,也就是 ,然后根据链式法则,雅克比向量内积将作为 关于 的梯度。
注意: 是一个行向量,也可以通过计算 来作为一个列向量。
现在,让我们来看一个雅克比向量内积的示例:
x = torch.randn(3, requires_grad=True)
y = x * 2
while y.data.norm() < 1000:
y = y * 2
print(y)
输出结果:
tensor([1001.7316, 475.3566, -226.5395], grad_fn=<MulBackward0>)
在这个案例中,y
不再是一个标量。torch.autograd
不能够完全直接计算出雅克比矩阵,但是我们仅仅是想要得到雅克比向量积,只需要简单地将向量作为参数传递给 backward
方法:
v = torch.tensor([0.1, 1.0, 0.0001], dtype=torch.float)
y.backward(v)
print(x.grad)
输出结果:
tensor([1.0240e+02, 1.0240e+03, 1.0240e-01])
你可以使用设置 Tensors 的 .requires_grad=True
,或者使用 with torch.no_grad()
来包裹代码块,来停止 autograd
对历史记录进行跟踪。
print(x.requires_grad)
print((x ** 2).requires_grad)
with torch.no_grad():
print((x ** 2).requires_grad)
输出结果:
True
True
False
或者使用 .detach()
方法来获得一个新的具备相同内容的 Tensor,但是不需要梯度计算:
print(x.requires_grad)
y = x.detach()
print(y.requires_grad)
print(x.eq(y).all())
输出结果:
True
False
tensor(True)
稍后可以阅读 autograd.Function
的文档在: https://pytorch.org/docs/stable/autograd.html#function
上一篇: 联合体
下一篇: 蓝桥杯:分配口罩————Python