PyTorch上实现卷积神经网络CNN的方法


Posted in Python onApril 28, 2018

一、卷积神经网络

卷积神经网络(ConvolutionalNeuralNetwork,CNN)最初是为解决图像识别等问题设计的,CNN现在的应用已经不限于图像和视频,也可用于时间序列信号,比如音频信号和文本数据等。CNN作为一个深度学习架构被提出的最初诉求是降低对图像数据预处理的要求,避免复杂的特征工程。在卷积神经网络中,第一个卷积层会直接接受图像像素级的输入,每一层卷积(滤波器)都会提取数据中最有效的特征,这种方法可以提取到图像中最基础的特征,而后再进行组合和抽象形成更高阶的特征,因此CNN在理论上具有对图像缩放、平移和旋转的不变性。

卷积神经网络CNN的要点就是局部连接(LocalConnection)、权值共享(WeightsSharing)和池化层(Pooling)中的降采样(Down-Sampling)。其中,局部连接和权值共享降低了参数量,使训练复杂度大大下降并减轻了过拟合。同时权值共享还赋予了卷积网络对平移的容忍性,池化层降采样则进一步降低了输出参数量并赋予模型对轻度形变的容忍性,提高了模型的泛化能力。可以把卷积层卷积操作理解为用少量参数在图像的多个位置上提取相似特征的过程。

二、代码实现

import torch 
import torch.nn as nn 
from torch.autograd import Variable 
import torch.utils.data as Data 
import torchvision 
import matplotlib.pyplot as plt 
 
torch.manual_seed(1) 
 
EPOCH = 1 
BATCH_SIZE = 50 
LR = 0.001 
DOWNLOAD_MNIST = True 
 
# 获取训练集dataset 
training_data = torchvision.datasets.MNIST( 
       root='./mnist/', # dataset存储路径 
       train=True, # True表示是train训练集,False表示test测试集 
       transform=torchvision.transforms.ToTensor(), # 将原数据规范化到(0,1)区间 
       download=DOWNLOAD_MNIST, 
       ) 
 
# 打印MNIST数据集的训练集及测试集的尺寸 
print(training_data.train_data.size()) 
print(training_data.train_labels.size()) 
# torch.Size([60000, 28, 28]) 
# torch.Size([60000]) 
 
plt.imshow(training_data.train_data[0].numpy(), cmap='gray') 
plt.title('%i' % training_data.train_labels[0]) 
plt.show() 
 
# 通过torchvision.datasets获取的dataset格式可直接可置于DataLoader 
train_loader = Data.DataLoader(dataset=training_data, batch_size=BATCH_SIZE, 
                shuffle=True) 
 
# 获取测试集dataset 
test_data = torchvision.datasets.MNIST(root='./mnist/', train=False) 
# 取前2000个测试集样本 
test_x = Variable(torch.unsqueeze(test_data.test_data, dim=1), 
         volatile=True).type(torch.FloatTensor)[:2000]/255 
# (2000, 28, 28) to (2000, 1, 28, 28), in range(0,1) 
test_y = test_data.test_labels[:2000] 
 
class CNN(nn.Module): 
  def __init__(self): 
    super(CNN, self).__init__() 
    self.conv1 = nn.Sequential( # (1,28,28) 
           nn.Conv2d(in_channels=1, out_channels=16, kernel_size=5, 
                stride=1, padding=2), # (16,28,28) 
    # 想要con2d卷积出来的图片尺寸没有变化, padding=(kernel_size-1)/2 
           nn.ReLU(), 
           nn.MaxPool2d(kernel_size=2) # (16,14,14) 
           ) 
    self.conv2 = nn.Sequential( # (16,14,14) 
           nn.Conv2d(16, 32, 5, 1, 2), # (32,14,14) 
           nn.ReLU(), 
           nn.MaxPool2d(2) # (32,7,7) 
           ) 
    self.out = nn.Linear(32*7*7, 10) 
 
  def forward(self, x): 
    x = self.conv1(x) 
    x = self.conv2(x) 
    x = x.view(x.size(0), -1) # 将(batch,32,7,7)展平为(batch,32*7*7) 
    output = self.out(x) 
    return output 
 
cnn = CNN() 
print(cnn) 
''''' 
CNN ( 
 (conv1): Sequential ( 
  (0): Conv2d(1, 16, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) 
  (1): ReLU () 
  (2): MaxPool2d (size=(2, 2), stride=(2, 2), dilation=(1, 1)) 
 ) 
 (conv2): Sequential ( 
  (0): Conv2d(16, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) 
  (1): ReLU () 
  (2): MaxPool2d (size=(2, 2), stride=(2, 2), dilation=(1, 1)) 
 ) 
 (out): Linear (1568 -> 10) 
) 
''' 
optimizer = torch.optim.Adam(cnn.parameters(), lr=LR) 
loss_function = nn.CrossEntropyLoss() 
 
for epoch in range(EPOCH): 
  for step, (x, y) in enumerate(train_loader): 
    b_x = Variable(x) 
    b_y = Variable(y) 
 
    output = cnn(b_x) 
    loss = loss_function(output, b_y) 
    optimizer.zero_grad() 
    loss.backward() 
    optimizer.step() 
 
    if step % 100 == 0: 
      test_output = cnn(test_x) 
      pred_y = torch.max(test_output, 1)[1].data.squeeze() 
      accuracy = sum(pred_y == test_y) / test_y.size(0) 
      print('Epoch:', epoch, '|Step:', step, 
         '|train loss:%.4f'%loss.data[0], '|test accuracy:%.4f'%accuracy) 
 
test_output = cnn(test_x[:10]) 
pred_y = torch.max(test_output, 1)[1].data.numpy().squeeze() 
print(pred_y, 'prediction number') 
print(test_y[:10].numpy(), 'real number') 
''''' 
Epoch: 0 |Step: 0 |train loss:2.3145 |test accuracy:0.1040 
Epoch: 0 |Step: 100 |train loss:0.5857 |test accuracy:0.8865 
Epoch: 0 |Step: 200 |train loss:0.0600 |test accuracy:0.9380 
Epoch: 0 |Step: 300 |train loss:0.0996 |test accuracy:0.9345 
Epoch: 0 |Step: 400 |train loss:0.0381 |test accuracy:0.9645 
Epoch: 0 |Step: 500 |train loss:0.0266 |test accuracy:0.9620 
Epoch: 0 |Step: 600 |train loss:0.0973 |test accuracy:0.9685 
Epoch: 0 |Step: 700 |train loss:0.0421 |test accuracy:0.9725 
Epoch: 0 |Step: 800 |train loss:0.0654 |test accuracy:0.9710 
Epoch: 0 |Step: 900 |train loss:0.1333 |test accuracy:0.9740 
Epoch: 0 |Step: 1000 |train loss:0.0289 |test accuracy:0.9720 
Epoch: 0 |Step: 1100 |train loss:0.0429 |test accuracy:0.9770 
[7 2 1 0 4 1 4 9 5 9] prediction number 
[7 2 1 0 4 1 4 9 5 9] real number 
'''

 三、分析解读

通过利用torchvision.datasets可以快速获取可以直接置于DataLoader中的dataset格式的数据,通过train参数控制是获取训练数据集还是测试数据集,也可以在获取的时候便直接转换成训练所需的数据格式。

卷积神经网络的搭建通过定义一个CNN类来实现,卷积层conv1,conv2及out层以类属性的形式定义,各层之间的衔接信息在forward中定义,定义的时候要留意各层的神经元数量。

CNN的网络结构如下:

CNN (

 (conv1): Sequential (

  (0): Conv2d(1, 16,kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))

  (1): ReLU ()

  (2): MaxPool2d (size=(2,2), stride=(2, 2), dilation=(1, 1))

 )

 (conv2): Sequential (

  (0): Conv2d(16, 32,kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))

  (1): ReLU ()

  (2): MaxPool2d (size=(2,2), stride=(2, 2), dilation=(1, 1))

 )

 (out): Linear (1568 ->10)

)

经过实验可见,在EPOCH=1的训练结果中,测试集准确率可达到97.7%。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中实现对Timestamp和Datetime及UTC时间之间的转换
Apr 08 Python
基于python中的TCP及UDP(详解)
Nov 06 Python
PyCharm 常用快捷键和设置方法
Dec 20 Python
django初始化数据库的实例
May 27 Python
python 用正则表达式筛选文本信息的实例
Jun 05 Python
numpy返回array中元素的index方法
Jun 27 Python
python进行两个表格对比的方法
Jun 27 Python
python pytest进阶之xunit fixture详解
Jun 27 Python
使用python写一个自动浏览文章的脚本实例
Dec 05 Python
Python3 中sorted() 函数的用法
Mar 24 Python
pandas中read_csv、rolling、expanding用法详解
Apr 21 Python
python+opencv实现目标跟踪过程
Jun 21 Python
python 日志增量抓取实现方法
Apr 28 #Python
Django 使用logging打印日志的实例
Apr 28 #Python
python实现log日志的示例代码
Apr 28 #Python
Python学习笔记之open()函数打开文件路径报错问题
Apr 28 #Python
Python之读取TXT文件的方法小结
Apr 27 #Python
如何利用python查找电脑文件
Apr 27 #Python
Python3 中把txt数据文件读入到矩阵中的方法
Apr 27 #Python
You might like
PHP制作图型计数器的例子
2006/10/09 PHP
在PHP中使用curl_init函数的说明
2010/11/02 PHP
php中的curl使用入门教程和常见用法实例
2014/04/10 PHP
ThinkPHP在Cli模式下使用模板引擎的方法
2015/09/25 PHP
php打乱数组二维数组多维数组的简单实例
2016/06/17 PHP
PHP实现Redis单据锁以及防止并发重复写入
2018/04/10 PHP
PHP排序算法之堆排序(Heap Sort)实例详解
2018/04/21 PHP
filemanage功能中用到的common.js
2007/04/08 Javascript
jQuery load方法用法集锦
2011/12/06 Javascript
node.js中的定时器nextTick()和setImmediate()区别分析
2014/11/26 Javascript
jquery禁止回车触发表单提交
2014/12/12 Javascript
微信小程序 location API接口详解及实例代码
2016/10/12 Javascript
BootStrap实现邮件列表的分页和模态框添加邮件的功能
2016/10/13 Javascript
jquery-mobile基础属性与用法详解
2016/11/23 Javascript
jquery实现倒计时小应用
2017/09/19 jQuery
React Native使用百度Echarts显示图表的示例代码
2017/11/07 Javascript
简单了解node npm cnpm的具体使用方法
2019/02/27 Javascript
详解babel升级到7.X采坑总结
2019/05/12 Javascript
微信公众号服务器验证Token步骤图解
2019/12/30 Javascript
javascript实现贪吃蛇小游戏
2020/07/28 Javascript
[01:03]悬念揭晓 11月26日DOTA2完美盛典不见不散
2017/11/23 DOTA
Python标准库之sqlite3使用实例
2014/11/25 Python
举例讲解Python面相对象编程中对象的属性与类的方法
2016/01/19 Python
Django Admin 实现外键过滤的方法
2017/09/29 Python
Python实现的rsa加密算法详解
2018/01/24 Python
使用Python的OpenCV模块识别滑动验证码的缺口(推荐)
2019/05/10 Python
关于Pytorch MaxUnpool2d中size操作方式
2020/01/03 Python
Tensorflow:转置函数 transpose的使用详解
2020/02/11 Python
Python代码需要缩进吗
2020/07/01 Python
python 模块导入问题汇总
2021/02/01 Python
使用css3实现的windows8开机加载动画
2014/12/09 HTML / CSS
给老师的一封建议书
2014/03/13 职场文书
创先争优承诺书范文
2014/03/31 职场文书
2014年幼儿园德育工作总结
2014/12/17 职场文书
公积金贷款承诺书
2015/04/30 职场文书
python实现黄金分割法的示例代码
2021/04/28 Python