使用PyTorch训练一个图像分类器实例


Posted in Python onJanuary 08, 2020

如下所示:

import torch
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import numpy as np

print("torch: %s" % torch.__version__)
print("tortorchvisionch: %s" % torchvision.__version__)
print("numpy: %s" % np.__version__)

Out:

torch: 1.0.0
tortorchvisionch: 0.2.1
numpy: 1.15.4

数据从哪儿来?

通常来说,你可以通过一些python包来把图像、文本、音频和视频数据加载为numpy array。然后将其转换为torch.*Tensor。

图像。Pillow、OpenCV是用得比较多的

音频。scipy和librosa

文本。纯Python或者Cython就可以完成数据加载,可以在NLTK和SpaCy找到数据

对于计算机视觉而言,我们有torchvision包,它可以用来加载一下常用数据集如Imagenet、CIFAR10、MINIST等等,也有一些常用的为图像准备数据转换例如torchvision.datasets和torch.utils.data.DataLoader。

这次的教程中,我们使用CIFAR10数据集,他有‘airplane', ‘automobile', ‘bird', ‘cat', ‘deer', ‘dog', ‘frog', ‘horse', ‘ship', ‘truck'这几个类别的图像。图像大小都是3x32x32的。也就是说,图像都是三通道的,每一张图的尺寸都是32x32。

使用PyTorch训练一个图像分类器实例

训练一个图像分类器

步骤如下:

使用torchvision加载、归一化训练集和测试集

定义卷积神经网络

定义损失函数

使用训练集训练网络

使用测试集测试网络

1. 加载、归一化CIFAR10

我们可以使用torchvision很轻松的完成

torchvision的数据集是基于PILImage的,数值是[0, 1],我们需要将其转成范围为[-1, 1]的Tensor

transform = transforms.Compose([
  transforms.ToTensor(),
  transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])

trainset = torchvision.datasets.CIFAR10(root='./data', train=True, 
                    download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, 
                     shuffle=True, num_workers=4)

testset = torchvision.datasets.CIFAR10(root='./data', train=False, 
                    download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=4, 
                     shuffle=True, num_workers=4)
classes = ('plane', 'car', 'bird', 'cat', 
      'deer', 'dog', 'frog', 'horse', 'ship', 'truck')

Out:

Downloading https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz to ./data/cifar-10-python.tar.gz
Files already downloaded and verified

让我们来看看训练集的图片

# 显示一张图片
def imshow(img):
  img = img / 2 + 0.5   # 逆归一化
  npimg = img.numpy()
  plt.imshow(np.transpose(npimg, (1, 2, 0)))
  plt.show()


# 任意地拿到一些图片
dataiter = iter(trainloader)
images, labels = dataiter.next()

# 显示图片
imshow(torchvision.utils.make_grid(images))
# 显示类标
print(' '.join('%5s' % classes[labels[j]] for j in range(4)))

Out:

使用PyTorch训练一个图像分类器实例

truck  dog ship  dog

2. 定义卷积神经网络

可以直接复制神经网络的代码,修改里面的几层即可。

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(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 = x.view(-1, 16 * 5 * 5)
    x = F.relu(self.fc1(x))
    x = F.relu(self.fc2(x))
    x = self.fc3(x)
    return x

net = Net()

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

使用多分类交叉熵损失函数,和带有momentum的SGD作为优化器

import torch.optim as optim

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=1e-3, momentum=0.9)

4. 训练网络

我们直接使用循环语句遍历数据集即可完成训练

nums_epoch = 2
for epoch in range(nums_epoch):
  _loss = 0.0
  for i, (inputs, labels) in enumerate(trainloader, 0):
    inputs, labels = inputs.to(device), labels.to(device)
    optimizer.zero_grad()
    
    outputs = net(inputs)
    loss = criterion(outputs, labels)
    loss.backward()
    optimizer.step()
    
    _loss += loss.item()
    if i % 2000 == 1999:  # 每2000步打印一次损失值
      print('[%d, %5d] loss: %.3f' %
         (epoch + 1, i + 1, _loss / 2000))
      _loss = 0.0

print('Finished Training')

Out:

[1, 2000] loss: 1.178
[1, 4000] loss: 1.200
[1, 6000] loss: 1.168
[1, 8000] loss: 1.175
[1, 10000] loss: 1.185
[1, 12000] loss: 1.165
[2, 2000] loss: 1.073
[2, 4000] loss: 1.066
[2, 6000] loss: 1.100
[2, 8000] loss: 1.107
[2, 10000] loss: 1.083
[2, 12000] loss: 1.103
Finished Training

5. 测试网络

这个网络已经训练了两个epoch,我们现在来看看这个网络是不是学到了一些什么东西。

我们让这个神经网络预测几张图片,看看它的答案与真实答案的差别。

下面我们选取一些测试数据集中的数据,看看他们的真实标签。

# 展示测试数据集
dataiter = iter(testloader)
images, labels = dataiter.next()
imshow(torchvision.utils.make_grid(images))
print('GraoundTruth: ', ' '.join(['%5s' % classes[labels[j]] for j in range(4)]))

Out:

使用PyTorch训练一个图像分类器实例

GraoundTruth:  ship ship deer ship

接着我们让神经网络来给出预测标签

神经网络的输出是10个信号值,信号值最高的那个神经元表示整个网络的预测值,所以我们需要拿到信号最强的那个节点的索引值

# 展示预测值
outputs = net(images)
_, predicted = torch.max(outputs, 1)
print('Predicted: ', ' '.join(['%5s' % classes[predicted[j]] for j in range(4)]))

Out:

Predicted:  car ship horse ship

下面我们对整个测试集做一次评估:

# 评估测试数据集
correct, total = 0, 0
with torch.no_grad():
  for images, labels in testloader:
    outputs = net(images)
    _, predicted = torch.max(outputs, 1)
    total += labels.size(0)
    correct += (labels == predicted).sum().item()
  
print('Accuracy of the network on the 10000 test images: %d %%' % (
  100 * correct / total))

Out:

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

整个结果比随机猜要好得多(随机猜是10%的概率)。看来我们的神经网络还是学到了点东西。

下面我们来看看它在哪一个类别的分类上做得最好:

# 按类标评估
n_classes = len(classes)
class_correct, class_total = [0]*n_classes, [0]* n_classes

with torch.no_grad():
  for images, labels in testloader:
    outputs = net(images)
    _, predicted = torch.max(outputs, 1)
    is_correct = (labels == predicted).squeeze()
    for i in range(len(labels)):
      label = labels[i]
      class_total[label] += 1
      class_correct[label] += is_correct[i].item()

for i in range(n_classes):
  print('Accuracy of %5s: %.2f %%' % (
    classes[i], 100.0 * class_correct[i] / class_total[i]
  ))

Out:

Accuracy of plane: 67.00 %
Accuracy of  car: 71.50 %
Accuracy of bird: 55.20 %
Accuracy of  cat: 45.60 %
Accuracy of deer: 38.20 %
Accuracy of  dog: 47.00 %
Accuracy of frog: 78.80 %
Accuracy of horse: 55.90 %
Accuracy of ship: 72.70 %
Accuracy of truck: 57.50 %

在GPU上训练

就像把Tensor从CPU转移到GPU一样,神经网络也可以转移到GPU上

首先需要检查是否有可用的GPU

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# 假设我们在支持CUDA的机器上,我们可以打印出CUDA设备:

print(device)

Out:

cuda:0

我们假设device已经是CUDA设备了

下面命令将递归的将所有模块和参数、缓存转移到CUDA设备上去

net.to(device)

Out:

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上

并且,需要重新实例化优化器,否则会报错

inputs, labels = inputs.to(device), labels.to(device)

练习:尝试增加神经网络的宽度。第一个nn.Conv2d的第二个参数和第二个nn.Conv2d的第一个参数的值必须一样。看看会有什么样的效果。

以上这篇使用PyTorch训练一个图像分类器实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python遍历numpy数组的实例
Apr 04 Python
python3使用smtplib实现发送邮件功能
May 22 Python
Python实现FM算法解析
Jun 18 Python
用Python配平化学方程式的方法
Jul 20 Python
python 计算积分图和haar特征的实例代码
Nov 20 Python
使用Python画出小人发射爱心的代码
Nov 23 Python
基于python实现MQTT发布订阅过程原理解析
Jul 27 Python
基于python requests selenium爬取excel vba过程解析
Aug 12 Python
sqlalchemy实现时间列自动更新教程
Sep 02 Python
Django windows使用Apache实现部署流程解析
Oct 12 Python
Pycharm编辑器功能之代码折叠效果的实现代码
Oct 15 Python
python3 sqlite3限制条件查询的操作
Apr 07 Python
pytorch 实现将自己的图片数据处理成可以训练的图片类型
Jan 08 #Python
pytorch下大型数据集(大型图片)的导入方式
Jan 08 #Python
Python 实现训练集、测试集随机划分
Jan 08 #Python
Pyecharts绘制全球流向图的示例代码
Jan 08 #Python
PyTorch 解决Dataset和Dataloader遇到的问题
Jan 08 #Python
使用PyTorch将文件夹下的图片分为训练集和验证集实例
Jan 08 #Python
使用 PyTorch 实现 MLP 并在 MNIST 数据集上验证方式
Jan 08 #Python
You might like
在mysql数据库原有字段后增加新内容
2009/11/26 PHP
php中函数的形参与实参的问题说明
2010/09/01 PHP
PHP将HTML转换成文本的实现代码
2015/01/21 PHP
thinkPHP5.0框架应用请求生命周期分析
2017/03/25 PHP
php如何把表单内容提交到数据库
2019/07/08 PHP
Web前端设计模式  制作漂亮的弹出层
2010/10/29 Javascript
Jquery中扩展方法extend使用技巧
2014/08/24 Javascript
jQuery中click事件的定义和用法
2014/12/20 Javascript
JavaScript中用let语句声明作用域的用法讲解
2016/05/20 Javascript
jquery插件uploadify多图上传功能实现代码
2016/08/12 Javascript
简单理解vue中实例属性vm.$els
2016/12/01 Javascript
基于JavaScript实现的快速排序算法分析
2017/04/14 Javascript
Bootstrap输入框组件使用详解
2017/06/09 Javascript
详解小程序输入框闪烁及重影BUG解决方案
2018/08/31 Javascript
Nautil 中使用双向数据绑定的实现
2019/10/02 Javascript
JS实现压缩上传图片base64长度功能
2019/12/03 Javascript
在 Vue 中使用 JSX 及使用它的原因浅析
2020/02/10 Javascript
vant组件中 dialog的确认按钮的回调事件操作
2020/11/04 Javascript
[01:13:51]TNC vs Serenity 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
Python实现将16进制字符串转化为ascii字符的方法分析
2017/07/21 Python
python、java等哪一门编程语言适合人工智能?
2017/11/13 Python
matplotlib实现热成像图colorbar和极坐标图的方法
2018/12/13 Python
python调用c++传递数组的实例
2019/02/13 Python
Django 查询数据库并返回页面的例子
2019/08/12 Python
python中return如何写
2020/06/18 Python
python中最小二乘法详细讲解
2021/02/19 Python
幼儿园教师考核制度
2014/02/01 职场文书
大学生两会学习心得体会
2014/03/10 职场文书
党员先锋岗事迹材料
2014/05/08 职场文书
领导干部作风整顿个人剖析材料
2014/10/11 职场文书
房屋买卖协议样本
2014/11/16 职场文书
护理专业自我评价
2015/03/11 职场文书
2015年技术员工作总结
2015/04/10 职场文书
摩登时代观后感
2015/06/03 职场文书
干货:我将这样书写我的演讲稿!
2019/05/09 职场文书
win sever 2022如何占用操作主机角色
2022/06/25 Servers