PyTorch学习教程(二)-------Autograd:自动微分
%matplotlib inline
Autograd:自动微分
autograd package是PyTorch神经网络的核心。我们先简单看一下,然后开始训练第一个神经网络。
autograd package为张量的所有operations(操作或运算)提供了自动微分。它是一个define-by-run框架,意思是说你的反向传播(backpropagation)是由 如何运行代码 定义的,并且每一个迭代可以是不同的。
用例子和一些简单的术语来看下:
Tensor(张量)
torch.Tensor是包的核心类。如果你设置它的**.requires_grad属性 为 True,它的所有操作都会被跟踪记录。完成计算后可以调用.backward()**方法,并自动计算所有的梯度。这个张量的梯度将会被累积到.grad属性。
你可以调用**.detach()**方法来阻止张量对所有操作的跟踪记录。
阻止跟踪历史的另一种方法是你在代码块外包裹语句 with torch.no_grad(): ,这种方法在模型中训练参数设置了requires_grad=True时依然有效。
实现自动微分的另一个重要的类是Function.(这里function可理解为一个运算。比如加法运算)
Tensor 和 Function相互关联建立了一个非循环图,它记录了完整的计算历史。每一个张量有一个.grad_fn属性,这个属性与创建张量(除了用户自己创建的张量,它们的**.grad_fn**是None)的Function关联。
如果你想要计算导数,你可以调用张量的**.backward()**方法。如果张量是一个标量(例如,它只有一个元素),你不需要指定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 0x00000298859D6278>
对y进行运算:
z = y * y * 3
out = z.mean()
print(z, out)
tensor([[27., 27.],
[27., 27.]], grad_fn=<MulBackward0>) tensor(27., grad_fn=<MeanBackward1>)
.requires_grad_(…)函数可以改变张量的requires_grad属性。如果该属性未给出,则默认为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 0x00000298859C8E80>
梯度
有了自动微分,现在我们可以反向传播了。
因为out只是一个简单的标量,out.backward()等价于out.backward(torch.tensor(1))
out.backward()
打印出导数 d(out)/dx
print(x.grad)
tensor([[4.5000, 4.5000],
[4.5000, 4.5000]])
用下图来解释下为什么对out进行反向传播,x的梯度是4.5的矩阵吧:
x = torch.randn(3, requires_grad=True)
y = x * 2
while y.data.norm() < 1000:
y = y * 2
print(y)
tensor([-1016.0380, -869.8464, 611.4693], grad_fn=<MulBackward0>)
你可以用自动微分做更多有趣的事。之前都是对标量进行backward(),不需要参数。下面看下是向量或矩阵时,gradient参数的值对梯度的影响:
v = torch.tensor([0.1, 1.0, 0.0001], dtype=torch.float)
y.backward(v)
print(x.grad)
tensor([5.1200e+01, 5.1200e+02, 5.1200e-02])
如果你不想要跟踪历史并自动微分的时候,你可以在代码块外面包一层: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
原文网页:https://pytorch.org/tutorials/beginner/deep_learning_60min_blitz.html