PyTorch基础知识总结
Tensor(张量)
张量是PyTorch里的基本运算单位,与numpy的ndarray相同都表示一个多维的矩阵。与ndarray最大的区别在于Tensor能使用GPU加速,而ndarray只能用在CPU上。
与Numpy之间进行转换
将Tensor转换成numpy,只需调用.numpy()方法即可。
将numpy转换成Tensor,使用torch.from_numpy()进行转换。
# a --> Tensor
a = torch.rand(3, 2)
# Tensor --> numpy
numpy_a = a.numpy()
# numpy --> Tensor
b = torch.from_numpy(numpy_a)
Tensor初始化
- torch.rand(*size) : 使用[0, 1]均匀分布随机初始化
- torch.randn(*size) : 服从正太分布初始化
- torch.zeros(*size) : 使用0填充
- torch.ones(*size):使用1填充
- torch.eye(*size) :初始化一个单位矩阵,即对角线为1,其余为0
Autograd
PyTorch中的Autograd模块实现了深度学习的算法中的反向传播求导数,在Tensor上的所有操作,Autograd都能为它们自动计算微分,简化了手动求导数的过程。
在张量创建时,通过设置requires_grad = True来告诉PyTorch需要对该张量进行自动求导,PyTorch会记录该张量的每一步操作历史并自动计算导数。requires_grad默认为False。
x = torch.randn(5, 5, requires_grad = True)
在计算完成后,调用backward()方法会自动根据历史操作来计算梯度,并保存在grad中。
神经网络包nn (torch.nn)
torch.nn是专门为神经网络设计的模块化接口,建立在Autogard之上。
通常定义一个神经网络类除了使用到nn之外还会引用nn.functional,这个包中包含了神经网络中使用的一些常见函数(ReLu, pool, sigmoid, softmax等),这些函数一般放在forward函数中。
通常一个神经网络类需要继承nn.Module,并实现forward方法,PyTorch就会根据autograd自动实现backward方法。下面是LeNet网络模型的定义。
import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
# 卷积层
self.conv1 = nn.Conv2d(1, 6, 5)
self.conv2 = nn.Conv2d(6, 16, 5)
# 全连接层
self.fc1 = nn.Linear(16 * 5 * 5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
# 卷积 --> ReLu --> 池化
x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
x = F.max_pool2d(F.relu(self.conv2(x)), (2, 2))
# reshape, '-1'表示自适应
# x = (n * 16 * 5 * 5) --> n : batch size
# x.size()[0] == n --> batch size
x = x.view(x.size()[0], -1)
# 全连接层
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
损失函数
在torch.nn中还定义了一些常用的损失函数,比如MESLoss(均方误差),CrossEntropyLoss(交叉熵误差)等。
labels = torch.arange(10).view(1, 10).float()
out = net(input)
criterion = nn.MSELoss()
# 计算loss
loss = criterion(labels, out)
优化器(torch.optim)
在反向传播计算完所有参数的梯度后,还需要使用优化方法来更新网络的参数,常用的优化方法有随机梯度下降法(SGD),策略如下:
weight = weight - learning_rate * gradient
import torch.optim
import torch.nn as nn
out = net(input)
criterion = nn.MSELoss(out, labels)
# 新建一个优化器,SGD只需要输入要调整的参数和学习率
optimizer = torch.optim.SGD(net.parameters(), lr = 0.01)
# 反向传播前,先梯度清0, optimizer.zero_grad()等同于net.zero_grad()
optimizer.zero_grad()
loss.backward()
# 更新参数
optimizer.step()
数据的加载和预处理
PyTorch通过torch.utils.data对一般常用的数据加载进行了封装,可以很容易实现数据预处理和批量加载。torchvision已经有一些常用的数据集以及训练好的模型(例如,CIFAR-10, ImageNet, COCO等),可以很方便的在这些模型上进行训练以及测试。
Dataset(torch.utils.data.Dataset)
为了方便数据的读取,通常需要将使用的数据集包装为Dataset类。可以使用torchvision.dataset包中存在数据集来生成Dataset,同时也可以自定义Dataset类。
以torchvision.dataset中MNIST数据集为例生成dataset
dataset = tv.datasets.MNIST(
root='data/',
train=True,
download=True,
transform=None
)
自定义Dataset,当torchvision.dataset包中没有相应的数据集,这时候就需要我们自定义Dataset类了,自定义类必须继承于torch.utils.data.Dataset类,并且实现__ len __ () 和 __ getitem __ () 方法。
- __ len __ () 该方法返回数据集的总长度。
- __ getitem __ () 该方法通过索引[0, len(self) - 1]来获取一条数据或者一个样本。
DataLoader(torch.utils.data.DataLoader)
DataLoader为我们提供了对Dataset的读取操作,常用的参数有batch_size(每一批数据的大小), shuffle(是否进行随机读取操作), num_workers(加载数据的时候使用几个子进程)
trainloader = torch.utils.data.DataLoader(dataset, batch_size=10, shuffle=True, num_works=0)
# trainloader是一个可迭代的对象,我们可以使用iter分次获取数据。
# 但是通常使用for循环来对其进行遍历,如下。
for i, data in enumerate(trainloader):
# deal the data
pass
此时,我们可以通过Dataset加装数据集,并使用DataLoader来遍历处理数据。
torchvision包
torchvision是专门用来处理图像的库,里面有datasets, models, transforms等类,其中最常用的类是transforms,它通常用来进行数据的预处理(ToTensor, 归一化等),如下。
from torchvision import transforms as transforms
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.4914, 0.4822, 0.4465), (0.229, 0.224, 0.225)), #R,G,B每层的归一化用到的均值和方差
])