先给出几个入门PyTorch的好的资料:

  • PyTorch官方教程(中文版):http://pytorch123.com
  • 《动手学深度学习》PyTorch版:https://github.com/ShusenTang/Dive-into-DL-PyTorch

1. PyTorch介绍

PyTorch是Torch7团队开发的,与Torch的不同之处在于PyTorch使用了Python作为开发语言,同样说明它是一个以Python优先的深度学习框架,它不仅能够实现强大的GPU加速,同时还支持动态神经网络,这是TensorFlow等很多主流框架不支持的。而且PyTorch可以轻松扩展,近两年有赶超TensorFlow的势头。

2. 卷积神经网络(CNN)

卷积神经网络(CNN——Convolutional Neural Network)是一种前馈神经网络。长期以来是图像识别领域的核心算法之一

这是一张卷及神经网络机构示意图,让我们理解下各部分:

  • 输入层(Input Layer):对于我们人来说输入的是一张图片,但是对于电脑来说输入的是一个矩阵类型的数据,这些数据代表着这张图片的像素值
  • 卷积层(Convolution Layer):对输入的数据进行特征提取,每个卷积核每次从一个小区域提取到一个特征值,所有的特征值组合起来就得到了一个特征图,当用多个卷积核对输入数据进行特征提取时,就得到了多个特征图。这个卷积核我们称为(kernel)
  • 激活函数(Activation Function):在人工神经网络的神经元上运行的函数,负责将神经元的输入映射到输出端,引入激活函数是为了增加神经网络模型的非线性
  • 池化层(Pooling Layer):在不影响特征质量的情况下对图片进行压缩,以减少参数,池化主要有两种,一种是MaxPooling,一种是AvePooling。假设池化的内核是一个2*2的矩阵,采用MaxPooling则是输出其中的最大值,采用AvePooling则输出所有数据的平均值
  • 全连接层(Fully Connected Layer,简称FC):在整个卷积神经网络中起到“分类器”的作用。如果说卷积层、池化层和激活函数层等操作是将原始数据映射到隐层特征空间的话,全连接层则起到将学到的“分布式特征表示”映射到样本标记空间的作用
  • 输出层(Output Layer):卷积神经网络中输出层的上游通常是全连接层,因此其结构和工作原理与传统前馈神经网络中的输出层相同。对于图像分类问题,输出层使用逻辑函数或归一化指数函数(softmax function)输出分类标签 。在物体识别(object detection)问题中,输出层可设计为输出物体的中心坐标、大小和分类 。在图像语义分割中,输出层直接输出每个像素的分类结果

理解完卷积神经网络后,让我们来看下PyTorch中的卷积神经网络

3. PyTorch中的卷积神经网络

3.1 卷积层:nn.Conv2d()

其参数如下:

  • in_channels : 输入信号的通道数.
  • out_channels : 卷积后输出结果的通道数.
  • kernel_size : 卷积核的形状。例如kernel_size=(3, 2)表示3X2的卷积核,如果宽和高相同,可以只用一个数字表示
  • stride : 卷积每次移动的步长, 默认为1.
  • padding : 处理边界时填充0的数量, 默认为0(不填充).
  • dilation : 采样间隔数量, 默认为1, 无间隔采样
  • groups : 输入与输出通道的分组数量. 当不为1时, 默认为1(全连接)
  • bias 为 True 时,添加偏置.

3.2 池化层:nn.MaxPool2d()

其参数如下:

  • kernel_size : 最大池化操作时的窗口大小
  • stride : 最大池化操作时窗口移动的步长, 默认值是 kernel_size
  • padding : 输入的每条边隐式补0的数量
  • dilation : 用于控制窗口中元素的步长的参数
  • return_indices : 如果等于 True, 在返回 max pooling 结果的同时返回最大值的索引 这在之后的 Unpooling 时很有用
  • ceil_mode : 如果等于 True, 在计算输出大小时,将采用向上取整来代替默认的向下取整的方式

4. 实现MNIST手写数字识别

下面就使用 pytorch 来动手搭建一个卷积神经网络来训练和识别手写数字。

4.1 引入库函数

import torch.nn as nn  # pytorch中最重要的模块,封装了神经网络相关的函数
import torch.nn.functional as F  # 提供了一些常用的函数,如softmax
import torch.optim as optim  # 优化模块,封装了求解模型的一些优化器,如Adam SGD
from torch.optim import lr_scheduler  # 学习率调整器,在训练过程中合理变动学习率
from torchvision import transforms  # pytorch 视觉库中提供了一些数据变换的接口
from torchvision import datasets  # pytorch 视觉库提供了加载数据集的接口

4.2 设置超参数

# 预设网络超参数 (所谓超参数就是可以人为设定的参数BATCH_SIZE = 64  # 由于使用批量训练的方法,需要定义每批的训练的样本数目EPOCHS = 3  # 总共训练迭代的次数# 让torch判断是否使用GPU,建议使用GPU环境,因为会快很多
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")learning_rate = 0.001  # 设定初始的学习率

4.3 加载数据集

这里我们使用dataloader迭代器来加载数据集

# 加载训练集
train_loader = torch.utils.data.DataLoader(datasets.MNIST('data', train=True, download=True,transform=transforms.Compose([transforms.ToTensor(),transforms.Normalize(mean=(0.5,), std=(0.5,))  # 数据规范化到正态分布])),batch_size=BATCH_SIZE, shuffle=True)  # 指明批量大小,打乱,这是处于后续训练的需要。test_loader = torch.utils.data.DataLoader(datasets.MNIST('data', train=False, transform=transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5,), (0.5,))])),batch_size=BATCH_SIZE, shuffle=True)

上述代码的作用是:

  1. 将mnist训练集和测试集下载到文件夹data中
  2. 对数据进行变化,包括转为tensor数据类型,以及为了保证训练集测试集的独立同分布,数据规范化到正态分布
  3. 数据分批量存储,顺序打乱,方便后续训练。

4.4 设计网络结构

一个简单的卷积神经网络的结构,一般包括:

  • 卷积层Conv:通过卷积核提取图像特征,得到feature map
  • 池化层Pool:利用卷积核对feature map 降采样,减少尺寸。最大池化层就是取滑动窗口内最大的像素,而平均池化层就是取滑动窗口内平均像素结果。
  • 全连接层:多个linear model + 激活函数 eg:ReLU。这样就构成了一个基本的CNN了,但是我们出于爱学习的心态呢,我们最好还要了解一些深度学习训练过程中的一些tricks,以提高模型的泛化能力。
  • batch normalization:简单来说就是将上一层的加权求和的所有输出结果再批量归一化(标准正态分布),然后输入一个线性模型,然后再连接到激活函数。
  • DropOut:在全连接层中,我们通过设定概率随机的让这一层的某些权重为0,相当于神经元无效。

# 设计模型
class ConvNet(nn.Module):def __init__(self):super(ConvNet, self).__init__()# 提取特征层self.features = nn.Sequential(# 卷积层# 输入图像通道为 1,因为我们使用的是黑白图,单通道的# 输出通道为32(代表使用32个卷积核),一个卷积核产生一个单通道的特征图# 卷积核kernel_size的尺寸为 3 * 3,stride 代表每次卷积核的移动像素个数为1# padding 填充,为1代表在图像长宽都多了两个像素nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3, stride=1, padding=1),# ((28-3+2*1)/1)+1=28  28*28*1  》 28*28*32# 批量归一化,跟上一层的out_channels大小相等,以下的通道规律也是必须要对应好的nn.BatchNorm2d(num_features=32),   #28*28*32  》 28*28*32# 激活函数,inplace=true代表直接进行运算nn.ReLU(inplace=True),nn.Conv2d(32, 32, kernel_size=3, stride=1, padding=1),   #  ((28-3+2*1)/1)+1=28     28*28*32 》 28*28*32nn.BatchNorm2d(32),nn.ReLU(inplace=True),# 最大池化层# kernel_size 为2 * 2的滑动窗口# stride为2,表示每次滑动距离为2个像素# 经过这一步,图像的大小变为1/4,即 28 * 28 -》 7 * 7nn.MaxPool2d(kernel_size=2, stride=2),nn.Conv2d(32, 64, kernel_size=3, padding=1),nn.BatchNorm2d(64),nn.ReLU(inplace=True),nn.Conv2d(64, 64, kernel_size=3, padding=1),nn.BatchNorm2d(64),nn.ReLU(inplace=True),nn.MaxPool2d(kernel_size=2, stride=2))# 分类层self.classifier = nn.Sequential(# Dropout层# p = 0.5 代表该层的每个权重有0.5的可能性为0nn.Dropout(p=0.5),# 这里是通道数64 * 图像大小7 * 7,然后输入到512个神经元中nn.Linear(64 * 7 * 7, 512),nn.BatchNorm1d(512),nn.ReLU(inplace=True),nn.Dropout(p=0.5),nn.Linear(512, 512),nn.BatchNorm1d(512),nn.ReLU(inplace=True),nn.Dropout(p=0.5),nn.Linear(512, 10),)# 前向传递函数    def forward(self, x):# 经过特征提取层x = self.features(x)# 输出结果必须展平成一维向量x = x.view(x.size(0), -1)x = self.classifier(x)return x

4.5 训练前准备

# 初始化模型 将网络操作移动到GPU或者CPUConvModel = ConvNet().to(DEVICE)
# 定义交叉熵损失函数
criterion = nn.CrossEntropyLoss().to(DEVICE)
# 定义模型优化器:输入模型参数,定义初始学习率
optimizer = torch.optim.Adam(ConvModel.parameters(), lr=learning_rate)
# 定义学习率调度器:输入包装的模型,定义学习率衰减周期step_size,gamma为衰减的乘法因子
exp_lr_scheduler = lr_scheduler.StepLR(optimizer, step_size=6, gamma=0.1)
# 在官网上的解释。如果初始学习率lr = 0.05,衰减周期step_size为30,衰减乘法因子gamma=0.01
# Assuming optimizer uses lr = 0.05 for all groups
# >>> # lr = 0.05     if epoch < 30
# >>> # lr = 0.005    if 30 <= epoch < 60
# >>> # lr = 0.0005   if 60 <= epoch < 90

4.6 训练

def train(num_epochs, _model, _device, _train_loader, _optimizer, _lr_scheduler):_model.train()  # 设置模型为训练模式_lr_scheduler.step() # 设置学习率调度器开始准备更新for epoch in range(num_epochs):# 从迭代器抽取图片和标签for i, (images, labels) in enumerate(_train_loader):samples = images.to(_device)labels = labels.to(_device)# 此时样本是一批图片,在CNN的输入中,我们需要将其变为四维,# reshape第一个-1 代表自动计算批量图片的数目n# 最后reshape得到的结果就是n张图片,每一张图片都是单通道的28 * 28,得到四维张量output = _model(samples.reshape(-1, 1, 28, 28))# 计算损失函数值loss = criterion(output, labels)# 优化器内部参数梯度必须变为0optimizer.zero_grad()# 损失值后向传播loss.backward()# 更新模型参数optimizer.step()if (i + 1) % 100 == 0:print("Epoch:{}/{}, step:{}, loss:{:.4f}".format(epoch + 1, num_epochs, i + 1, loss.item()))

4.7 预测

def test(_test_loader, _model, _device):_model.eval()  # 设置模型进入预测模式 evaluationloss = 0correct = 0with torch.no_grad():  # 如果不需要 backward更新梯度,那么就要禁用梯度计算,减少内存和计算资源浪费。for data, target in _test_loader:data, target = data.to(_device), target.to(_device)output = ConvModel(data.reshape(-1, 1, 28, 28))loss += criterion(output, target).item()  # 添加损失值pred = output.data.max(1, keepdim=True)[1]  # 找到概率最大的下标,为输出值correct += pred.eq(target.data.view_as(pred)).cpu().sum()  # .cpu()是将参数迁移到cpu上来。loss /= len(_test_loader.dataset)print('\nAverage loss: {:.4f}, Accuracy: {}/{} ({:.3f}%)\n'.format(loss, correct, len(_test_loader.dataset),100. * correct / len(_test_loader.dataset)))

4.8 运行

for epoch in range(1, EPOCHS + 1):train(epoch, ConvModel, DEVICE, train_loader, optimizer, exp_lr_scheduler)test(test_loader,ConvModel, DEVICE)test(train_loader,ConvModel, DEVICE)

5 结果

用的pytorch =0.4 用CPU跑的

Epoch:1/1, step:100, loss:0.1579
Epoch:1/1, step:200, loss:0.0809
Epoch:1/1, step:300, loss:0.0673
Epoch:1/1, step:400, loss:0.1391
Epoch:1/1, step:500, loss:0.0323
Epoch:1/1, step:600, loss:0.0870
Epoch:1/1, step:700, loss:0.0441
Epoch:1/1, step:800, loss:0.0705
Epoch:1/1, step:900, loss:0.0396Average loss: 0.0006, Accuracy: 9881/10000 (98.000%)Epoch:1/2, step:100, loss:0.0487
Epoch:1/2, step:200, loss:0.1519
Epoch:1/2, step:300, loss:0.0262
Epoch:1/2, step:400, loss:0.2133
Epoch:1/2, step:500, loss:0.0161
Epoch:1/2, step:600, loss:0.0805
Epoch:1/2, step:700, loss:0.0927
Epoch:1/2, step:800, loss:0.0663
Epoch:1/2, step:900, loss:0.0669
Epoch:2/2, step:100, loss:0.0124
Epoch:2/2, step:200, loss:0.0527
Epoch:2/2, step:300, loss:0.0256
Epoch:2/2, step:400, loss:0.0138
Epoch:2/2, step:500, loss:0.0894
Epoch:2/2, step:600, loss:0.1030
Epoch:2/2, step:700, loss:0.0528
Epoch:2/2, step:800, loss:0.1106
Epoch:2/2, step:900, loss:0.0044Average loss: 0.0003, Accuracy: 9930/10000 (99.000%)

PyTorch入门一:卷积神经网络实现MNIST手写数字识别相关推荐

  1. Tensorflow之 CNN卷积神经网络的MNIST手写数字识别

    点击"阅读原文"直接打开[北京站 | GPU CUDA 进阶课程]报名链接 作者,周乘,华中科技大学电子与信息工程系在读. 前言 tensorflow中文社区对官方文档进行了完整翻 ...

  2. PyTorch基础与简单应用:构建卷积神经网络实现MNIST手写数字分类

    文章目录 (一) 问题描述 (二) 设计简要描述 (三) 程序清单 (四) 结果分析 (五) 调试报告 (六) 实验小结 (七) 参考资料 (一) 问题描述 构建卷积神经网络实现MNIST手写数字分类 ...

  3. 基于TensorFlow深度学习框架,运用python搭建LeNet-5卷积神经网络模型和mnist手写数字识别数据集,设计一个手写数字识别软件。

    本软件是基于TensorFlow深度学习框架,运用LeNet-5卷积神经网络模型和mnist手写数字识别数据集所设计的手写数字识别软件. 具体实现如下: 1.读入数据:运用TensorFlow深度学习 ...

  4. 【TensorFlow-windows】(四) CNN(卷积神经网络)进行手写数字识别(mnist)

    主要内容: 1.基于CNN的mnist手写数字识别(详细代码注释) 2.该实现中的函数总结 平台: 1.windows 10 64位 2.Anaconda3-4.2.0-Windows-x86_64. ...

  5. tensorflow saver_机器学习入门(6):Tensorflow项目Mnist手写数字识别-分析详解

    本文主要内容:Ubuntu下基于Tensorflow的Mnist手写数字识别的实现 训练数据和测试数据资料:http://yann.lecun.com/exdb/mnist/ 前面环境都搭建好了,直接 ...

  6. 全连接神经网络实现MNIST手写数字识别

    在对全连接神经网络的基本知识(全连接神经网络详解)学习之后,通过MNIST手写数字识别这个小项目来学习如何实现全连接神经网络. MNIST数据集 对于深度学习的任何项目来说,数据集是其中最为关键的部分 ...

  7. PyTorch基础入门五:PyTorch搭建多层全连接神经网络实现MNIST手写数字识别分类

    )全连接神经网络(FC) 全连接神经网络是一种最基本的神经网络结构,英文为Full Connection,所以一般简称FC. FC的准则很简单:神经网络中除输入层之外的每个节点都和上一层的所有节点有连 ...

  8. 深蓝学院第三章:基于卷积神经网络(CNN)的手写数字识别实践

    参看之前篇章的用全连接神经网络去做手写识别:https://blog.csdn.net/m0_37957160/article/details/114105389?spm=1001.2014.3001 ...

  9. 深度学习入门实例——基于keras的mnist手写数字识别

    本文介绍了利用keras做mnist数据集的手写数字识别. 参考网址 http://www.cnblogs.com/lc1217/p/7132364.html mnist数据集中的图片为28*28的单 ...

最新文章

  1. HBuilder简单入门
  2. SAP MM 启用了Advanced Return Management之后采购订单上的一些变化
  3. 日志——Vue.js开发在线简历生成器
  4. Jquery的html方法里包含特殊字符的处理,类似双引号之类的
  5. java判断读到末尾_Flink实战:自定义KafkaDeserializationSchema(Java/Scala)
  6. 文件操作的小tips
  7. flask中关于endpoint端点、url_map映射、view_func视图函数,view_functions、及视图函数名是否何以相同的问题?
  8. LAMP详解及源码编译安装过程
  9. 关闭 启动_win10系统关闭快速启动功能教程
  10. 编写 iPhone Friendly 的 Web 应用程序 (Part 6 - iUI)
  11. tmp name php,linux环境 上传文件失败 tmp_name为空
  12. scala 基础 —— 函数(柯里化)
  13. word多级编号,如何让第一级为大写“一”,其他级别均为小写1.
  14. 侧方、s弯道、坡起相关
  15. jersey 过滤_Jersey的Filter详解
  16. SolidWorks二次开发---简单的参数化示例
  17. 云时代如何做好IT运维审计
  18. 短线王的盯盘宝怎么样_短线王炒股十大技巧!
  19. java 加单引号_【沫沫金】Java逗号拼接字符串增加单引号
  20. 利用树莓派(3B+)板载蓝牙(ble)实现与蓝牙热敏打印机的通信

热门文章

  1. matlab种子点 边缘,如何只做种子点和某个区域(假如额叶)的功能连接
  2. 开始记录自己的搬砖学习生涯(尽力周更~~)
  3. 大学毕业后,留在北京的人,要坚强!
  4. 合作共赢位来_张亚超
  5. DSP48E1 (primitive)原语例化实例2
  6. [模式识别].(希腊)西奥多里蒂斯lt;第四版gt;笔记8它__模板匹配
  7. 亲测奥维互动地图访问GMAP方法
  8. 免费采购网站 软件 平台大全 全国排行 必收藏
  9. 【ASP.NET Web】项目实践—网上宠物店2:创建ASP.NET Web 网站项目、连接数据库
  10. 环二肽cyclo(Trp-Trp),20829-55-4