之前的内容已经学习了如何定义神经网络、计算损失和更新网络的权重。 现在我们可以完整的训练一个分类器。

我们将按顺序执行以下步骤:

  1. 使用torchvision加载和规范化 CIFAR10 训练和测试数据集
  2. 定义卷积神经网络
  3. 定义损失函数
  4. 在训练数据上训练网络
  5. 在测试数据上测试网络

获取数据

通常,当我们必须处理图像、文本、音频或视频数据时, 可以使用将数据加载到 numpy 数组中的标准 python 包。 然后将此数组转换为 torch.*Tensor类型。

  • 对于图像,Pillow、OpenCV 等软件包很有用
  • 对于音频,scipy 和 librosa 等软件包
  • 对于文本,基于原始 Python 或 Cython 的加载,或 NLTK 和 SpaCy 很有用

例如针对计算机视觉可以使用名为 torchvision 的包,它具有用于常见数据集的数据加载器,比如ImageNet、CIFAR10、MNIST 数据集等。和用于图像的数据转换器, torchvision.datasetstorch.utils.data.DataLoader

这为我们提供了极大的便利并避免了编写模板代码。 对于本次代码,将使用 CIFAR10 数据集。 它有:'飞机','汽车','鸟','猫','鹿', “狗”、“青蛙”、“马”、“船”、“卡车”十个类别。 CIFAR-10 中的图像尺寸是 3x32x32,即 32x32 像素大小的 3 通道彩色图像。

1、加载并规范化 CIFAR10

使用 torchvision,加载 CIFAR10

import torch
import torchvision
import torchvision.transforms as transforms

torchvision 数据集的输出是范围 [0, 1] 的 PILImage图像。 最后我们将它标准化转换为范围 [-1, 1] 的张量。

transform = transforms.Compose(     #图像预处理包。一般用Compose把多个步骤整合到一起:[transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])#用均值和标准差对张量图像进行归一化batch_size = 4trainset = torchvision.datasets.CIFAR10(root='./data', train=True,download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=batch_size,shuffle=True, num_workers=0)testset = torchvision.datasets.CIFAR10(root='./data', train=False,download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=batch_size,shuffle=False, num_workers=0)classes = ('plane', 'car', 'bird', 'cat','deer', 'dog', 'frog', 'horse', 'ship', 'truck')#定义其中的类别

 其中ToTensor()能够把灰度范围从0-255变换到0-1之间,ToTensor()shape(H, W, C)nump.ndarrayimg 转为 shape(C, H, W)tensor,再将每一个数值归一化到[0,1],其归一化方法比较简单,直接除以255即可。

transforms.Normalize(std=(0.5,0.5,0.5),mean=(0.5,0.5,0.5)),则其作用就是先将输入归一化到(0,1),再使用公式"(x-mean)/std",将每个元素分布到(-1,1)之间,对每个通道而言,执行image=(image-mean)/std。每个样本图像变成了均值为0  方差为1 的标准正态分布。有时 stdmean 中的数据是从imagenet训练集中抽样算出来的

为了更加直观,让我们展示一些训练图像:

import matplotlib.pyplot as plt #和matlab类似的绘图API,方便用户快速绘制2D图表。
import numpy as np
def imshow(img):img = img / 2 + 0.5     # 逆标准化,Normalize的逆过程,img = img * std + meannpimg = img.numpy()     # 将张量转化成numpy的ndarray类型plt.imshow(np.transpose(npimg, (1, 2, 0)))#ndarray对象的形状(C, H, W)转换为(H, W, C)plt.show()
# 获取一组随机训练图片,#获取数据流中的数据元素
dataiter = iter(trainloader)
images, labels = dataiter.next()#得到图像数据和对应标签
# 展示图片
imshow(torchvision.utils.make_grid(images))##组成图像的网络,其实就是将多张图片组合成一张图片。
# 输出对应标签
print(' '.join(f'{classes[labels[j]]:5s}' for j in range(batch_size)))
#join()返回被子字符串连接的字符串。5s表示空格大小

 其中transpose()函数的实质作用是改变序列。根据维度(shape)索引决定的,就是调换数组的行列值的索引值。

Python numpy.transpose 详解_November丶Chopin的博客-CSDN博客_numpy transpose

输出结果:                               标签:car   frog  truck deer

2、定义卷积神经网络

import torch.nn as nn
import torch.nn.functional as Fclass Net(nn.Module):def __init__(self):super().__init__()self.conv1 = nn.Conv2d(3, 6, 5)self.pool = nn.MaxPool2d(2, 2)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):x = self.pool(F.relu(self.conv1(x)))#卷积+激活+池化x = self.pool(F.relu(self.conv2(x)))x = torch.flatten(x, 1) # 展平层、展平除批次外的所有尺寸x = F.relu(self.fc1(x))#全连接层+激活函数x = F.relu(self.fc2(x))x = self.fc3(x)#全连接层return x
net = Net()
print(net)

输出结果:

Net((conv1): Conv2d(3, 6, kernel_size=(5, 5), stride=(1, 1))(pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))(fc1): Linear(in_features=400, out_features=120, bias=True)(fc2): Linear(in_features=120, out_features=84, bias=True)(fc3): Linear(in_features=84, out_features=10, bias=True)
)

3、定义损失函数和优化器

使用具有动量的分类交叉熵损失函数随机梯度下降SGD优化器。

import torch.optim as optimcriterion = nn.CrossEntropyLoss()#定义交叉熵损失函数
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

其中torch.optim是一个实现了各种优化算法的库。SGD就是optim中的一个算法(优化器):随机梯度下降算法。torch.optim.SGD参数学习率lr、动量momentum、权重衰减weight_decay的解析_jjw_zyfx的博客-CSDN博客_pytorch sgd参数

第一个参数 net.parameters() 包括权重w,和偏置b等是神经网络中的参数,也是SGD优化的重点。

第二个参数lr是学习率。sgd中的学习率lr的作用可以理解为: p ′ = p − l r ∗ d p 其中p就是模型中的参数比如:权重(w), 偏置(b)。dp 就是对p的一阶求导, lr 即学习率, p ′为p的另一种形式,用来替换上一次的p。

第三个参数momentum是冲量,在普通的梯度下降法x+=v中,每次x的更新量v为v=−dx∗lr,其中dx为目标函数func(x)对x的一阶导数,当使用冲量时,把每次x的更新量v考虑为本次的梯度下降量−dx∗lr与上次x的更新量v乘上介于[0,1][0,1]因子momentum的和,即v′=−dx∗lr+v∗momemtum

4、训练网络

遍历我们的数据迭代器,并将输入提供给网络和优化器。

for epoch in range(2):  # 在数据集上循环多次running_loss = 0.0for i, data in enumerate(trainloader, 0):# data中包含输入图像张量inputs,张量标签labelsinputs, labels = data                # 获取输入;数据是[输入、标签]的列表# 将优化器参数梯度归零optimizer.zero_grad()# 前向传播 + 计算损失 + 反向传播 + 优化outputs = net(inputs)        # 输入图像张量进网络,得到输出张量outputsloss = criterion(outputs, labels) # 利用网络的输出outputs和标签labels计算损失值loss.backward()        # 反向传播+参数更新,是标准代码的标准流程optimizer.step()# 打印轮次和损失值running_loss += loss.item()if i % 2000 == 1999:    # 每2000小批量打印一次print(f'[{epoch + 1}, {i + 1:5d}] loss: {running_loss / 2000:.3f}')running_loss = 0.0
print('Finished Training')

输出结果:

[1,  2000] loss: 2.253
[1,  4000] loss: 1.901
[1,  6000] loss: 1.699
[1,  8000] loss: 1.564
[1, 10000] loss: 1.507
[1, 12000] loss: 1.454
[2,  2000] loss: 1.363
[2,  4000] loss: 1.347
[2,  6000] loss: 1.313
[2,  8000] loss: 1.297
[2, 10000] loss: 1.251
[2, 12000] loss: 1.288
Finished Training

快速保存我们训练好的模型(参数):

PATH = './cifar_net.pth'#首先设定模型的保存路径
torch.save(net.state_dict(), PATH)#保存模型的状态字典

 5、在测试数据上测试网络

我们已经在训练数据集上训练了网络 2 次。 但是我们需要检查网络是否学到了任何东西。通过预测神经网络的类标签来检查这一点输出,并根据实际情况对其进行检查。 如果预测是正确,则将样本添加到正确预测列表中。

dataiter = iter(testloader)#获取一批数据流
images, labels = dataiter.next()
# 打印原始图像, 展示来自测试集的图像。
imshow(torchvision.utils.make_grid(images))
#打印真实的数据标签
print('GroundTruth: ', ' '.join(f'{classes[labels[j]]:5s}' for j in range(4)))
# 首先实例化模型的类的对象
net = Net()
net.load_state_dict(torch.load(PATH))# 加载训练阶段保存好的模型的状态字典outputs = net(images)# 利用模型对图片进行预测_, predicted = torch.max(outputs, 1)# 共有十个类别,采用模型计算出的概率最大的作为预测的类别
print('Predicted: ', ' '.join(f'{classes[predicted[j]]:5s}'# 打印预测标签的结果for j in range(4)))

输出结果:                     GroundTruth:    cat  ship  ship plane
                                       Predicted:    cat  ship  ship  ship

现在看看网络在整个数据集上的表现。

correct = 0
total = 0
# 因为没有训练,所以我们不需要计算输出的梯度
with torch.no_grad():for data in testloader:images, labels = data# 通过网络运行图像计算输出outputs = net(images)# 我们选择概率最高的类作为预测_, predicted = torch.max(outputs.data, 1)total += labels.size(0)#测试数据集的样本个数correct += (predicted == labels).sum().item()#预测正确个数print(f'Accuracy of the network on the 10000 test images: {100 * correct // total} %')

输出结果:

Accuracy of the network on the 10000 test images: 54 %

分析结果:对于拥有10个类别的数据集,随机猜测的准确率是10%,模型达到了54%,说明模型学到了真实的东西。为了更细致的看一下模型在哪些类上表现得更好,在哪些类上表现得更差,我们分类别的进行准确率的计算

# 准备计算每个类别的预测
correct_pred = {classname: 0 for classname in classes}#字典生成器
total_pred = {classname: 0 for classname in classes}#创建包含10个类别的字典# 同样不需要梯度
with torch.no_grad():for data in testloader:images, labels = dataoutputs = net(images)_, predictions = torch.max(outputs, 1)# 收集每个类别的正确预测for label, prediction in zip(labels, predictions):if label == prediction:correct_pred[classes[label]] += 1#给此标签对应的类别加1total_pred[classes[label]] += 1#此类别的总数加1
# 打印每一个类别的准确率
for classname, correct_count in correct_pred.items():accuracy = 100 * float(correct_count) / total_pred[classname]print(f'Accuracy for class: {classname:5s} is {accuracy:.1f} %')

其中 zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。

输出结果:

Accuracy of plane : 100 %
Accuracy of   car : 100 %
Accuracy of  bird : 100 %
Accuracy of   cat : 100 %
Accuracy of  deer : 100 %
Accuracy of   dog : 100 %
Accuracy of  frog : 100 %
Accuracy of horse : 100 %
Accuracy of  ship : 100 %
Accuracy of truck : 100 %

6、在 GPU 上训练

就像如何将张量转移到 GPU 上一样,转移神经网络到GPU上。如果有GPU,让我们首先将我们的设备定义为第一个可见的 cuda 设备 可用的 CUDA:

device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
# 假设我们在CUDA机器上,这应该打印CUDA设备:
print(device)

假设 device是一个 CUDA 设备。当训练模型的时候,只需要将模型转移到GPU上,同时将输入的图片和标签页转移到GPU上即可。然后这些方法将递归地遍历所有模块并转换它们的 CUDA 张量的参数和缓冲区:

net.to(device)#将模型转移到GPU上
inputs, labels = data[0].to(device), data[1].to(device)
#将输入的图片张量和标签张量转移到GPU上

使用 PyTorch 进行深度学习-训练分类器相关推荐

  1. PyTorch深度学习训练可视化工具tensorboardX

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 之前笔者提到了PyTorch的专属可视化工具visdom,参看Py ...

  2. 【深度学习】PyTorch深度学习训练可视化工具visdom

    PyTorch Author:louwill Machine Learning Lab 在进行深度学习实验时,能够可视化地对训练过程和结果进行展示是非常有必要的.除了Torch版本的TensorBoa ...

  3. 配置ubuntu20.04+anaconda+pytorch+ssh+win10+vscode远程深度学习训练环境

    目录 前言 服务端配置 安装ubuntu20.04 安装nvidia驱动 安装anaconda 安装pytorch 配置ssh 客户端 配置ssh 安装vscode 配置vscode插件 前言 本文主 ...

  4. PyTorch核心贡献者开源书:《使用PyTorch进行深度学习》完整版现已发布!

    来源|新智元 [导读]<使用PyTorch进行深度学习>一书的完整版现已发布!教你如何使用PyTorch创建神经网络和深度学习系统,内含图解与代码,操作易上手. 由Luca Antiga. ...

  5. 使用pytorch进行深度学习

    文章目录 使用pytorch进行深度学习 1. 深度学习构建模块:仿射变换, 非线性函数以及目标函数 1.1 仿射变换 1.2 非线性函数 1.3 Softmax和概率 1.4 目标函数 2. 优化和 ...

  6. 深度学习训练技巧总结

    参考: 1 技巧链接一!重要 技巧链接二!重要 技巧链接三!重要 模型训练技巧最直接的就是几个超参数的设置 根据图片大小来选择网络和超参数 如果图片不是很大比如3030,这种情况下做分类就不能用VGG ...

  7. 免费现场课程:使用PyTorch进行深度学习

    Are you interested in learning about Deep Learning? We are hosting a free 6-week live course on our ...

  8. MLPerf结果证实至强® 可有效助力深度学习训练

    MLPerf结果证实至强® 可有效助力深度学习训练 · 核心与视觉计算事业部副总裁Wei Li通过博客回顾了英特尔这几年为提升深度学习性能所做的努力. · 目前根据英特尔® 至强® 可扩展处理器的ML ...

  9. 基于NVIDIA GPUs的深度学习训练新优化

    基于NVIDIA GPUs的深度学习训练新优化 New Optimizations To Accelerate Deep Learning Training on NVIDIA GPUs 不同行业采用 ...

最新文章

  1. oracle按照时间过滤
  2. matlab字母随机排列,matlab_一组数据元素随机排列
  3. 磁盘格式化,磁盘挂载,手动增加swap空间
  4. mysql数据还原命令_mysql数据备份和还原命令:mysqldump
  5. 「软件测试」刚从腾讯面试出来,留下了这些面试笔记
  6. Function function 隐式function
  7. Linux基础,命令的使用以及环境的安装,jdk,mysql,tomcat
  8. twig模板基本学习
  9. vs2010创建动态库(亲测可行)
  10. Linux从入门到精通——数据库
  11. C#调用windows API实现 smallpdf客户端程序进行批量压缩
  12. 将MinimalLinux安装在U盘中
  13. QT的安装及环境配置
  14. 安装Mercurial进行版本管理
  15. 接口接收数据_基于原语的千兆以太网RGMII接口设计
  16. 移植emwin到stm32f205上卡死在gui_init();
  17. 新加坡政府企业架构:问题、实践和趋势(2008)
  18. Win10安装Centos8 Stream
  19. 无线通信中存在的远近效应、多普勒效应、多径效应以及其应对策略
  20. 计蒜客——恋爱纪念日(学习如何格式化打印日期)

热门文章

  1. 方阵的特征值和特征向量的求解案例(三阶方阵)
  2. 基于java的社区志愿者服务系统——计算机毕业设计
  3. 音频剪辑软件哪个好【资源分享】
  4. 编译器设计(十一)——标量优化
  5. ASTM D3475防打开测试认定标准
  6. 计算机科学与技术专业教学大纲,《计算机科学与技术专业》教学大纲
  7. 6 机器学习 IV与WOE 分箱 过抽样与欠抽样
  8. Jmeter性能测试2
  9. Windows命令操作
  10. AMD推出Radeon软件Adrenalin 21.3.1 WHQL驱动程序