作者:Soumith Chintala
原文翻译自:https://pytorch.org/tutorials/beginner/deep_learning_60min_blitz.html
中文翻译、注释制作:黄海广
github:https://github.com/fengdu78
代码全部测试通过。
配置环境:PyTorch 1.0,python 3.6,
主机:显卡:一块1080ti;内存:32g(注:绝大部分代码不需要GPU)
目录
- 1.Pytorch是什么?
- 2.AUTOGRAD
- 3.神经网络
- 4.训练一个分类器
- 5.数据并行
二、Autograd: 自动求导(automatic differentiation)
PyTorch 中所有神经网络的核心是autograd
包.我们首先简单介绍一下这个包,然后训练我们的第一个神经网络.
autograd
包为张量上的所有操作提供了自动求导.它是一个运行时定义的框架,这意味着反向传播是根据你的代码如何运行来定义,并且每次迭代可以不同.
接下来我们用一些简单的示例来看这个包:
张量(Tensor)
torch.Tensor
是包的核心类。如果将其属性.requires_grad
设置为True,则会开始跟踪其上的所有操作。完成计算后,您可以调用.backward()
并自动计算所有梯度。此张量的梯度将累积到.grad
属性中。
要阻止张量跟踪历史记录,可以调用.detach()
将其从计算历史记录中分离出来,并防止将来的计算被跟踪。
要防止跟踪历史记录(和使用内存),您还可以使用torch.no_grad()包装代码块:在评估模型时,这可能特别有用,因为模型可能具有requires_grad = True
的可训练参数,但我们不需要梯度。
还有一个类对于autograd实现非常重要 - Function。
Tensor和Function互相连接并构建一个非循环图构建一个完整的计算过程。每个张量都有一个.grad_fn
属性,该属性引用已创建Tensor的Function(除了用户创建的Tensors - 它们的grad_fn
为None
)。
如果要计算导数,可以在Tensor上调用.backward()
。如果Tensor是标量(即它包含一个元素数据),则不需要为backward()
指定任何参数,但是如果它有更多元素,则需要指定一个梯度参数,该参数是匹配形状的张量。
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,而x是由用户创建,所以它的grad_fn为None.
print(y.grad_fn)
print(x.grad_fn)
<AddBackward0 object at 0x000001E020B794A8>
None
在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_(...)
就地更改现有的Tensor的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 0x000001E020B79FD0>
梯度(Gradients)
现在我们来执行反向传播,out.backward()
相当于执行out.backward(torch.tensor(1.))
out.backward()
输出out对x的梯度d(out)/dx:
print(x.grad)
tensor([[4.5000, 4.5000],
[4.5000, 4.5000]])
你应该得到一个值全为4.5的矩阵,我们把张量out称为”
%7D%5E%7B2%7D%7D#card=math&code=%7B%7Bz%7D%7Bi%7D%7D%3D3%7B%7B%28x%2B2%29%7D%5E%7B2%7D%7D&height=24&width=103)![](https://g.yuque.com/gr/latex?z%5Cleft%7C%20%7B%7B%7Bx%7D%7Bi%7D%7D%3D1%7D%20%5Cright.%3D27#card=math&code=z%5Cleft%7C%20%7B%7B%7Bx%7D%7Bi%7D%7D%3D1%7D%20%5Cright.%3D27&height=21&width=82)#card=math&code=%5Cfrac%7B%5Cpartial%20o%7D%7B%5Cpartial%20x_i%7D%20%3D%20%5Cfrac%7B3%7D%7B2%7D%28x_i%2B2%29&height=42&width=125)![](https://g.yuque.com/gr/latex?%5Cfrac%7B%5Cpartial%20o%7D%7B%5Cpartial%20x_i%7D%5Cbigr%5Crvert%7Bxi%3D1%7D%20%3D%20%5Cfrac%7B9%7D%7B2%7D%20%3D%204.5#card=math&code=%5Cfrac%7B%5Cpartial%20o%7D%7B%5Cpartial%20x_i%7D%5Cbigr%5Crvert%7Bx_i%3D1%7D%20%3D%20%5Cfrac%7B9%7D%7B2%7D%20%3D%204.5&height=42&width=144)
#card=math&code=%5Cvec%7By%7D%3Df%28%5Cvec%7Bx%7D%29&height=20&width=63)
#card=math&code=J%3D%5Cleft%28%20%5Cbegin%7Bmatrix%7D%0A%20%20%20%5Cfrac%7B%5Cpartial%20%7B%7By%7D%7B1%7D%7D%7D%7B%5Cpartial%20%7B%7Bx%7D%7B1%7D%7D%7D%20%26%20%5Cldots%20%20%26%20%5Cfrac%7B%5Cpartial%20%7B%7By%7D%7Bm%7D%7D%7D%7B%5Cpartial%20%7B%7Bx%7D%7B1%7D%7D%7D%20%20%5C%5C%0A%20%20%20%5Cvdots%20%20%26%20%5Cddots%20%20%26%20%5Cvdots%20%20%20%5C%5C%0A%20%20%20%5Cfrac%7B%5Cpartial%20%7B%7By%7D%7B1%7D%7D%7D%7B%5Cpartial%20%7B%7Bx%7D%7Bn%7D%7D%7D%20%26%20%5Ccdots%20%20%26%20%5Cfrac%7B%5Cpartial%20%7B%7By%7D%7Bm%7D%7D%7D%7B%5Cpartial%20%7B%7Bx%7D%7Bn%7D%7D%7D%20%20%5C%5C%0A%5Cend%7Bmatrix%7D%20%5Cright%29&height=102&width=177)
一般来说,torch.autograd是一个计算雅可比向量积的引擎。 也就是说,给定任何向量
%5ET#card=math&code=v%20%3D%28v1%20v_2%20…v_m%29%5ET&height=23&width=127)#card=math&code=l%3Dg%28%5Cvec%7By%7D%29&height=20&width=57)![](https://g.yuque.com/gr/latex?v%3D%7B%7B(%5Cfrac%7B%5Cpartial%20l%7D%7B%5Cpartial%20%7B%7By%7D%7B1%7D%7D%7D%5Ccdots%20%5Cfrac%7B%5Cpartial%20l%7D%7B%5Cpartial%20%7B%7By%7D%7Bm%7D%7D%7D)%7D%5E%7BT%7D%7D#card=math&code=v%3D%7B%7B%28%5Cfrac%7B%5Cpartial%20l%7D%7B%5Cpartial%20%7B%7By%7D%7B1%7D%7D%7D%5Ccdots%20%5Cfrac%7B%5Cpartial%20l%7D%7B%5Cpartial%20%7B%7By%7D_%7Bm%7D%7D%7D%29%7D%5E%7BT%7D%7D&height=47&width=146)
%5Cleft(%20%5Cbegin%7Bmatrix%7D%0A%20%20%20%5Cfrac%7B%5Cpartial%20l%7D%7B%5Cpartial%20%7B%7By%7D%7B1%7D%7D%7D%20%20%5C%5C%0A%20%20%20%5Cvdots%20%20%20%5C%5C%0A%20%20%20%5Cfrac%7B%5Cpartial%20l%7D%7B%5Cpartial%20%7B%7By%7D%7Bm%7D%7D%7D%20%20%5C%5C%0A%5Cend%7Bmatrix%7D%20%5Cright)%3D%5Cleft(%20%5Cbegin%7Bmatrix%7D%0A%20%20%20%5Cfrac%7B%5Cpartial%20l%7D%7B%5Cpartial%20%7B%7Bx%7D%7B1%7D%7D%7D%20%20%5C%5C%0A%20%20%20%5Cvdots%20%20%20%5C%5C%0A%20%20%20%5Cfrac%7B%5Cpartial%20l%7D%7B%5Cpartial%20%7B%7Bx%7D%7Bn%7D%7D%7D%20%20%5C%5C%0A%5Cend%7Bmatrix%7D%20%5Cright)#card=math&code=J%5Ccenterdot%20v%3D%5Cleft%28%20%5Cbegin%7Bmatrix%7D%0A%20%20%20%5Cfrac%7B%5Cpartial%20%7B%7By%7D%7B1%7D%7D%7D%7B%5Cpartial%20%7B%7Bx%7D%7B1%7D%7D%7D%20%26%20%5Cldots%20%20%26%20%5Cfrac%7B%5Cpartial%20%7B%7By%7D%7Bm%7D%7D%7D%7B%5Cpartial%20%7B%7Bx%7D%7B1%7D%7D%7D%20%20%5C%5C%0A%20%20%20%5Cvdots%20%20%26%20%5Cddots%20%20%26%20%5Cvdots%20%20%20%5C%5C%0A%20%20%20%5Cfrac%7B%5Cpartial%20%7B%7By%7D%7B1%7D%7D%7D%7B%5Cpartial%20%7B%7Bx%7D%7Bn%7D%7D%7D%20%26%20%5Ccdots%20%20%26%20%5Cfrac%7B%5Cpartial%20%7B%7By%7D%7Bm%7D%7D%7D%7B%5Cpartial%20%7B%7Bx%7D%7Bn%7D%7D%7D%20%20%5C%5C%0A%5Cend%7Bmatrix%7D%20%5Cright%29%5Cleft%28%20%5Cbegin%7Bmatrix%7D%0A%20%20%20%5Cfrac%7B%5Cpartial%20l%7D%7B%5Cpartial%20%7B%7By%7D%7B1%7D%7D%7D%20%20%5C%5C%0A%20%20%20%5Cvdots%20%20%20%5C%5C%0A%20%20%20%5Cfrac%7B%5Cpartial%20l%7D%7B%5Cpartial%20%7B%7By%7D%7Bm%7D%7D%7D%20%20%5C%5C%0A%5Cend%7Bmatrix%7D%20%5Cright%29%3D%5Cleft%28%20%5Cbegin%7Bmatrix%7D%0A%20%20%20%5Cfrac%7B%5Cpartial%20l%7D%7B%5Cpartial%20%7B%7Bx%7D%7B1%7D%7D%7D%20%20%5C%5C%0A%20%20%20%5Cvdots%20%20%20%5C%5C%0A%20%20%20%5Cfrac%7B%5Cpartial%20l%7D%7B%5Cpartial%20%7B%7Bx%7D%7Bn%7D%7D%7D%20%20%5C%5C%0A%5Cend%7Bmatrix%7D%20%5Cright%29&height=102&width=348)
雅可比向量积的这种特性使得将外部梯度馈送到具有非标量输出的模型中非常方便。
现在让我们来看一个雅可比向量积的例子:
x = torch.randn(3, requires_grad=True)
y = x * 2
while y.data.norm() < 1000:
y = y * 2
print(y)
tensor([ 384.5854, -13.6405, -1049.2870], grad_fn=<MulBackward0>)
现在在这种情况下,y不再是标量。 torch.autograd
无法直接计算完整雅可比行列式,但如果我们只想要雅可比向量积,只需将向量作为参数向后传递:
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])
您还可以通过torch.no_grad()代码,在张量上使用.requires_grad = True来停止使用跟踪历史记录。
print(x.requires_grad)
print((x ** 2).requires_grad)
with torch.no_grad():
print((x ** 2).requires_grad)
True
True
False
关于autograd
和Function
的文档在http://pytorch.org/docs/autograd
本章的官方代码:
- Python:autograd_tutorial.py
- Jupyter notebook:autograd_tutorial.ipynb