最近在弄CNN实现手写数字识别系统,简单的使用了PyQt5设计了一个简单的系统界面,但是最后发现我的模型使用LeNet-5经典卷积神经网络,在MNIST测试集上的准确率有98%,却对我自己输入的一个非常简单的图片都识别错误???我就开始产生疑问,各种阅读资料,自己随便弄了弄,也没有很好的效果,但对于我自己输入的20张图片,有85%的正确率了。【前十张图片是网络上找的,侵删。】
1、最开始输入手写图片的时候,发现图片大小基本都大于28*28(MNIST数据集中的图片大小),我就直接使用resize修改尺寸了,这个时候基本识别不出来。
2、然后我查资料就怀疑是过拟合,就尝试减轻过拟合,首先使用了Dropout(以P=0.3的概率使神经元停止工作),有效果但是不明显,而且使用Dropout层改进的模型有点不稳定,我第一次输入的图片和第二次输入相同图片的识别结果有不一样的情况。
3、最后,我决定采用BatchNorm层改进模型(有论文说,Dropout和BatchNorm不能同时使用,会正正得负),BatchNorm层果然比Dropout层稳定,至少不会导致我第一次输入和第二次输入相同图片结果不一样了,但是好像训练出来的模型,有的对自己输入图片的准确率更差,所以我训练了几次,保留了一个最好的模型。
4、我觉得最最最重要的来了————————预处理!!!!!!MNIST手写数字识别的模型随处可见,但预处理对自己输入的图片非常非常重要‼️ MNIST数据集是经过归一化处理了的,所以训练模型的测试准确度也是非常高(也不排除模型是适应了MNIST数据集的手写方式的原因),但是自己输入的图片放进模型前,经过预处理就可以很明显的提高识别准确率。
我做的预处理如下:
1、去噪:这一步对我输入的图片影响不大,因为我的图片是电子版的,噪声基本为0,但是如果是拍照的图片,一般噪声会比较大,建议增加去噪预处理。
2、黑白反转:这是我发现的最有效提高识别准确率的方法!!!我查看了MNIST数据集中的图片,发现都是黑底,就产生了疑问,最后通过查看图片像素点的值,猜测原因是黑色像素点值为0,白色像素点值为255,卷积操作是对应点相乘然后总体相加,0乘以任何数得0,所以背景为黑色就不会对卷积操作产生任何影响,减少了背景的干扰。
3、数字定位及图片切割:前文提到过,MNIST数据集是28*28的大小,所以我直接采用resize修改尺寸,等比缩小尺寸的情况下,对于较大的图片,其有效信息保留较少,反而背景信息占比较多,所以我使用了Sobel算子进行边缘定位,然后对定位出来的数字切割,减少背景所占的比例,然后再使用resize修改尺寸,有效信息占比有一定提高。
4、平滑锐化:尝试过,但对我的图片没有很好的效果,但是我相信是有效果的。
OVER!!!我的系统设计经过上面这些步骤之后,正确率还是在75%左右的,就一直卡在这个地方,上不去了,但是我输入的图片也算是各种各样(千奇百怪),正常手写的还是能成功识别的,数量一多,我相信模型的识别准确率应该也有明显提高。
吐槽。。。。然后老师打错分!!好憋屈