1 Star 2 Fork 0

伍小南18 / MNIST_pytorch

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
MNIST手写数字识别.md 5.85 KB
一键复制 编辑 原始数据 按行查看 历史
伍小南18 提交于 2022-12-04 11:37 . update MNIST手写数字识别.md.

MNIST手写数字识别

Woo wrnthu@163.com

任务背景

MNIST数据库(Modified National Institute of Standards and Technology database)是一个大型数据库的手写数字是通常用于训练各种图像处理系统。

采用CNN模型实现对手写数字的识别。

模型架构

对于CNN模型架构如下(图片较宽,建议在pic文件夹中 查看)

分别为

标题

(卷积层—激活层—池化层)—(卷积层—激活层—池化层)—展平层—

(线性层—线性层)

模型细节

数据预处理

MNIST手写数字图像大小固定为28X28像素,图像为256阶灰度图,如图。

对应的,其数据格式为 [28, 28] 的二维数组,数组中的每个元素对应一个像素点,元素代表该像素点的灰度值,都是uint8格式,从0至255。

为了便于计算,同时加快模型收敛速度,对数据先进行预处理,即标准化。

transform = transforms.Compose([transforms.ToTensor(),
                                transforms.Normalize(mean=											[0.5],std=[0.5])])

其中

  • ToTensor()将灰度范围从0-255线性放缩到0-1

  • Normalize()把0-1的取值范围根据mean和std变换到(-1,1),如下式 $$ x = \frac{x - mean(x)}{std(x)} $$ 其中为通道指定了mean和std,将区间 [0,1] 变换到 [-1,1]。一般的图片有RGB三通道,而MNIST为灰度图,只有单通道。

CNN层细节

第一部分(卷积1)

  • 第1层为卷积层
torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride, padding)

输入1通道(灰度值),输出64通道,无填充,采用64个1通道的5×5卷积核提取64种特征

输入:$batch128*28$

输出:$batch6424*24$

  • 第2层为激活层
torch.nn.ReLU()

激活层使用ReLU激活函数,线性整流

  • 第3层为池化层
torch.nn.MaxPool2d(kernel_size, stride, padding)

选取最大池化,池化窗口大小为2×2,步长为2,无填充

输入:$batch6424*24$

输出:$batch6412*12$

第二部分(卷积2)

  • 第4层为卷积层

输入64通道,输出128通道,采用128个64通道的3×3卷积核提取128种特征

输入:$batch6412*12$

输出:$batch12810*10$

  • 第5层为激活层

激活层使用ReLU激活函数,线性整流

  • 第6层为池化层

选取最大池化,池化窗口大小为2×2,步长为2

输入:$batch12810*10$

输出:$batch1285*5$

第三部分(展平)

  • 第7层为展平层

在全连接层前进行展平操作

temp = x.view(x.shape[0], -1)

对多维的数据展平,即对张量进行重构,其中x.shape[0]为batch,而-1表示把剩余维度展平,即可得到$batch*total$的张量

第三部分(全连接)

  • 第8层为线性层
torch.nn.Linear(in_features, out_features, bias=True)

输入神经元$12855$,输出神经元$256$,相当于引入一个[$12855$, $256$]的线性变换矩阵A和向量b,有 $$ y=Ax^T+b $$

  • 第9层为线性层

输入神经元$256$,输出神经元$10$,即对应十个数字结果的概率

损失函数和优化器

损失函数

采用交叉熵损失作为损失函数,可以度量预测与真实概率分布间的差异性。

loss = torch.nn.CrossEntropyLoss()

对于标签$y_i=[0,0\cdots,1,\cdots,0]$,预测其为$x_i$的概率$p(x_i)$,损失函数即为 $$ Loss=-\sum y_i\log p(x_i) $$

优化器

采用随机梯度下降(SVD)作为优化方法。

optimizer = torch.optim.SGD(CNN_model_wr.parameters(), lr=CNN_model_wr.learning_rate)

对于分批的训练集,对每一个batch的数据都更新一次梯度,SGD有以下优势:

  • 当训练数据太多时,利用整个数据集更新往往时间上不显示。batch的方法可以减少机器的压力,并且可以更快地收敛。

  • 当训练集有很多冗余时(类似的样本出现多次,比如本次数据集),batch方法收敛更快。

    以一个极端情况为例,若训练集前一半和后一半梯度相同。那么如果前一半作为一个batch,后一半作为另一个batch,那么在一次遍历训练集时,batch的方法向最优解前进两个step,而整体的方法只前进一个step。

不过SGD方法的更新并不稳定,其更新方向完全依赖于当前的batch。可以考虑加入动量项来增加稳定性,并增强摆脱局部最优的能力。

性能分析

经过10轮训练,用时6min左右,性能分析如下

训练轮数 损失 训练集正确率 测试集正确率
1 0.0027 94.6183% 97.9000%
2 0.0007 98.5883% 98.1300%
5 0.0003 99.4483% 99.0400%
10 0.0001 99.8117% 99.2200%

同时关注训练过程中的各项指标

训练轮数 Acc Recall precision F1 score Auc
1 0.9790 0.9792 0.9790 1.0002 0.9979
2 0.9813 0.9814 0.9817 1.0002 0.9986
5 0.9904 0.9904 0.9903 1.0000 0.9989
10 0.9922 0.9923 0.9921 1.0000 0.9991

由于数字识别中0-9的样本数量比较均衡,CNN模型也未过拟合,不会对某一个数字偏重太明显,故对0-9所有数字的准确率、召回率、精确率取平均,其结果数值相近,f1也随之趋向于1。

也可以分别查看各数字的识别情况。

实验总结

本次实验在pytorch的框架上搭建了MNIST手写数字识别的卷积神经网络,深刻理解了卷积过程的几何含义(比如padding和stride对输出size的影响,比如kernel对特征的影响等),也自己完成了CNN模型的搭建,有了较好的实验效果。

马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Python
1
https://gitee.com/wu-xiaonan-18/mnist_pytorch.git
git@gitee.com:wu-xiaonan-18/mnist_pytorch.git
wu-xiaonan-18
mnist_pytorch
MNIST_pytorch
master

搜索帮助

344bd9b3 5694891 D2dac590 5694891