03_深度学习实现手写数字识别(python)

本次项目采用了多种模型进行测试,并尝试策略来提升模型的泛化能力,最终取得了99.67%的准确率,并采用pyqt5来制作可视化GUI界面进行呈现。具体代码已经开源。

代码详情见附录

1简介

早在1998年,在AT&T贝尔实验室的YannLeCun就开始使用人工神经网络挑战数字手写体识别,用于解决当时银行支票以及邮局信件邮编自动识别的需求。而现今,数字手写体识别,已经成了机器学习的入门实验案例,或者说是深度学习里的“Helloworld”任务。其中算法实验使用最广泛的数据集就是MNIST,由YannLeCun提供下载。它包含了60000张训练图片集,以及10000张测试图片集,最初来源于NIST(NationalInstituteofStandardsandTechnology,美国国家标准与技术研究院)数据库。

1.1验证指标

首先是观察模型在验证集的损失函数值loss和精度acc。然后在随机使用几张图片,主观判断其模型的识别结果。同样除了主观判断,我们还需要客观判断。因此我们引入混淆矩阵。分类问题中的混淆矩阵如下:
在这里插入图片描述
上表中TP:预测为1,预测正确,即实际1;FP:预测为1,预测错误,即实际0;FN:预测为0,预测错确,即实际1;TN:预测为0,预测正确即,实际0。

(1)准确率

其中准确率的定义是预测正确的结果占总样本的百分比,其公式如下:

Accuracy=(TP+TN)/(TP+TN+FP+FN)

虽然准确率可以判断总的正确率,但是在样本不平衡的情况下,并不能作为很好的指标来衡量结果。举个简单的例子,比如在一个总样本中,正样本占90%,负样本占10%,样本是严重不平衡的。对于这种情况,我们只需要将全部样本预测为正样本即可得到90%的高准确率,但实际上我们并没有很用心的分类,只是随便无脑一分而已。这就说明了:由于样本不平衡的问题,导致了得到的高准确率结果含有很大的水分。即如果样本不平衡,准确率就会失效。

(2)精准率

精准率(Precision)又叫查准率,它是针对预测结果而言的,它的含义是在所有被预测为正的样本中实际为正的样本的概率,意思就是在预测为正样本的结果中,我们有多少把握可以预测正确,其公式如下:

Precise=TP/(TP+FP)

精准率代表对正样本结果中的预测准确程度,而准确率则代表整体的预测准确程度,既包括正样本,也包括负样本。

(3)召回率

召回率(Recall)又叫查全率,它是针对原样本而言的,它的含义是在实际为正的样本中被预测为正样本的概率,其公式如下:

Recall=TP/(TP+FN)

召回率的应用场景:比如拿网贷违约率为例,相对好用户,我们更关心坏用户,不能错放过任何一个坏用户。因为如果我们过多的将坏用户当成好用户,这样后续可能发生的违约金额会远超过好用户偿还的借贷利息金额,造成严重偿失。召回率越高,代表实际坏用户被预测出来的概率越高,它的含义类似:宁可错杀一千,绝不放过一个。

(4)F1值

我们希望精准率和召回率同时都非常高。但实际上这两个指标是一对矛盾体,无法做到双高。如果其中一个非常高,另一个肯定会非常低。选取合适的阈值点要根据实际需求,比如我们想要高的查全率,那么我们就会牺牲一些查准率,在保证查全率最高的情况下,查准率也不那么低。在实际情况中,不会有分类器仅仅以精确度(Precision)或者召回率(Recall)作为单一的度量标准,而是使用这两者的调和平均,于是就有了F值(F-Score),F1分数同时考虑了查准率和查全率,让二者同时达到最高,取一个平衡。

F1measure=2PreciseRecall/(Precise+Recall)

2深度学习的手写数字识别实现

2.1数据预处理

1)图像剪裁

中心裁剪的目的是从图片的中心开始,裁剪出其四周指定长度和宽度的图片,也就是获取原图的中心部分。让图片的特征更加突出。

在这里插入图片描述

如上图所示是图像剪裁的样例,从左到右分别是图片,中心裁剪24后的图片,在经过缩放还原的图片,可以看出中心的图片变的更加突出,不过相应的图片在缩放之后变得模糊,但是不影响判断。

2)水平翻转

水平翻转是将图片从左向右,从右向左180度翻转,从下图可以看出水平翻转后的数字‘2’与数字‘5’及其相似,且不好区分,所以这里不适用水平翻转

在这里插入图片描述

如图所示,如果是正规的数字,我们可以引入水平翻转,让模型的鲁棒性更加的优秀,但是对于手写体数字,水平翻转对于某些数字,如2,5等,可能造成影响,故这里不进行水平翻转。

3)随机旋转

水平翻转不可以使用,但不代表一般的旋转不可以使用,为此这我采用随机旋转,但是为了避免出现上述的情况,旋转的角度固定在-60到60度的范围。

在这里插入图片描述

如上图所示,旋转一定的角度,即可以增加模型的旋转不变性,同时也不会出现误导的情况。

4)亮度,对比度,饱和度,色调

这里还是对示例图数字‘2’做图像增强,结果如下

在这里插入图片描述

如上图所示,因为灰度图的原因,除了亮度和饱和度之外,色调和对比度的调整效果不大,虽然上述变换没有明显的变化,但是对计算机而言已经发生了很大的改变,所以这里我们采用随机调整亮度,对比度,饱和度,色调的方式来生成新的图片。

5)腐蚀和膨胀

原本是准备采用上述几种数据增强方式即可,但是后序的GUI界面生成新的图片时,笔的粗细会带来很大的影响,因此这里我加了新的数据增强方式,腐蚀和膨胀,他们是最基本的形态学操作,腐蚀和膨胀都是针对白色部分(高亮部分)而言的。

在这里插入图片描述

可以看到,上述腐蚀操作由黑色的数字2进行,所以字体变粗,而右边的膨胀操作则为白色的膨胀导致数字变细。

2.2基于Lenet的手写体数字识别

LeNet是最早的卷积神经网络之一[1]。1998年,YannLeCun第一次将LeNet卷积神经网络应用到图像分类上,在手写数字识别任务中取得了巨大成功。LeNet通过连续使用卷积和池化层的组合提取图像特征,其架构如图1所示,这里展示的是用于MNIST手写体数字识别任务中的LeNet模型。

在这里插入图片描述

2.3基于Alexnet的手写数字识别

虽然LeNet在手写数字识别数据集上取得了很好的结果,但在更大的数据集上表现却并不好。自从1998年LeNet问世以来,接下来十几年的时间里,神经网络并没有在计算机视觉领域取得很好的结果,反而一度被其它算法所超越。原因主要有两方面,一是神经网络的计算比较复杂,对当时计算机的算力来说,训练神经网络是件非常耗时的事情;另一方面,当时还没有专门针对神经网络做算法和训练技巧的优化,神经网络的收敛是件非常困难的事情。随着技术的进步和发展,计算机的算力越来越强大,尤其是在GPU并行计算能力的推动下,复杂神经网络的计算也变得更加容易实施。另一方面,互联网上涌现出越来越多的数据,极大的丰富了数据库。同时也有越来越多的研究人员开始专门针对神经网络做算法和模型的优化,AlexKrizhevsky等人提出的AlexNet以很大优势获得了2012年ImageNet比赛的冠军。这一成果极大的激发了产业界对神经网络的兴趣,开创了使用深度神经网络解决图像问题的途径,随后也在这一领域涌现出越来越多的优秀成果。

在这里插入图片描述

AlexNet与LeNet相比,具有更深的网络结构,包含5层卷积和3层全连接,同时与LeNet相比,使用了如下二种方法改进模型的训练过程:

  • 使用Dropout抑制过拟合。
  • 使用ReLU

2.4基于VGG的手写数字识别

VGG是当前最流行的CNN模型之一,2014年由Simonyan和Zisserman提出,其命名来源于论文作者所在的实验室VisualGeometryGroup。AlexNet模型通过构造多层网络,取得了较好的效果,但是并没有给出深度神经网络设计的方向。VGG通过使用一系列大小为3x3的小尺寸卷积核和池化层构造深度卷积神经网络,并取得了较好的效果。VGG模型因为结构简单、应用性极强而广受研究者欢迎,尤其是它的网络结构设计方法,为构建深度神经网络提供了方向。

在这里插入图片描述

上图是VGG-16的网络结构示意图,有13层卷积和3层全连接层。VGG网络的设计严格使用3×3的卷积层和池化层来提取特征,并在网络的最后面使用三层全连接层,将最后一层全连接层的输出作为分类的预测。在VGG中每层卷积将使用ReLU作为激活函数,在全连接层之后添加dropout来抑制过拟合。使用小的卷积核能够有效地减少参数的个数,使得训练和测试变得更加有效。比如使用两层3×3卷积层,可以得到感受野为5的特征图,而比使用5×5的卷积层需要更少的参数。由于卷积核比较小,可以堆叠更多的卷积层,加深网络的深度,这对于图像分类任务来说是有利的。VGG模型的成功证明了增加网络的深度,可以更好的学习图像中的特征模式。

2.5基于GoogLeNet的手写体数字识别

GoogLeNet是2014年ImageNet比赛的冠军,它的主要特点是网络不仅有深度,还在横向上具有“宽度”。由于图像信息在空间尺寸上的巨大差异,如何选择合适的卷积核来提取特征就显得比较困难了。空间分布范围更广的图像信息适合用较大的卷积核来提取其特征;而空间分布范围较小的图像信息则适合用较小的卷积核来提取其特征。为了解决这个问题,GoogLeNet提出了一种被称为Inception模块的方案。如下图所示:

在这里插入图片描述

图(a)是Inception模块的设计思想,使用3个不同大小的卷积核对输入图片进行卷积操作,并附加最大池化,将这4个操作的输出沿着通道这一维度进行拼接,构成的输出特征图将会包含经过不同大小的卷积核提取出来的特征,从而达到捕捉不同尺度信息的效果。Inception模块采用多通路(multi-path)的设计形式,每个支路使用不同大小的卷积核,最终输出特征图的通道数是每个支路输出通道数的总和,这将会导致输出通道数变得很大,尤其是使用多个Inception模块串联操作的时候,模型参数量会变得非常大。为了减小参数量,Inception模块使用了图(b)中的设计方式,在每个3x3和5x5的卷积层之前,增加1x1的卷积层来控制输出通道数;在最大池化层后面增加1x1卷积层减小输出通道数。基于这一设计思想,形成了上图(b)中所示的结构

在这里插入图片描述

GoogLeNet的架构如上图所示,在主体卷积部分中使用5个模块(block),每个模块之间使用步幅为2的3×3最大池化层来减小输出高宽。

3基于pyqt5的可视化界面效果

GUI界面采用的pyqt5进行制作,具体代码参考CSDN上的开源代码,修改了白底黑字的画板为黑底白字,并提高了笔的粗细。最重要的是修改了图片处理和模型识别部分的代码,让其符合我的模型的图片格式,用于进行测试。

具体代码参考digital_recognition_gui文件夹,这里需要配置paddle的深度学习框架的环境,建议用CPU配置方案,GPU配置较为复杂,但如果需要本地运行我的模型就需要配置GPU环境。也可以在我的开源代码界面里面直接运行我的代码。飞浆提供免费的服务器进行训练。

总结

以上是手写数字识别的全部内容,具体代码如下

UI界面及代码链接

提取码:fjd4

项目开源地址:手写数字识别+GUI界面 - 飞桨AI Studio (baidu.com)

老规矩,有问提问,有用二连,感谢!

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码

)">
< <上一篇
 

)">
下一篇>>