minist字符识别达到top4%

 

            (一)项目描述

   文字是人类表达和交流信息的重要工具之一,不论是在生产还是日常生活中,人们都要接触和处理大量的文字信息。数字识别能够将数字高速、快效的输入到计算机系统,实现人机交互,减轻人们的劳动,将人力从枯燥冗杂的工作中解放出来,提高处理效率。手写数字识别在车牌号码识别,快递信息录入,邮件文字录入等领域具有重要的价值。

   MNIST是一个简单的图片数据集,包含了大量的数字手写体图片。每张图像都是灰度图,其高度和宽度都为28个像素,总共784个像素。每个像素具有灰度值这一属性来表示。下面是一些示例图片:

    

一张图片是一个28*28的像素点矩阵,我们可以用一个同大小的二维整数矩阵来表示。如下:

https://i-blog.csdnimg.cn/blog_migrate/81ee70fb8de3dea3a7e2a74e13f44fd0.png

MNIST数据集一共包含三部分:训练数据集(55,000份,mnist.train)、测试数据集(10,000份,mnist.test)和验证数据集(5,000份,mnist.validation)。为了取得更好的效果,我们使用了将Kaggle的数据集进行了数据扩充以扩大训练数据集样本。Kaggle的训练集包括42000的训练集(train.csv)和28000的测试集(test.train)。一般来说,训练数据集是用来训练模型,验证数据集可以检验所训练出来的模型的正确性和是否过拟合,测试集是不可见的(相当于一个黑盒),但我们最终的目的是使得所训练出来的模型在测试集上的效果(这里是准确性)达到最佳。

本次项目的主要目的是根据1-9数字特征利用神经网络对数字进行分类。当输入一张手写数字图片时,根据我们训练的模型可以输出相应的数字。我们使用训练好的网络去识别手写数字。最后达到99.885%的预测准确率。

               (二)识别原理

  传统数字识别的关键在于能否找到有效的特征,选取的特征应具有可分辨能力并尽可能的少,分辨能力在应用中而言就是特征能够使得不同类别的个体在特征值上相差大,同类别特征值相差小。特征值小一方面是为了减少计算量,另一方面也减少了信息冗余。特征提取方式主要有笔画密度特征、粗网格特征、重心以及重心距特征、首个黑点位置特征、投影特征以及空间域变换特征等。例如如果数字竖直长度比上横向宽度大于某个值比如 4 ,那么很有可能是数字 1 ,如果数字内有两个封闭的区域则很可能是字 8 ,如果只有一个封闭的区域,且封闭区域的重心偏上则很可能是数字 9 (同理可判断数字6 ),以上都是这些数字普遍具有的特征,但因为数字手写的原因,也包含了大量数字则需要进一步借助其他特征进行识别。

  K-近邻算法应用于数字识别时,通过大量标记好数据进行运算。根据测试数据与每个训练集数据距离的大小来判断该测试数据分属哪个类别。

  决策树应用于数字识别时,有好多种针对数字识别的建立决策树的方法,根据不同特征分类。其中一种 原理是图像用灰度图或者二值图表示,经过一系列降噪,剪裁之后,将原图切分成矩阵小图,比如3*5的小图。然后分别求这15个小图的密度特征(1-10)。这样每一个原始的大图就具有了15个特征属性。这里决策树的属性变量是数字型,可以使用>= 或者<=来作为分隔条件。这样在每一步分割的时候,需要分别遍历剩余属性点的1-10中所有的点,选一个熵增益最大的当做当前分割点。这样分割,每一次都能判别出一个数字的类别。比如第一次判断的时候,发现用第2块小图的密度,以密度为5作为分割,这时的熵是最大的。所以做一次分割,分割后,左右两边,右边仍然是杂乱无章的,而明显左边大部分的数字类别都是数字1(可以定义个阈值或者投票)。认为此次分割分离出了1.然后依次类推。。直到第10次分割,就认为吧所有的0-9的数字都区分了。然后代入待测样本的密度,根据决策树就能找到对应的数字类别。

  SVM分类算法应用于数字识别时,它分类的基本思想是利用最大间隔进行分类,处理非线性问题是通过核函数将特征向量映射到高维空间,从而变成线性可分的,但是运算却是在低维空间运行的。考虑到数据中可能存在噪音,还引入了松弛变量。其思路是获取大量的手写数字,常称作训练样本,然后开发出一个可以从这些训练样本中进行学习的系统。换言之,SVM使用样本来自动推断出识别手写数字的规则。随着样本数量的增加,算法可以学到更多关于手写数字的知识,这样就能够提升自身的准确性。

  BP神经网络应用于字符识别时,输入层有784(28*28)个神经元、隐藏层自由设定、输出层10个神经元。初始化各级权重w;各级偏置值b——都是采用随机数列生成的方式。定义隐藏层、输出层的计算方式以及各自的激活函数 。计算误差并用梯度下降法优化权重从而得到最优的分类模型。神经网络的出现使我们不需要做大量的特征工程,譬如提前设计好特征的内容或者说特征的数量等等,我们可以直接把数据灌进去,让它自己训练,自我修正,即可得到一个较好的效果。图像是由一个个像素点构成,每个像素点有三个通道,分别代表RGB颜色,那么,如果一个图像的尺寸是(28,28,1),即代表这个图像的是一个长宽均为28,channel为1的图像(channel也叫depth,此处1代表灰色图像)。如果使用全连接的网络结构,即,网络中的每个神经元与与相邻层上的神经元均连接,那就意味着我们的网络有28 * 28 =784个神经元,hidden层采用了15个神经元,那么简单计算一下,我们需要的参数个数(w和b)就有:784*15*10+2=117602个,这个参数太多了,随便进行一次反向传播计算量都是巨大的。

  CNN应用于字符识别时,其基本结构包括两层,其一为特征提取层,每个神经元的输入与前一层的局部接受域相连,并提取该局部的特征。一旦该局部特征被提取后,它与其它特征间的位置关系也随之确定下来;其二是特征映射层,网络的每个计算层由多个特征映射组成,每个特征映射是一个平面,平面上所有神经元的权值相等。特征映射结构采用影响函数核小的sigmoid函数作为卷积网络的激活函数,使得特征映射具有位移不变性。此外,由于一个映射面上的神经元共享权值,因而减少了网络自由参数的个数。卷积神经网络中的每一个卷积层都紧跟着一个用来求局部平均与二次提取的计算层,这种特有的两次特征提取结构减小了特征分辨率。这种自适应提取特征优化模型的方法正是我们实验取得最好效果的方法。

           (三)数据预处理

3.1导入需要用到的package

这些库包括:mnist数据源;Sequential类,可以封装各种神经网络层,包括Dense全连接层,Dropout层,Cov2D 卷积层,等等;矩阵运算以及数据处理包。

3.2读取mnist与kaggle的数据集,并编码为指定格式。

3.3读取文件,并查看其形状(shape),将两个数据集连接在一块。

可以看到,训练集是102000张28*28的单通道图片,测试集是38000张28*28的单通道图片。

3.4将数据归一化并变为keras可以处理的数据格式

Keras 自身就有 MNIST 这个数据包,再分成训练集和测试集。x 是一张张图片,y 是每张图片对应的标签,即它是哪个数字。输入的 x 变成 60,000*784 的数据,然后除以 255 进行标准化,因为每个像素都是在 0 到 255 之间的,标准化之后就变成了 0 到 1 之间。对于 y,要用到 Keras 改造的 numpy 的一个函数 np_utils.to_categorical,把 y 变成了 one-hot 的形式,即之前 y 是一个数值, 在 0-9 之间,现在是一个大小为 10 的向量,它属于哪个数字,就在哪个位置为 1,其他位置都是 0。数据格式如下图所示:

https://i-blog.csdnimg.cn/blog_migrate/19dd7d9f35e83f0c5723af39621cd2bd.png          https://i-blog.csdnimg.cn/blog_migrate/0c532f9c147484e107cc32d1eb4ca2be.png    

               (四)构建模型

模型解释:

https://i-blog.csdnimg.cn/blog_migrate/5fea712501cbf5fa023d804ac3f975d0.png

  1. Sequential模型是多个网络层的线性堆栈,我们keras的模型库中导入Sequential模型.
  2. 第一层使用40个卷积核对输入图像做卷积运算,卷积核尺寸为5*5,padding方式为same,卷积结果使用relu函数进行激活,输出图像仍然为28*28.
  3. 第二层使用50个卷积核对输入图像做卷积运算,卷积核尺寸为5*5,padding方式为valid,卷积结果使用relu函数进行激活,输出图像为24*24.
  4. 第三层为池化层,抽样然后再进行局部平均。它没有参数,起到降维的作用。将输入切分成不重叠的一些 n×n 区域。每一个区域就包含个值。从这个值计算出一个值。计算方法可以是求平均、取最大 max 等等。程序中polling操作将输入图像变为2*2的小块,然后每个小块取最大值,最后输出图片大小为12*12.
  5. 第四层为了防止过拟合现象发生,加上一层dropout层。
  6. 第五层使用70个卷积核对输入图像做卷积运算,卷积核尺寸为3*3,padding方式为same,卷积结果使用relu函数进行激活,输出图像为12*12.
  7. 第六层为池化层,最后输出图片大小为6*6.
  8. 第七层使用100个卷积核对输入图像做卷积运算,卷积核尺寸为3*3,padding方式为valid,卷积结果使用relu函数进行激活,输出图像为4*4.
  9. 第六层为池化层,最后输出图片大小为2*2.
  10. 第七层对数据进行展平,为了输出到全连接层。这是因为全连接层只处理包含样本数在内一共二维的数据,要求第一维是样本数,第二维是所有特征的个数。因此对于一个包含6000个样本,每个样本是28x28x1的小图像的数据,展平之后是一个6000x(28 x28)的矩阵。在keras里进行展平非常简单,在上面的MaxPooling2D层之后添model.add(Flatten())即可,KERAS能自己分析出输入和输出的维度。
  11. 在前面这些处理之后,但是在输出之前,通常会添加一个或者多个全连接层进一步处理数据。全连接层可以通过Dense指出,指明输出神经元个数和激活函数即可,中间再加一个dropout层,最后再加一个全连接层即可完成模型搭建。

模型中参数选择的一些问题

  1. 卷积核的大小随便设置,如:3*3、5*5、7*7、9*9等,一般都为奇数,卷积的个数也是自己设置的,100个卷积的意思,代表的是你要提取原图上100个特征(每一个卷积提取一种特征)。
  2. 设置激活函数的目的是保证结果输出的非线性化,RELU激活函数需要大于一个阈值,才会有输出,和人的神经元结构很像,激活函数的种类有很多,RELU的变种就有很多,在卷积神经网络中经常使用的激活函数有RELU和tanh。相比于其它激活函数来说,ReLU有以下优势:对于线性函数而言,ReLU的表达能力更强,尤其体现在深度网络中;而对于非线性函数而言,ReLU由于非负区间的梯度为常数,因此不存在梯度消失问题(Vanishing Gradient Problem),使得模型的收敛速度维持在一个稳定状态。
  3. 输入28*28的图像通过5*5的卷积之后,输出还是28*28,这和卷积的方式有关,设置步长为1,如果对28*28的图像设置不填充边距,那么输出图像的大小应该是(28-5)/1 + 1,输出图像应该是24*24,如果我们将原图的填充边距设置为2(在原图的周围填充两圈全0),来保证输入图像和输出图像的大小一致,这个时候的计算公式(28-5+2*2)/1 + 1,输出图像的大小还是和原图保持一致。这样做的目的,是为了防止输入图像经过卷积之后过快的衰减,因为有时候我们设计的卷积网络层数可能达到上100层,而填充0并不会对结果有影响。常见池化的方式有两种,均值和最大值,池化核的大小设置为2*2,代表是从2*2中选出一个值(平均值或者最大值),所以一个28*28的图像再经过2*2的池化之后就变成了14*14,池化的目的是为了减少参数而且还可以很好的保证图像的特征。

 

               (五)训练参数设置

batch_size、epoch、iteration是深度学习中常见的几个超参数:

(1)batchsize:每批数据量的大小。DL通常用SGD的优化算法进行训练,也就是一次(1 个iteration)一起训练batchsize个样本,计算它们的平均损失函数值,来更新参数。

(2)iteration:1个iteration即迭代一次,也就是用batchsize个样本训练一次。

(3)epoch:1个epoch指用训练集中的全部样本训练一次,此时相当于batchsize 等于训练集的样本数。

           (六)编译和训练模型

我们看到这个模型一共有186870个参数,大多来自于卷积层和全连接层。其中选定了损失函数和优化器。

这里使用最标准的fit方法。其中指定几个核心参数:

1.训练用特征数据X_train

2.训练用结果数据y_train

3.迭代次数epochs

4.批量大小用batch_size指定

5.validation_split用于在没有提供验证集的时候,按一定比例从训练集中取出一部分作为验证集

 

         (七) 测试集测试并保存结果

使用上述网络结构,只采用kaggle提供的48000训练集,通过调整Batch size 和 训练集遍历次数获得的最高准确率为99.614%。

使用同样的网络结构,只采用keras内置提供的60000训练集,通过调整Batch size 和 训练集遍历次数获得的最高准确率为99.842%。

将两个训练集集合在一起增强为一个更大的训练集后,通过调整Batch size 和 训练集遍历次数,获得的最高准确率为99.885%。

提交结果排名:

由上述网络模型进行预测得到的结果获得了99.885%的准确率,该成绩取得了Top 4%的排名。

                            

          (八) 总结与心得

1.CNN在图像数字上比KNN,随机森林树,BP神经网络效果都好,CNN处理图像问题具有很大的优势,最后得到成绩也是最高的。

2.多加卷积层有助于提升准确率,由于卷积运算的增加会使模型训练速度更快。

3.适当加Dropout可以提高准确率

4.激活函数使用relu比其他激活函数效果要好。

5.迭代次数过多会过拟合。实际预测结果并不理想。

6.改变卷积核的大小与卷积核的数目会对结果产生一定影响,缩小卷积核尺寸,增加卷积核数目都会提高准确率。

7.随机森林树由于构建方式不同,结果变化很大,如果构建合适可能会取得更好的效果。

8.对实际字符进行识别时还需要进行一系列处理。比如分割,裁剪,去噪等。

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值