Pytorch 笔记Ⅱ——Pytorch 自动求导机制
文章目录
Autograd: 自动求导机制
PyTorch
中,所有神经网络的核心是autograd
包。autograd
包为张量上的所有操作提供了自动求导机制。它是一个在运行时定义(define-by-run)
的框架,这意味着反向传播是根据代码如何运行来决定的,并且每次迭代可以是不同的。
张量(Tensor)
torch.Tensor
是这个包的核心类。如果设置.requires_grad
为 True
,那么将会追踪所有对于该张量的操作。
当完成计算后通过调用 .backward()
,自动计算所有的梯度,
这个张量的所有梯度将会自动积累到 .grad
属性。
要阻止张量跟踪历史记录,可以调用.detach()
方法将其与计算历史记录分离,并禁止跟踪它将来的计算记录。
为了防止跟踪历史记录(和使用内存),可以将代码块包装在with torch.no_grad():
中。
在评估模型时特别有用,因为模型可能具有requires_grad = True
的可训练参数,但是我们不需要梯度计算。
在自动梯度计算中还有另外一个重要的类Function
.
Tensor
和 Function
互相连接并生成一个非循环图,它表示和存储了完整的计算历史。
每个张量都有一个.grad_fn
属性,这个属性引用了一个创建了Tensor
的Function
(除非这个张量是用户手动创建的,即,这个张量的grad_fn
是 None
)。
如果需要计算导数,你可以在Tensor
上调用.backward()
。
如果Tensor
是一个标量(即它包含一个元素数据)则不需要为backward()
指定任何参数,
但是如果它有更多的元素,你需要指定一个gradient
参数来匹配张量的形状。
具体的后面会有详细说明
import torch
创建一个张量,设置 requires_grad=True 来跟踪与它相关的计算,创建一个单位矩阵
x = torch.ones(2, 2, requires_grad=True)
print(x)
tensor([[1., 1.],
[1., 1.]], requires_grad=True)
对张量进行操作:
y = x + 2
print(y)
tensor([[3., 3.],
[3., 3.]], grad_fn=<AddBackward0>)
结果y
已经被计算出来了,所以,grad_fn
已经被自动生成了。
print(y.grad_fn)
<AddBackward0 object at 0x000001D6A23509E8>
对y
进行一个操作,*
号计算点乘,将矩阵的对应元素相乘,.mean
操作是对矩阵求均值,可以利用axis
指定求均值的维度
Tensor1 = torch.tensor([5.5, 3])
Tensor2 = torch.tensor([2, 6])
result = Tensor1 * Tensor2
print(result)
print(result.mean(axis=0))
tensor([11., 18.])
tensor(14.5000)
因此可以发现
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_( ... )
可以改变现有张量的 requires_grad
属性。
如果没有指定的话,默认输入的flag是 False
。
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 0x000001D6ABD8C550>
梯度
反向传播
因为 out
是一个标量(scalar),out.backward()
等于out.backward(torch.tensor(1))
。
out.backward()
打印梯度
print(x.grad)
tensor([[4.5000, 4.5000],
[4.5000, 4.5000]])
得到矩阵 4.5
.将 out
叫做
Tensor “”.
得到
因此
则
在数学上,如果我们有向量值函数 ,且 关于 的梯度是一个雅可比矩阵(Jacobian matrix):
一般来说,torch.autograd
就是用来计算的工具。也就是说,给定任一向量 ,计算 ,如果 恰好是标量函数 的梯度,也就是说 ,那么根据链式法则, 是 对 的梯度:
这种特性使得将外部梯度返回到具有非标量输出的模型变得非常方便。
现在让我们来看一个的例子
x = torch.randn(3, requires_grad=True)
y = x * 2
i = 0
while y.data.norm() < 1000:
i += 1
print('已计算'+str(i)+'次')
y = y * 2
print(y)
已计算1次
已计算2次
已计算3次
已计算4次
已计算5次
已计算6次
已计算7次
已计算8次
已计算9次
已计算10次
tensor([-150.5787, 1158.3252, 227.0515], grad_fn=<MulBackward0>)
在这个情形中,y
不再是个标量。torch.autograd
无法直接计算出完整的雅可比行列,但是如果我们只想要,只需将向量作为参数传入backward
:
gradients = torch.tensor([0.1, 1.0, 0.0001], dtype=torch.float)
y.backward(gradients)
print(x.grad)
tensor([4.0960e+02, 4.0960e+03, 4.0960e-01])
如果.requires_grad=True
但是你又不希望进行autograd的计算,
那么可以将变量包裹在 with torch.no_grad()
中:
print(x.requires_grad)
print((x ** 2).requires_grad)
with torch.no_grad():
print((x ** 2).requires_grad)
True
True
False
推荐阅读:
autograd
和 Function
的官方文档
下载 Python 源代码:autograd_tutorial.py
下载 Jupyter 源代码:autograd_tutorial.ipynb
参考链接:PyTorch官方教程中文版
参考链接:yunjey-pytorch-tutorial
推荐阅读
-
Deep Learning with Pytorch 中文简明笔记 第六章 Using a neural network to fit the data
-
pytorch代码示例笔记 -- Autograd
-
PyTorch学习笔记01: PyTorch基本概念
-
学习笔记|Pytorch使用教程25(Batch Normalization)
-
PyTorch学习笔记(5)Dataloader与Dataset(2)
-
PyTorch学习笔记(6)逻辑回顾LR
-
【笔记】Ubuntu下创建用户,添加sudo权限,安装anaconda,创建虚拟环境,安装pytorch
-
PyTorch 的 自动求导(Autograd)
-
详解pytorch中的自动求导Autograd,彻底理解gradient参数
-
PyTorch自动求导:Autograd包案例详解