PyTorch入门四-卷积神经网络
PyTorch的基础使用官方教程,主要描述了构建卷积神经网络
训练分类器
在已经知晓如何定义神经网络、计算损失和更新网络权重以后。 现在需要进一步思考
关于数据
通常而言,当你处理图像、文本、音频或者是视频数据是,你可以使用标准的python包,并加载到numpy中,之后你就可以将向量转换为torch.*Tensor
- 对于图像而言,使用诸如Pillow
- 对于音频而言,可使用scipy和librosa
- 对于文本而言,使用原生的Python或者Cython接口,或者是NLTK和SpaCy都是有效的
对于视觉领域而言,Torch创建了名为torchvision
的包,它拥有大多数数据集的数据加载方法,例如:ImageNet,CIFAR10,MNIST等,以及针对图片的数据转换器:torchvision.datasets
和torch.utils.data.DataLoader
这样为使用过程提供了巨大的便利,并避免了重复编写样板代码的问题
在这篇入门教程中,主要是使用CIFAR10数据集,它有:飞机
,轿车
,鸟
,猫
,鹿
,狗
,青蛙
,马
,船只
,卡车
共计十个类别。CIFAR-10数据集的尺寸都是3x32x32,也就是说3-通道的彩图,并且每个图片尺寸为32x32
cifar10
训练一个图像分类器
我们将遵循下列步骤: 1. 使用torchvision
加载并正则化CIFAR10训练和测试数据集 2. 定义一个卷积神经网络 3. 定义损失函数 4. 在训练数据集上训练网络 5. 在测试数据集上测试数据
加载并正则化CIFAR10数据
使用torchvision
将使得处理CIFAR10数据变得极其简单
1 | import torch |
torchvision数据集的输出是PILImage图片数据,取值范围处于[0,1],我们将转换这些张量并正则化为[-1,1]
1 | # compose表示计算的串联,步骤1,转换为张量;步骤2,Normalize((mean),(std))是将数据按照通道以mean和std进行正则化,即:input[channel] = (input[channel] - mean[channel]) / std[channel] |
Files already downloaded and verified
Files already downloaded and verified
让我们看下训练数据集
1 | import matplotlib.pyplot as plt |

定义一个卷积神经网络
可以从上篇复制网络结构过来,并将输入改为三个通道
1 | import torch.nn as nn |
定义一个损失函数和优化器
我们使用分类交叉熵损失和具有momentum迭代策略的SGD优化器
1 | import torch.optim as optim |
训练一个网络
从这里开始一切才变得有趣,我们简单的在数据迭代中进行循环,并将数据输入网络进行调整
1 | for epoch in range(2): #在数据集上重复循环多次 |
[1, 2000] loss: 2.185
[1, 4000] loss: 1.888
[1, 6000] loss: 1.699
[1, 8000] loss: 1.583
[1, 10000] loss: 1.515
[1, 12000] loss: 1.502
[2, 2000] loss: 1.416
[2, 4000] loss: 1.353
[2, 6000] loss: 1.353
[2, 8000] loss: 1.330
[2, 10000] loss: 1.334
[2, 12000] loss: 1.277
Finish Training
在测试集上测试模型
我们已经在训练集上将模型训练了两遍,但是我们还需要检查模型是否真的学习到了什么
我们将通过在神经网络输出结果比较标签是否正确,并与事实对照,如果预测结果是正确的,我们将把正确的结果放到一个列表中。
首先,我们展示一些测试集数据熟悉一下图片
1 | dataiter = iter(testloader) |

GroundTruth: cat ship ship plane
接下来让我们看下神经网络认为上述的图片是什么
1 | outputs = net(images) |
tensor([[-2.7341, -2.1010, 0.8536, 2.9584, -0.1055, 1.9402, 1.6559, -1.0969,
-1.1401, -1.6067],
[ 2.8572, 4.1361, -1.3402, -1.8916, -1.7792, -3.6649, -3.3518, -3.7235,
4.7233, 2.9778],
[ 1.3926, 2.4972, -0.5155, -1.1045, -1.4472, -1.9245, -2.2989, -1.4306,
2.1951, 1.9672],
[ 1.8752, -0.1371, 0.9561, -0.2573, 0.3003, -1.3104, -2.2200, -0.9442,
2.4067, -0.8872]], grad_fn=<AddmmBackward>)
输出的是10个类别的概率,越高的概率对应着神经网络所认为的类别,因此我们只需要最高可能性的即可
1 | _, predicted = torch.max(outputs, 1) |
Predicted: cat ship car ship
结果看上去非常的好
让我们再看下网络在整个数据集上的表现情况
1 | correct = 0 |
Accuracy of the network on the 10000 test images: 55 %
看了总比碰运气好,将近10%的准确性可以认为神经网络确实学到了一些东西
也许有些类别学的很好,但是有些学的不好:
1 | class_correct = list(0. for i in range(10)) |
Accuracy of plane : 60 %
Accuracy of car : 62 %
Accuracy of bird : 40 %
Accuracy of cat : 52 %
Accuracy of deer : 47 %
Accuracy of dog : 47 %
Accuracy of frog : 62 %
Accuracy of horse : 60 %
Accuracy of ship : 59 %
Accuracy of truck : 58 %
那么之后我们需要做什么?在GPU上如何加速?
在GPU上加速
正如将张量转移到GPU上一样,你也可以将神经网络转移到GPU上
如果CUDA可用,那么我首先将需要定义一个cuda可见的设备
1 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") |
cpu
接下来的章节,假定device
都是CUDA设备
然后这些方法将递归遍历所有模块并将其参数和缓冲区转换为CUDA张量:
1 | net.to(device) |
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)
)
请记住,您还必须将每一步的输入和目标发送到GPU:
1 | inputs, labels = inputs.to(device), labels.to(device) |
为什么我没有感到高速的加速呢?因为你的网络非常的小
练习:尝试增加网络的宽度(第一个nn.Conv2d的第二个参数和第二个nn.Conv2d的第一个参数 - 它们需要是相同的数字),看看你能获得什么样的加速。
在多个GPU上训练
如果您想使用所有GPU查看更多加速的内容,请查看Data Parallelism
本文标题:PyTorch入门四-卷积神经网络
文章作者:Hao Wang
发布时间:2019-04-11
最后更新:2022-06-19
原始链接:https://blog.waynehfut.com/2019/04/11/torch4/
版权声明:Copyright (C) 2022
分享