1. Tensor
创建一个随机初始化的张量(\(5 \times 3\)矩阵):
torch.rand(5, 3)
.创建一个全为\(0\)的张量(\(5 \times 3\)矩阵):
torch.zeros(5, 3, dtype=torch.long)
, 其中数据类型是long
.创建一个张量:
torch.tensor([1.3, 1.4])
.基于已经存在的张量创建一个张量:
x = x.new_ones(5, 3, dtype=torch.double) |
- 获取张量的维度信息:
x.size()
.
2. Operation
- 加法的几种方式:
x = torch.rand(5, 3) |
_
会使张量发生变化,例如x.copy_(y)
或x.t_()
都会改变x
.
- 使用
torch.view
改变张量的大小或形状:
x = torch.randn(6, 4) |
view(-1, n)
中-1
的大小是由其它位置推断出来的,比如上例中z
是一个\(3 \times 8\)的矩阵。
- 如果张量仅为一个元素,可以使用
.item()
来获得这个元素的值:
x = torch.randn(1) |
3. Automatic Differentiation
- 如果将
torch.Tensor
的属性.requires_grad
设置为True
, 则会开始跟踪针对张量的所有操作。在完成计算后,调用.backward()
来自动计算所有梯度。张量的梯度将累积到.grad
属性中。
x = torch.ones(2, 2, requires_grad=True) |
Let out
be \(o\), then \(\displaystyle o=\frac{1}{4}\sum_i z_i\), where \(z_i=3(x_i+2)^2\). Hence, \(\displaystyle \frac{\partial o}{\partial x_i}=\frac{3}{2}(x_i+2)\), and thus \(\displaystyle \frac{\partial o}{\partial x_i}\bigg|_{x_i-1}=4.5\).
当调用.backward()
时,一个张量会自动传递为.backward(torch.tensor(1.0))
, 其中torch.tensor(1.0)
是用来终止链式法则梯度乘法的外部梯度。
.backward()
中的张量的维数必须与正在计算梯度的张量的维数相同:
x = torch.tensor([0., 2., 8.], requires_grad=True) |
Tensor
和Function
互相连接并构建一个保存整个完整计算过程的历史信息的非循环图。每一个张量都一个.grad_fn
属性,这一属性保存着创建张量的Function
的引用。如果是用户自己创建张量,则.grad_fn
为None
:
x = torch.ones(2, 2, requires_grad=True) |
如果要停止张量历史记录的跟踪,调用
.detach()
来将其与计算历史记录分离,并防止将来的计算被跟踪。此外,还可以使用with torch.no_grad():
包装起来——在评估模型时尤其有用,因为模型在训练阶段具有requires_grad=True
的可训练参数有利于有利于调参,但在评估阶段我们不需要梯度。.requires_grad_()
会改变张量的requires_grad
标记。如果没有提供相应的参数,输入的标记默认为False
.
4. Neural Network
一个典型的神经网络训练过程包括:
定义一个包含可训练参数的神经网络。
迭代整个输入。
通过神经网络处理输入。
计算损失。
反向传播梯度到神经网络的参数。
更新网络的参数。
4.1. Example: LeNet-5
考虑一个简单的前馈神经网络。
在PyTorch
中,图像数据集的存储顺序为(batch, channels, height, width)
,依次为批大小、通道数、高度、宽度。按照网络结构,我们可以整理得:
|
|
|
---|---|---|
input
|
channels=1 height=32 width=32
|
(b, 1, 32, 32) Output: (b, 1, 32, 32)
|
conv1
|
in_channels=1 out_channels=6 kernel_size=5 padding=0 stride=1
|
(b, 1, 32, 32) Output: (b, 6, 28, 28)
|
pool1
|
kernel_size=2
|
(b, 6, 28, 28) Output: (b, 6, 14, 14)
|
conv2
|
in_channels=6 out_channels=16 kernel_size=5 padding=0 stride=1
|
(b, 6, 14, 14) Output: (b, 16, 10, 10)
|
pool2
|
kernel_size=2
|
(b, 16, 10, 10) Output: (b, 16, 5, 5)
|
fc1
|
in=16*5*5 out=120
|
(b, 16*5*5) Output: (b, 120)
|
fc2
|
in=120 out=84
|
(b, 120) Output: (b, 84)
|
fc3
|
in=84 out=10
|
(b, 84) Output: (b, 10)
|
4.1.1. torch.nn.Conv2d
卷积层用于提取特征。torch.nn.Conv2d
是二维卷积方法(常用于二维图像),相对应的还有一维卷积方法torch.nn.Conv1d
(常用于文本数据的处理)。torch.nn.Conv2d
有9个参数,我们先介绍6个较为重要的参数:
in_channels
及out_channels
:channels
意为通道数。在输入层中的RGB图片,channels=3
(红、绿、蓝);而单色图,channels=1
. 一般而言,channels
指每个卷基层中卷积核的数量。kernel_size
: 卷积核的大小,可以用int
表示长宽相等的卷积核,或者用tuple
.表示长宽不同的卷积核。stride
: 步长,用来控制卷积核移动间隔,默认stride=1
.padding
: 填充宽度。例如当padding=1
的时候,如果原来的大小为\(3 \times 3\), 那么填充后的大小为\(5 \times 5\), 即在外围加了一圈, 默认padding=0
.padding_mode
: 填充宽度的方式,默认padding_mode="zeros"
.
4.1.2. torch.nn.MaxPool2d
池化层用于提取重要信息,可以去掉不重要的信息,减少计算开销。torch.nn.MaxPool2d
在提取数据时,保留相邻信息中的最大值,并去掉其它值。我们先介绍torch.nn.MaxPool2d
中2个较为重要的参数:
kernel_size
: 池化核的大小,与卷积核类似。stride
: 步长,默认stride=
kernel_size`.
4.1.3. torch.nn.Linear
torch.nn.Linear
用于设置网络中的全连接层。在二维图像处理的任务中,全连接层的输入与输出一般都设置为二维张量(batch, size)
. torch.nn.Linear
有三个参数,分别为in_features
, out_features
和bias
.
4.2. Code
- 神经网络可以通过
torch.nn
来构建。首先我们定义图片中的神经网络:
import torch |
一个模型可训练的参数可以通过调用
LeNet5.parameters()
返回。一个简单的损失函数是均方误差
nn.MSELoss(output, target)
.调用
LeNet5.zero_grad()
将梯度清零,并随机的梯度来反向传播loss.vackward()
.利用梯度更新神经网络,最简单的更新规则是随机梯度下降:
learning_rate = 0.01 |
此外,我们可以使用不同的更新规则,比如Adam
等:
import torch.optim as optim |