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中apply函数的用法实例教程
Jul 31 Python
Python提取网页中超链接的方法
Sep 18 Python
flask框架路由常用定义方式总结
Jul 23 Python
python中matplotlib条件背景颜色的实现
Sep 02 Python
flask框架配置mysql数据库操作详解
Nov 29 Python
python无序链表删除重复项的方法
Jan 17 Python
详解pandas中iloc, loc和ix的区别和联系
Mar 09 Python
python对指定字符串逆序的6种方法(小结)
Apr 02 Python
Django实现将一个字典传到前端显示出来
Apr 03 Python
Django视图、传参和forms验证操作
Jul 15 Python
安装并免费使用Pycharm专业版(学生/教师)
Sep 24 Python
Elasticsearch 基本查询和组合查询
Apr 19 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
什么是短波收听SWL
2021/03/01 无线电
Yii2中如何使用modal弹窗(基本使用)
2016/05/30 PHP
php原生导出excel文件的两种方法(推荐)
2016/11/19 PHP
javascript this用法小结
2008/12/19 Javascript
jQuery操作input type=radio的实现代码
2012/06/14 Javascript
文本框中禁止非数字字符输入比如手机号码、邮编
2013/08/19 Javascript
js通过元素class名字获取元素集合的具体实现
2014/01/06 Javascript
javascript中的undefined和not defined区别示例介绍
2014/02/26 Javascript
SuperSlide2实现图片滚动特效
2014/06/20 Javascript
javascript与jquery中的this关键字用法实例分析
2015/12/24 Javascript
js类式继承与原型式继承详解
2016/04/07 Javascript
AngularJS 路由和模板实例及路由地址简化方法(必看)
2016/06/24 Javascript
Node学习记录之cluster模块
2017/05/31 Javascript
理解 javascript 中的函数表达式与函数声明
2017/07/07 Javascript
Node.js npm命令运行node.js脚本的方法
2018/10/10 Javascript
送你43道JS面试题(收藏)
2019/06/17 Javascript
javascript前端和后台进行数据交互方法示例
2020/08/07 Javascript
Python isinstance判断对象类型
2008/09/06 Python
python根据距离和时长计算配速示例
2014/02/16 Python
scrapy爬虫实例分享
2017/12/28 Python
python实现拓扑排序的基本教程
2018/03/11 Python
详解Python3的TFTP文件传输
2018/06/26 Python
python实现远程控制电脑
2019/05/23 Python
python语言基本语句用法总结
2019/06/11 Python
python 多线程中join()的作用
2020/10/29 Python
英国虚拟主机服务商:eUKhost
2016/08/16 全球购物
H&M旗下高端女装品牌:& Other Stories
2018/05/07 全球购物
网络安全类面试题
2015/08/01 面试题
小学学习雷锋活动总结
2014/07/03 职场文书
二人合伙经营协议书
2014/09/13 职场文书
争先创优演讲稿
2014/09/15 职场文书
群众路线查摆问题整改措施
2014/10/10 职场文书
践行党的群众路线心得体会
2014/11/05 职场文书
2015年助理政工师工作总结
2015/05/26 职场文书
世界上超棒的8种逻辑思维
2019/08/06 职场文书
springboot为异步任务规划自定义线程池的实现
2022/06/14 Java/Android