使用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 相关文章推荐
haskell实现多线程服务器实例代码
Nov 26 Python
使用Python判断IP地址合法性的方法实例
Mar 13 Python
深入解析Python中的WSGI接口
May 11 Python
Python的Django框架下管理站点的基本方法
Jul 17 Python
5个很好的Python面试题问题答案及分析
Jan 19 Python
解决python3中解压zip文件是文件名乱码的问题
Mar 22 Python
python的set处理二维数组转一维数组的方法示例
May 31 Python
详解Selenium+PhantomJS+python简单实现爬虫的功能
Jul 14 Python
tensorflow 实现打印pb模型的所有节点
Jan 23 Python
python求最大公约数和最小公倍数的简单方法
Feb 13 Python
Django实现随机图形验证码的示例
Oct 15 Python
scrapy redis配置文件setting参数详解
Nov 18 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
常用的php图片处理类(水印、等比缩放、固定高宽)分享
2015/06/19 PHP
ThinkPHP自定义函数解决模板标签加减运算的方法
2015/07/03 PHP
php reset() 函数指针指向数组中的第一个元素并输出实例代码
2016/11/21 PHP
网页中CDATA标记的说明
2010/09/12 Javascript
JavaScript的parseInt 取整使用
2011/05/09 Javascript
JQuyer $.post 与 $.ajax 访问WCF ajax service 时的问题需要注意的地方
2011/09/20 Javascript
JS操作iframe里的dom(实例讲解)
2014/01/29 Javascript
JS建造者模式基本用法实例分析
2015/06/30 Javascript
在JavaScript中对HTML进行反转义详解
2016/05/18 Javascript
ES6正则的扩展实例详解
2017/04/25 Javascript
Vue侧滑菜单组件——DrawerLayout
2017/12/18 Javascript
在vue项目中,使用axios跨域处理
2018/03/07 Javascript
从零使用TypeScript开发项目打包发布到npm
2020/02/14 Javascript
卸载vue2.0并升级vue_cli3.0的实例讲解
2020/02/16 Javascript
python在命令行下使用google翻译(带语音)
2014/01/16 Python
python脚本监控docker容器
2016/04/27 Python
Python匹配中文的正则表达式
2016/05/11 Python
Django添加sitemap的方法示例
2018/08/06 Python
详解Django-auth-ldap 配置方法
2018/12/10 Python
Python 装饰器@,对函数进行功能扩展操作示例【开闭原则】
2019/10/17 Python
python 两个数据库postgresql对比
2019/10/21 Python
安装Pycharm2019以及配置anconda教程的方法步骤
2019/11/11 Python
使用PyWeChatSpy自动回复微信拍一拍功能的实现代码
2020/07/02 Python
python闭包与引用以及需要注意的陷阱
2020/09/18 Python
用Python制作音乐海报
2021/01/26 Python
使用CSS3实现字体颜色渐变的实现
2020/08/10 HTML / CSS
Canvas与图片压缩的示例代码
2017/11/28 HTML / CSS
利用Node实现HTML5离线存储的方法
2020/10/16 HTML / CSS
计算机科学与技术应届生求职信
2013/11/07 职场文书
工业设计专业自荐书
2014/06/05 职场文书
员工趣味活动方案
2014/08/27 职场文书
公民授权委托书范本
2014/09/17 职场文书
党的群众路线教育实践活动个人批评与自我批评
2014/10/16 职场文书
Python使用scapy模块发包收包
2021/05/07 Python
vue使用节流函数的踩坑实例指南
2021/05/20 Vue.js
PostgreSQL事务回卷实战案例详析
2022/03/25 PostgreSQL