前言

学习pytorch已经一周了,pytorch官网的示例代码基本上都敲了一遍,关于tensor的使用,数据集,网络定义等。和之前学习caffe痛苦的经历相比,pytorch对常用的操作都进行了封装,只要安装流程做即可。在之前的学习基础上,本章节内容将在CIFAR10数据集上训练一个简单的CNN网络。

目的

基于CIFAR-10数据集,训练一个简单CNN网络。

保存训练好的模型,测试

使用GPU训练

开发/实验环境

Ubuntu 18.04

pytorch 1.0

Anaconda3, python3.6

pycharm

CIFAR数据集

The CIFAR-10 and CIFAR-100 are labeled subsets of the 80 million tiny images dataset. They were collected by Alex Krizhevsky, Vinod Nair, and Geoffrey Hinton.

CIFAR数据集可分为CIFAR10, CIFAR100。 CIFAR-10是指包含10个种类, CIFAR-100包含100个种类。

CIFAR-10

The CIFAR-10 dataset consists of 60000 32x32 colour images in 10 classes, with 6000 images per class. There are 50000 training images and 10000 test images.

特点:

32x32 彩色图像

10个类别

总共60000张图像

50000张训练样本 + 10000张测试样本

每个类别有6000张图像, 10 x 6000 = 60000

10个类别:

airplane

automobile

bird

cat

deer

dog

frog

horse

ship

truck

image.png

实验过程

准备数据集

这一步骤在pytorch中非常方便,pytorch已经为我们准备好了常见的数据集合,只需要导入即可。

数据集在torchvision.dataset 包里面

import torch

import torchvision

import torchvision.transforms as transforms

from torch.utils.data import DataLoader

import torch.nn as nn

import torch.nn.functional as F

import torch.optim as optim

import matplotlib.pyplot as plt

import numpy as np

torchvision.dataset.CFAIR10 是一个类, 通过实例化该类的一个对象,就可以操作数据集。

参数:

root -----数据集下载后保存的路径

train-----训练or测试

download----是否需要自动下载

transform----对图像进行变换, 一般需要对原始图像进行ToTensor(), Normalize()变换

之后,使用DataLoader类对数据集进行包装,目的是为了方便读取和使用,比如可以min_batch读取, 采用多线程。

# --------------------准备数据集------------------

# Dataset, DataLoader

transform = transforms.Compose(

[transforms.ToTensor(),

transforms.Normalize((0.5, 0.5, 0.5), std =(0.5, 0.5, 0.5))])

trainset = torchvision.datasets.CIFAR10(root='./data', train=True,

download=True, transform=transform)

testset = torchvision.datasets.CIFAR10(root='./data',train=False,

transform=transform, download=True)

trainloader = DataLoader(dataset=trainset, batch_size=4, shuffle=True, num_workers=4)

testloader = DataLoader(dataset=testset, batch_size=4, shuffle=True, num_workers=4)

#

dataiter = iter(trainloader)

images, labels = dataiter.next()

imshow(torchvision.utils.make_grid(images))

# print labels

print(' '.join('%5s' % classes[labels[j]] for j in range(4)))

随机显示一个min_batch的图像,batch=4

image.png

标签:

image.png

至此,数据集就准备OK,下面开始定义一个网络。

定义CNN网络

简单起见,采用LeNet网络,将第一个卷积层的输入通道改为3,因为CIFAR-10是彩色3通道图像。

#定义一个简单的网络

# LeNet -5

class Net(nn.Module):

def __init__(self):

super(Net, self).__init__()

self.conv1 = nn.Conv2d(in_channels=3, out_channels=6, kernel_size=5)

self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)

self.conv2 = nn.Conv2d(in_channels=6, out_channels=16, kernel_size=5)

self.fc1 = nn.Linear(in_features=16 * 5 * 5,out_features=120)

self.fc2 = nn.Linear(in_features=120, out_features=84)

self.fc3 = nn.Linear(in_features=84, out_features=10)

def forward(self, x):

x = self.pool1(F.relu(self.conv1(x)))

x = self.pool1(F.relu(self.conv2(x)))

x = x.view(-1, 16 * 5 * 5) # reshape tensor

x = F.relu(self.fc1(x))

x = F.relu(self.fc2(x))

x = self.fc3(x)

return x

设置网络的优化、迭代方法,训练网络

CNN网络训练本质上就是对一个目标函数(损失函数)求最小的问题,在数学中,对于一般的凸函数,优化方法有梯度下降法、牛顿法等。(除此之外还有启发式搜索,比如遗传算法等)。 对于神经网络的训练,常用的优化方法为随机梯度下降法SGD。

定义损失函数,优化方法

采用交叉熵损失函数

采用SGD随机梯度下降法进行优化(带动量项)

# 定义损失函数,优化方法

# 采用Cross-Entropy loss, SGD with moment

criterion = nn.CrossEntropyLoss()

optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

进行迭代优化,训练

之前学习caffe时候,终于搞清楚2个概念。

Iter------一次迭代,是指一个min_batch的一次forward+backward

Epoch------迭代完所有的训练数据(1次),称为一个epoch

这里总共跑20个epoch。

# 训练网络

# 迭代epoch

for epoch in range(20):

running_loss = 0.0

for i, data in enumerate(trainloader, 0):

# get the input

inputs, labels = data

# zeros the paramster gradients

optimizer.zero_grad() #

# forward + backward + optimize

outputs = net(inputs)

loss = criterion(outputs, labels) # 计算loss

loss.backward() # loss 求导

optimizer.step() # 更新参数

# print statistics

running_loss += loss.item() # tensor.item() 获取tensor的数值

if i % 2000 == 1999:

print('[%d, %5d] loss: %.3f' %

(epoch + 1, i + 1, running_loss / 2000)) # 每2000次迭代,输出loss的平均值

running_loss = 0.0

print('Finished Training')

训练过程:

1.png

2.png

3.png

可以看到,loss值不断下降。因为本人采用CPU,所以地只跑了20个epoch。

保存模型

# --------保存模型-----------

torch.save(net, './model/model_cfair10_2.pth') # 保存整个模型,体积比较大

# torch.save(net.state_dict(), './model/model_cfair10.pth')

image.png

测试模型

import torch

import torchvision

import torchvision.transforms as transforms

from torch.utils.data import DataLoader

import torch.nn as nn

import torch.nn.functional as F

import torch.optim as optim

import matplotlib.pyplot as plt

import numpy as np

from PIL import Image

CIFAR-10总共包含10个类别:

CFAIR10_names = ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'forg', 'horse', 'ship', 'truck']

载入一张图像,RBG,要属于上述类别的某一类,不然识别不出来

# load a image

image = Image.open('/xxxx/image/dog.jpg')

对图像进行相同的变换:

transform = transforms.Compose(

[transforms.Resize((32, 32)),

transforms.ToTensor(),

transforms.Normalize(

mean=(0.5, 0.5, 0.5),

std=(0.5, 0.5, 0.5)

)])

image_transformed = transform(image)

print(image_transformed.size())

需要注意的地方

CNN网络的输入为4D Tensor (NxCxHxW), 转换之后的图像需要变换为4D

torsor1.unsqueeze(0) 即可增加一个维度,这样输入的tensor为: 1x3x32x32

#

transform = transforms.Compose(

[transforms.Resize((32, 32)),

transforms.ToTensor(),

transforms.Normalize(

mean=(0.5, 0.5, 0.5),

std=(0.5, 0.5, 0.5)

)])

image_transformed = transform(image)

print(image_transformed.size())

class Net(nn.Module):

def __init__(self):

super(Net, self).__init__()

self.conv1 = nn.Conv2d(in_channels=3, out_channels=6, kernel_size=5)

self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)

self.conv2 = nn.Conv2d(in_channels=6, out_channels=16, kernel_size=5)

self.fc1 = nn.Linear(in_features=16 * 5 * 5,out_features=120)

self.fc2 = nn.Linear(in_features=120, out_features=84)

self.fc3 = nn.Linear(in_features=84, out_features=10)

def forward(self, x):

x = self.pool1(F.relu(self.conv1(x)))

x = self.pool1(F.relu(self.conv2(x)))

x = x.view(-1, 16 * 5 * 5) # reshape tensor

x = F.relu(self.fc1(x))

x = F.relu(self.fc2(x))

x = self.fc3(x)

return x

net = torch.load('./model/model_cfair10.pth')

# print(net)

image_transformed = image_transformed.unsqueeze(0)

output = net(image_transformed)

predict_value, predict_idx = torch.max(output, 1) # 求指定维度的最大值,返回最大值以及索引

plt.figure()

plt.imshow(np.array(image))

plt.title(CFAIR10_names[predict_idx])

plt.axis('off')

plt.show()

测试结果:

识别正确

i识别正确

识别正确

识别错误

识别正确

GPU训练、模型学习率调整

问题:

采用CPU模型训练了20个Epoch之后,loss下降到了0.6左右,后来在之前训练的基础上迭代了20个Epoch,发现loss处于0.5~0.6之间。

CPU上训练确实很慢,跑20个Epoch基本上用了1h多(具体时间不记得),比较漫长。

使用GPU训练模型

计算机配置 GPU: 1080

首先,需要安装GPU版本的pytorch, 具体安装步骤pytorch官网有。使用GPU训练需要对代码做一些小调整。

step1:在代码中,首先使用pytorch中的函数判断是否支持GPU

is_support = torch.cunda.is_available()

if is_support:

device = torch.device('cuda:0')

# device = torch.device('cuda:1')

else:

device = torch.device('cpu')

step2: 将CPU上的计算转移到GPU上

net = Net()

net.to(device) # GPU模式需要添加

# 训练网络

# 迭代epoch

for epoch in range(20):

running_loss = 0.0

for i, data in enumerate(trainloader, 0):

# get the input

inputs, labels = data

inputs = inputs.to(device) # GPU计算

labels = labels.to(device) # GPU计算

# zeros the paramster gradients

optimizer.zero_grad() #

# forward + backward + optimize

outputs = net(inputs)

loss = criterion(outputs, labels) # 计算loss

loss.backward() # loss 求导

optimizer.step() # 更新参数

# print statistics

running_loss += loss.item() # tensor.item() 获取tensor的数值

if i % 2000 == 1999:

print('[%d, %5d] loss: %.3f' %

(epoch + 1, i + 1, running_loss / 2000)) # 每2000次迭代,输出loss的平均值

running_loss = 0.0

print('Finished Training')

run, 会发现迭代速度飞起,10min左右就可以完成20个Epoch迭代,速度非常快。

学习率调整

随机梯度下降法SGD重要的一个参数是:学习率 leaning_rate

上面的代码采用的是固定学习率lr=0.001,。 刚开始迭代时候,学习率可以大一些,这样收敛速度快,随着迭代次数增加,学习率应该减小防止loss震荡。

简单起见,本人将学习率调整为lr=0.0001,然后在之前模型的基础上迭代20个Epoch。明显发现Loss变为0.3, 0.2, 0.1。

GPU模型测试结果

测试正确

测试正确

测试错误

测试错误

测试正确

测试正确

虽然采用GPU训练, lr减小为0.0001, loss也减少了(训练集loss)。 在测试中,1个horse识别为deer, bird识别为cat。 因为,要训练到一个适合模型,还需要其他策略,包括采用其他网络模型。

在整个测试集上评价模型性能

计算Acc

import torch

import torchvision

import torchvision.transforms as transforms

from torch.utils.data import DataLoader

import torch.nn as nn

import torch.nn.functional as F

import torch.optim as optim

import matplotlib.pyplot as plt

import numpy as np

from PIL import Image

CFAIR10_names = ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'forg', 'horse', 'ship', 'truck']

# --------------测试数据集------------------------------

transform = transforms.Compose(

[transforms.Resize((32, 32)),

transforms.ToTensor(),

transforms.Normalize(

mean=(0.5, 0.5, 0.5),

std=(0.5, 0.5, 0.5)

)])

testset = torchvision.datasets.CIFAR10(root='./data', train=False,

download=True, transform=transform)

testloader = torch.utils.data.DataLoader(testset, batch_size=4,

shuffle=False, num_workers=4)

# -----------------网咯模型-------------------------------

class Net(nn.Module):

def __init__(self):

super(Net, self).__init__()

self.conv1 = nn.Conv2d(in_channels=3, out_channels=6, kernel_size=5)

self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)

self.conv2 = nn.Conv2d(in_channels=6, out_channels=16, kernel_size=5)

self.fc1 = nn.Linear(in_features=16 * 5 * 5,out_features=120)

self.fc2 = nn.Linear(in_features=120, out_features=84)

self.fc3 = nn.Linear(in_features=84, out_features=10)

def forward(self, x):

x = self.pool1(F.relu(self.conv1(x)))

x = self.pool1(F.relu(self.conv2(x)))

x = x.view(-1, 16 * 5 * 5) # reshape tensor

x = F.relu(self.fc1(x))

x = F.relu(self.fc2(x))

x = self.fc3(x)

return x

net = torch.load('./model/model_cfair10_20.pth',map_location='cpu')

# ------------在整个测试集上测试-------------------------------------------

correct = 0

total = 0

count = 0

with torch.no_grad():

for sample_batch in testloader:

images = sample_batch[0]

labels = sample_batch[1]

# forward

out = net(images)

#

_, pred = torch.max(out, 1)

correct += (pred == labels).sum().item()

total += labels.size(0)

print('batch:{}'.format(count + 1))

count += 1

#

# Acc

accuracy = float(correct) / total

print('Acc = {:.5f}'.format(accuracy))

自己训练的模型,采用GPU, 学习率中途调整过一次:

image.png

End

通过这个完整的例子,学习到了不少内容。关于GPU的使用,这里只是简单的应用,还没有使用多块GPU加速训练。后续,再接再厉,学习GPU加速,CNN调参。

pytorchgpu测试_pytorch学习(十)—训练并测试CNN网络相关推荐

  1. 从零开始的深度学习(一) 经典CNN网络 LeNet-5

    从零开始的深度学习(一) 经典CNN网络 LeNet-5 之前的四篇博客围绕着一个大作业项目来进行的入门,由于小白初涉,因此行文中有时侧重于某些并不重要的东西,同时也忽略了许多其实蛮重要的东西,再加上 ...

  2. 【Pytorch分布式训练】在MNIST数据集上训练一个简单CNN网络,将其改成分布式训练

    文章目录 普通单卡训练-GPU 普通单卡训练-CPU 分布式训练-GPU 分布式训练-CPU 租GPU服务器相关 以下代码示例基于:在MNIST数据集上训练一个简单CNN网络,将其改成分布式训练. 普 ...

  3. idea2020.2中@test是怎么测试的_Sklearn 划分训练集和测试集

    [从零开始学机器学习第 03 篇] 摘要:手写 Sklearn 的 train_test_split 函数. 之前两篇文章以酒吧的红酒故事引出了 kNN 分类算法,根据已倒好的酒(样本),预测新倒的酒 ...

  4. 直播分享|邓文彬:如何在GPU/CPU/移动端高效训练和推断CNN网络

    | 极市线上分享 第35期 | ➤活动信息 主题:如何在GPU/CPU/移动端高效训练CNN网络 (看TEE AI算力棒在计算机视觉训练和推断的最新突破) 时间:本周四(11月15日)晚20:00~2 ...

  5. 信息学奥赛学习、训练、测试的顺序,思路及方法

    信奥学习的方法其实很简单 和学其他的学科是差不多的思路.方法和过程 1.预习(在上课的时候可以带着问题来听课) 2.课上认真听讲 良好的开端是成功的一半 3.教师讲完了相关的知识点后课上会带着学生做一 ...

  6. 1.5 训练/开发/测试集划分-深度学习第三课《结构化机器学习项目》-Stanford吴恩达教授

    ←上一篇 ↓↑ 下一篇→ 1.4 满足和优化指标 回到目录 1.6 开发集合测试集的大小 训练/开发/测试集划分 (Train/Dev/Test Distribution) 设立训练集,开发集和测试集 ...

  7. (五)如何训练和测试AI语言翻译系统

    目录 介绍 使用 LST单元进行训练和测试 现在有自我注意 下一步 在这里,我们将创建一个Keras标记器,它将从平行语料库中找到的单词中构建一个内部词汇表,使用Jupyter notebook训练和 ...

  8. 数据标准化常见问题:对整个数据集数据标准化后再划分训练集、测试集和先对训练级标准化再将规则用于测试集有什么区别(Python实现)

    在数据分析与挖掘.算法建模的都会用到数据标准化.数据的标准化(normalization)是将数据按比例缩放,使之落入一个小的特定区间.在某些比较和评价的指标处理中经常会用到,去除数据的单位限制,将其 ...

  9. [源码解析] 深度学习分布式训练框架 horovod (10) --- run on spark

    [源码解析] 深度学习分布式训练框架 horovod (10) - run on spark 文章目录 [源码解析] 深度学习分布式训练框架 horovod (10) --- run on spark ...

最新文章

  1. Imec推出高性能芯片的低成本冷却解决方案
  2. swift基础--变量
  3. Xamarin.FormsShell基础教程(8)Shell的模版构成
  4. 数据中心大火波及360万网站,或因UPS故障,3月10日晚法国斯特拉斯堡
  5. 启动rabbitmq,提示ERROR: node with name rabbit already running on localhost(亲测)
  6. Android实例-拍摄和分享照片、分享文本(XE8+小米2)
  7. ScheduledExecutorService线程调度的使用
  8. 手势UIGestureRecognizer
  9. eclise,myeclise,sts 打叉但是没提示解决办法
  10. linux的ftp指令发邮件,三种使用Linux命令发送邮件
  11. 【SICP练习】123 练习3.54
  12. [转载]Informix平安特征庇护数据的详细方法
  13. mysql 6.17,mysql小结篇2(17.6.27)
  14. ubuntu系统计算机_显卡-性能测试软件
  15. Android App图标尺寸
  16. 五金模具设计统赢外挂提升效率技巧、外挂模具设计流程的问题归纳
  17. react引入html2canvas和jspdf生成PDF打印及下载
  18. 北大三日游游记(北大信科暑期课堂)
  19. 移动端手机 摇一摇加声音
  20. 开心一刻:今天下班后,我尾随一女同事,为她充当护花使者

热门文章

  1. linux ACL应用学习
  2. Bash Shell 的一些语法
  3. linux chown命令: 修改文件或目录的所有者或群组
  4. 认识 URL 及其编码
  5. 《Java程序设计》第4周学习总结
  6. linux 设置ssh免密登录
  7. nyoj 56 阶乘中素数的个数
  8. Linux之|etc|group文件
  9. idea建springcloud项目_idea创建springcloud项目图文教程(EurekaServer注册中心)
  10. 写给Git初学者的7个建议