三、Pytorch主要组成

3.1深度学习总览

完成一项机器学习的步骤:数据预处理——数据划分——模型选择——损失函数和优化方法及对应超参数的设定——模型拟合,计算模型表现

深度学习与机器学习在流程上类似,但由于深度学习样本量大可能会超出内存,同时还有批训练等,因此须有另外的设计。

深度神经网络往往需要“逐层”搭建一些用于实现特定功能的层,或者预先定义好可以实现特定功能的模块,再把这些模块组装起来。

损失函数和优化器要能够保证反向传播能够在用户自行定义的模型结构上实现。

按批读入数据,放入GPU训练,然后将损失函数反向传播回网络最前面的层,同时使用优化器调整网络参数。之后需要根据设定好的指标计算模型表现。

3.2基本配置

(1)包的导入

建议导入了一些常用的包

(2)习惯统一设置的参数

1
2
3
4
5
batch_size = 16
# 批次的大小
lr = 1e-4
# 优化器的学习率
max_epochs = 100

(3)GPU的设置

1
2
3
4
5
# 方案一:使用os.environ,这种情况如果使用GPU不需要设置
os.environ['CUDA_VISIBLE_DEVICES'] = '0,1'

# 方案二:使用“device”,后续对要使用GPU的变量用.to(device)即可
device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu")

3.3数据读入

PyTorch数据读入是通过Dataset+DataLoader的方式完成的,Dataset定义好数据的格式和数据变换形式,DataLoader用iterative的方式不断读入批次数据。

自定义类三个函数:

  • __init__: 用于向类中传入外部参数,同时定义样本集
  • __getitem__: 用于逐个读取样本集合中的元素,可以进行一定的变换,并将返回训练/验证所需的数据
  • __len__: 用于返回数据集的样本数

3.4模型构建

(1)继承Module类构造模型

例:继承 Module 类构造多层感知机

MLP 类重载了 Module 类的 init 函数和 forward 函数,分别用于创建模型参数和定义前向计算(正向传播)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import torch
from torch import nn

class MLP(nn.Module):
# 声明带有模型参数的层,这里声明了两个全连接层
def __init__(self, **kwargs):
# 调用MLP父类Block的构造函数来进行必要的初始化。这样在构造实例时还可以指定其他函数
super(MLP, self).__init__(**kwargs)
self.hidden = nn.Linear(784, 256)
self.act = nn.ReLU()
self.output = nn.Linear(256,10)

# 定义模型的前向计算,即如何根据输入x计算返回所需要的模型输出
def forward(self, x):
o = self.act(self.hidden(x))
return self.output(o)
以上的 MLP 类中⽆须定义反向传播函数。系统将通过⾃动求梯度⽽自动⽣成反向传播所需的 backward 函数。

(2)自定义层

  • 不含模型参数的层

例:将输入减掉均值后输出

1
2
3
4
5
6
7
8
import torch
from torch import nn

class MyLayer(nn.Module):
def __init__(self, **kwargs):
super(MyLayer, self).__init__(**kwargs)
def forward(self, x):
return x - x.mean()
  • 含模型参数的层

通过训练得到模型参数

常见层

  • 二维卷积层

    二维卷积层将输入和卷积核做互相关运算,并加上一个标量偏差来得到输出。卷积层的模型参数包括了卷积核和标量偏差。在训练模型的时候,通常我们先对卷积核随机初始化,然后不断迭代卷积核和偏差。

  • 池化层

    池化层每次对输入数据的一个固定形状窗口(⼜称池化窗口)中的元素计算输出。不同于卷积层里计算输⼊和核的互相关性,池化层直接计算池化窗口内元素的最大值或者平均值。该运算也 分别叫做最大池化或平均池化。在二维最⼤池化中,池化窗口从输入数组的最左上方开始,按从左往右、从上往下的顺序,依次在输⼊数组上滑动。当池化窗口滑动到某⼀位置时,窗口中的输入子数组的最大值即输出数组中相应位置的元素。

3.5 模型初始化

权重的初始值极为重要。一个好的权重值,会使模型收敛速度提高,使模型准确率更精确。

torch.nn.init中为我们提供了常用的初始化方法。

3.6损失函数

损失函数即对模型效果的负反馈,很重要,模型可按此改进。

原文对损失函数进行了简单举例:3.6 损失函数 — 深入浅出PyTorch (datawhalechina.github.io)

3.7训练和评估

(1)训练

1
model.train()   # 训练状态

用for循环读取DataLoader中的全部数据。

1
for data, label in train_loader:

之后将数据放到GPU上用于后续计算,此处以.cuda()为例

1
data, label = data.cuda(), label.cuda()

开始用当前批次数据做训练时,应当先将优化器的梯度置零:

1
optimizer.zero_grad()

之后将data送入模型中训练:

1
output = model(data)

根据预先定义的criterion计算损失函数:

1
loss = criterion(output, label)

将loss反向传播回网络:

1
loss.backward()

使用优化器更新模型参数:

1
optimizer.step()

(2)评估

1
model.eval()   # 验证/测试状态

验证/测试的流程基本与训练过程一致,不同点在于:

  • 需要预先设置torch.no_grad,以及将model调至eval模式
  • 不需要将优化器的梯度置零
  • 不需要将loss反向回传到网络
  • 不需要更新optimizer

3.8可视化

将训练过程中的一些参数可视化能更好的反映模型相关的内容。

3.9Pytorch优化器

深度学习就是寻找最优参数的过程,对多参数的寻找有俩各种方法:

(1)暴力穷举

(2)BP+优化器(根据网络反向传播的梯度信息来更新网络的参数,以起到降低loss函数计算值,使得模型输出更加接近真实标签。)

Pytorch的优化器库(torch.optim)

原文:3.9 Pytorch优化器 — 深入浅出PyTorch (datawhalechina.github.io)

四、基础实战——FashionMNIST时装分类

十类服装分类,使用FashionMNIST数据集。(已预划分好训练和测试集,训练集共60,000张图像,测试集共10,000张图像。每张图像均为单通道黑白图像,大小为28*28pixel,分属10个类别。)

过程讲解详细,训练结果待补充。。。