基于tensorflow的MNIST手写字识别

来源:互联网 发布:dijkstra算法的优缺点 编辑:程序博客网 时间:2024/05/01 03:18

一、卷积神经网络模型知识要点卷积卷积

1、卷积
2、池化
3、全连接
4、梯度下降法
5、softmax

本次就是用最简单的方法给大家讲解这些概念,因为具体的各种论文网上都有,连推导都有,所以本文主要就是给大家做个铺垫,如有错误请指正,相互学习共同进步。

二、卷积神经网络讲解

    2.1卷积神经网络作用

     大家应该知道大名鼎鼎的傅里叶变换,即一个波形,可以有不同的正弦函数和余弦函数进行叠加完成,卷积神经网络也是一样,可以认为一张图片是由各种不同特征的图片叠加而成的,所以它的作用是用来提取特定的特征,举个例子,比如给定一张图片,然后我只想提取它的轮廓,于是就需要卷积神经网络。

                                            

2.2卷积神经网络模型

                 

             如图是大名鼎鼎的LeNet-5(识别数字的卷积网络),效果和论文在此,这里拿出来只是为了说明一下卷积神经网络的模型,就像图中那样,经过多次,卷积,池化(又叫子采样),然后全连接,就完工了。

2.3 卷积

        

2.3.1 卷积的原理

其实卷积很好理解,左侧绿色的部分的5*5矩阵其实一般就是我们输入的图片的灰度值(可以想象成一张5px*5px的黑白照片,然后把黑白照片上的每一个点转化成矩阵上的每一个元素),然后上面的黄色部分矩阵就是我们的过滤器,用来提取特征,(其实应该叫滤波器或者卷积核),让卷积核在输入矩阵上进行从左到右,从上到下滑动,然后每一次滑动,两个矩阵对应位置的元素相乘然后求和,就是右边那个矩阵的一个元素。

2.3.2 滑动的步长-stride

上面那张图片从左到右,每次滑动的时候只移动一格,但是其实它一次滑动多格,这就是步长

2.3.3 卷积的边界处理-padding

如上图所示,卷积后的矩阵只有3*3,比原来的图片要小了,因为边界没有了,所以要考虑这个边界的问题,网上说卷积的边界处理有两种方式:
一、丢掉边界,也就是就按右边那个缩小的矩阵来。
二、复制边界,也就是把左边的最外层原封不动地复制过去

但是在看matlab代码和tensorflow代码的时候发现并不是那么简单的事情。
matlab中conv2这个“padding”参数可以设为三个值FULL,SAME,VALID
tensorflow中conv2d的"padding"参数可以设为两个值SAME,VALID

它们对边界是这样处理的,对输入的矩阵,包裹n层0,然后再按照上面所说的卷积方法进行卷积,这个n怎么求呢,
FULL: edge_row = kernel_row - 1;   edge_cols = kernel_cols - 1; 
SAME: edge_row = (kernel_row - 1) / 2;   edge_cols = (kernel_cols - 1) / 2; 
VALID:edge_row = edge_cols = 0;  

edge_row就是边的行数,kernel_row就是卷积核的行数,所以上面讲的其实就是VALID模式
 

         2.3.4 卷积与神经网络


右下角就是卷积的数学公式,矩阵的对应元素相乘求和,然后加上一个偏置值

      2.4 池化

池化分为两种,一种是最大池化,在选中区域中找最大的值作为抽样后的值,另一种是平均值池化,把选中的区域中的平均值作为抽样后的值,这样做的,原因是为了后面全连接的时候减少连接数

2.5 全连接


左边的是没有没有进行卷积的全连接,假设图片是1000*1000的,然后用1M的神经元去感知,最后需要10^12个权值作为参数,右边是经过卷积过的,每个圆点是一个神经元,因此只是用一个卷积核的话,其实只要100*10^6,数量级就大大减少,而且因为提取的就是所需的特征,所以在加快训练速度的时候对结果并不会产生过大的影响,甚至更为精确。


2.6 梯度下降法

可能很多人会问,那个卷积核是怎么得出来的呢,其实它是被各种训练集训练出来的,利用梯度下降法使得我们的参数到达最优解。
梯度下降法可以这样子理解,假设我们正在下山,要使得下山的路径达到最短,于是我们每走一步之前就判断一下四面八方从哪个方向跨出这一步会最短,不过学过算法的人应该都知道,有个问题就是,我们当前走的这一步是当前位置最短的,但是真正从山上到山下最短路径可能并不路过这一步。也就是说这是个局部最优解,而不是全局最优解,我们得到的路径并不一定是最短的,但是也足够优秀,原因就是,得到最优解费时费力,性价比并不高。这一个知识点还是建议大家伙去看一下斯坦福Andrew Ng的《机器学习》,然后就能理解上面所说的权值参数要少的意义了。


2.7最后 softmax

softmax是分类用的,说直白一点就是归一化,因为这个店最好跟例子结合起来,所以暂时不多说,感兴趣的可以去网上找,也可以关注后面的系列文章。

三、总结

其实感觉讲的并不深入,因此还是希望各位能自己去仔细钻研一下,这里给各位一些基础吧,读起论文和数学公式来会更轻松一些。

四、参考

[javascript] view plain copy
  1. <span style="font-family:Microsoft YaHei;">神经网络介绍  
  2. http://ufldl.stanford.edu/wiki/index.php/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C  
  3.   
  4. 技术向:一文读懂卷积神经网络CNN  
  5. http://www.cnblogs.com/nsnow/p/4562308.html  
  6.   
  7.    
  8. 深度学习(卷积神经网络)一些问题总结  
  9. http://blog.csdn.net/nan355655600/article/details/17690029  
  10.   
  11.   
  12. 卷积神经网络(CNN)  
  13. http://ibillxia.github.io/blog/2013/04/06/Convolutional-Neural-Networks/  
  14.   
  15.   
  16. Deep Learning模型之:CNN卷积神经网络(一)深度解析CNN  
  17. http://www.cnblogs.com/nsnow/p/4562363.html  
  18.   
  19.   
  20. 数据挖掘系列(10)——卷积神经网络算法的一个实现(转)  
  21. http://blog.sina.com.cn/s/blog_4ff49c7e0102vl5m.html  
  22.   
  23.   
  24. Matlab/DeepLearnToolbox  
  25. https://github.com/rasmusbergpalm/DeepLearnToolbox  
  26.   
  27.   
  28. Deep Learning论文笔记之(四)CNN卷积神经网络推导和实现  
  29. http://blog.csdn.net/zouxy09/article/details/9993371  
  30.   
  31.   
  32.    
  33. Deep Learning论文笔记之(五)CNN卷积神经网络代码理解  
  34.   
  35. http://blog.csdn.net/zouxy09/article/details/9993743  
  36.   
  37.   
  38. 斯坦福  池化  
  39. http://ufldl.stanford.edu/wiki/index.php/%E6%B1%A0%E5%8C%96  
  40.   
  41. CNN神经网络层次分析  
  42. http://blog.csdn.net/liulina603/article/details/44915905  
  43.   
  44. 深度学习笔记1(卷积神经网络)  
  45. http://blog.csdn.net/lu597203933/article/details/46575779  
  46.   
  47.   
  48. CNN公式推导  
  49. http://blog.csdn.net/lu597203933/article/details/46575871  
  50.   
  51. 前向型神经网络之BPNN(附源码)  
  52. http://blog.csdn.net/heyongluoyao8/article/details/48213345  
  53.   
  54. 残差与误差的区别  
  55. http://wenku.baidu.com/link?url=DUDkyV1tnD_SEGzgcxb9AaFU5VUcP9ISNR8q39-fpCcq_LGUHY7ucx5vDwr-MCfU_ofr7yIQZ_UgTfiivTtaDOulW2DD3pGs07eYmiQv5P7  
  56.   
  57. 反向传导算法  
  58. http://deeplearning.stanford.edu/wiki/index.php/%E5%8F%8D%E5%90%91%E4%BC%A0%E5%AF%BC%E7%AE%97%E6%B3%95  
  59.   
  60.   
  61. 图像卷积与滤波的一些知识点  
  62. http://blog.csdn.net/zouxy09/article/details/49080029  
  63.   
  64. CNN卷积神经网络原理简介+代码详解  
  65. http://doc.okbase.net/u012162613/archive/126058.html  
  66.   
  67. 卷积神经网络(lenet)  
  68. http://deeplearning.net/tutorial/lenet.html  
  69.   
  70.   
  71. 激活函数的作用  
  72. https://www.zhihu.com/question/22334626  
  73.   
  74. 神经网络入门第一部分  
  75. http://blog.sina.com.cn/s/blog_6a67b5c50100tspb.html  
  76.   
  77. 神经网络入门第二部分  
  78. http://blog.sina.com.cn/s/blog_6a67b5c50100tspe.html  
  79.   
  80. 卷积神经网络全面解析  
  81. http://www.moonshile.com/post/juan-ji-shen-jing-wang-luo-quan-mian-jie-xi  
  82.   
  83. Deep learning:四十一(Dropout简单理解)  
  84. http://www.cnblogs.com/tornadomeet/p/3258122.html  
  85.   
  86. DeepLearning (六) 学习笔记整理:神经网络以及卷积神经网络  
  87. http://www.07net01.com/2015/11/963741.html  
  88.   
  89.    
  90. 深度卷积网络CNN与图像语义分割  
  91. http://blog.csdn.net/xiahouzuoxin/article/details/47789361  
  92.   
  93.    
  94. MATLAB conv2卷积的实现  
  95. http://blog.csdn.net/celerychen2009/article/details/38852105  
  96. </span>  


基于tensorflow的MNIST手写字识别(一)--白话卷积神经网络模型


一、本文的意义


      因为谷歌官方其实已经写了MNIST入门和深入两篇教程了,那我写这些文章又是为什么呢,只是抄袭?那倒并不是,更准确的说应该是笔记吧,然后用更通俗的语言来解释,并且补充更多,官方文章中没有详细展开的一些知识点,不过建议与官方文章结合着阅读。

       另外是代码部分的改动,官方的demo只提供了验证精确度,我将它改造成了能输入并预测输出结果的代码也就是说是一个从准备待测图片到最终是别的一个完整demo


 中文版本:MNIST机器学习入门
http://wiki.jikexueyuan.com/project/tensorflow-zh/tutorials/mnist_beginners.html


需要识别的图片放到test_num里,然后运行mnist_softmax.py就好了
demo截图如下,会将放进去的图片预测,然后输出结果,代码说明请看github的readme(最底下)



二、MNIST简介

[javascript] view plain copy
  1. <span style="font-family:Microsoft YaHei;">官网:http://yann.lecun.com/exdb/mnist/</span>  

这个MNIST数据库是一个手写数字的数据库,它提供了六万的训练集和一万的测试集。
它的图片是被规范处理过的,是一张被放在中间部位的28px*28px的灰度图

总共4个文件:

train-images-idx3-ubyte: training set images 
train-labels-idx1-ubyte: training set labels 
t10k-images-idx3-ubyte:  test set images 
t10k-labels-idx1-ubyte:  test set labels

图片都被转成二进制放到了文件里面,
所以,每一个文件头部几个字节都记录着这些图片的信息,然后才是储存的图片信息

TRAINING SET LABEL FILE (train-labels-idx1-ubyte):

[offset] [type]          [value]          [description] 
0000     32 bit integer  0x00000801(2049) magic number (MSB first) 
0004     32 bit integer  60000            number of items 
0008     unsigned byte   ??               label 
0009     unsigned byte   ??               label 
........ 
xxxx     unsigned byte   ??               label

The labels values are 0 to 9.

TRAINING SET IMAGE FILE (train-images-idx3-ubyte):

[offset] [type]          [value]          [description] 
0000     32 bit integer  0x00000803(2051) magic number 
0004     32 bit integer  60000            number of images 
0008     32 bit integer  28               number of rows 
0012     32 bit integer  28               number of columns 
0016     unsigned byte   ??               pixel 
0017     unsigned byte   ??               pixel 
........ 
xxxx     unsigned byte   ??               pixel

每个像素被转成了0-255,0代表着白色,255代表着黑色。

TEST SET LABEL FILE (t10k-labels-idx1-ubyte):

[offset] [type]          [value]          [description] 
0000     32 bit integer  0x00000801(2049) magic number (MSB first) 
0004     32 bit integer  10000            number of items 
0008     unsigned byte   ??               label 
0009     unsigned byte   ??               label 
........ 
xxxx     unsigned byte   ??               label

The labels values are 0 to 9.

TEST SET IMAGE FILE (t10k-images-idx3-ubyte):

[offset] [type]          [value]          [description] 
0000     32 bit integer  0x00000803(2051) magic number 
0004     32 bit integer  10000            number of images 
0008     32 bit integer  28               number of rows 
0012     32 bit integer  28               number of columns 
0016     unsigned byte   ??               pixel 
0017     unsigned byte   ??               pixel 
........ 
xxxx     unsigned byte   ??               pixel

每个像素被转成了0-255,0代表着白色,255代表着黑色。


三、tensorflow手写数字识别的大致步骤


1、将要识别的图片转为灰度图,并且转化为28*28矩阵(单通道,每个像素范围0-255,0为黑色,255为白色,这一点与MNIST中的正好相反)
2、将28*28的矩阵转换成1维矩阵(也就是把第2,3,4,5....行矩阵纷纷接入到第一行的后面)
3、用一个1*10的向量代表标签,也就是这个数字到底是几,举个例子e数字1对应的矩阵就是[0,1,0,0,0,0,0,0,0,0]
4、softmax回归预测图片是哪个数字的概率
5、用交叉熵和梯度下降法训练参数

四、过程讲解


4.1 准备要识别的图片


这个部分其实是比较重要的,因为如果处理不得当可能并不一定会有很好的结果,所以按照mnist的标准规范需要将待测图片转为28×28且文字居中的灰度图(其实彩色的也可以,不过就是最后代码需要改一下),目前介绍两种获得待测图片的方法:
1、自己用ps或者真的手写一些数字
2、将MNIST数据库中的二进制转化成图片,然后用来做测试
              ps:图片解析  点击进入

4.2 将待测图片转换为矩阵


     如图所示,根据黑色部分的浓淡将其转化成微一个浮点数的数组,(白色0,黑色1)

           看到这里,如果你跟我一样不熟悉python,是不是开始方了,没事,其实python很厉害,自带的PIL图片库一句话就可以搞定
    
[python] view plain copy
  1. <span style="font-family:Microsoft YaHei;">img=array(Image.open(filename))         //打开然后就被numpy转化了</span>  



如果是彩色的图片,则需要先将它这样子转换一下(我当初并不知道可以转化,傻不垃圾地自己写了一个转化,所以python还是好好学习啊)
[python] view plain copy
  1. <span style="font-family:Microsoft YaHei;"> im=Image.open("test_num3/8_3.png")  
  2. Lim  = img=array(im.convert("L")) </span>  


           

4.3将矩阵转化为一维矩阵,以及标签的介绍


转化为一维的矩阵其实并不难,用python的reshape就能搞定,还是要讲一下标签的表示方法,这个曾经令队友疑惑不久,直到我把这个数组打印出来

4.3.1标签的来历--有监督学习 和 无监督学习


 监督学习:利用一组已知类别的样本调整分类器的参数,使其达到所要求性能的过程,也称为监督训练或有教师学习    举个例子,MNIST自带了训练图片和训练标签,每张图片都有一个对应的标签,比如这张图片是1,标签也就是1,用他们训练程序,之后程序也就能识别测试集中的图片了,比如给定一张2的图片,它能预测出他是2    无监督学习:其中很重要的一类叫聚类    举个例子,如果MNIST中只有训练图片,没有标签,我们的程序能够根据图片的不同特征,将他们分类,但是并不知道他们具体是几,这个其实就是“聚类”

4.3.2 标签的表示

在这里标签的表示方式有些特殊,它也是使用了一个一维数组,而不是单纯的数字,上面也说了,他是一个一位数组,0表示方法[1,0,0,0,0,0,0,0,0,0],1表示[0,1,0,0,0,0,0,0,0,0],........., 主要原因其实是这样的,因为softmax回归处理后会生成一个1*10的数组,数组[0,0]的数字表示预测的这张图片是0的概率,[0,1]则表示这张图片表示是1的概率......以此类推,这个数组表示的就是这张图片是哪个数字的概率(已经归一化),因此,实际上,概率最大的那个数字就是我们所预测的值。两者对应来看,标准的标签就是表示图片对应数字的概率为100%,而表示其它数字的概率为0,举个例子,0表示[1,0,0,0,0,0,0,0,0,0],可以理解为它表示0的概率为1,而表示别的数字的概率为0.


4.4 softmax回归

    这是一个分类器,可以认为是Logistic回归的扩展,Logistic大家应该都听说过,就是生物学上的S型曲线,它只能分两类,用0和1表示,这个用来表示答题对错之类只有两种状态的问题时足够了,但是像这里的MNIST要把它分成10类,就必须用softmax来进行分类了。  

    P(y=0)=p0,P(y=1)=p1,p(y=2)=p2......P(y=9)=p9.这些表示预测为数字i的概率,(跟上面标签的格式正好对应起来了),它们的和为1,即 ∑(pi)=1。

    tensorflow实现了这个函数,我们直接调用这个softmax函数即可,对于原理,可以参考下面的引文,这里只说一下我们这个MNIST demo要用softmax做什么。

  (注:每一个神经元都可以接收来自网络中其他神经元的一个或多个输入信号,神经元与神经元之间都对应着连接权值,所有的输入加权和决定该神经元是处于激活还是抑制状态。感知器网络的输出只能取值0或1,不具备可导性。而基于敏感度的训练算法要求其输出函数必须处处可导,于是引入了常见的S型可导函数,即在每个神经元的输出之前先经过S型激活函数的处理。)


4.5 交叉熵

通俗一点就是,方差大家都知道吧,用它可以衡量预测值和实际值的相差程度,交叉熵其实也是一样的作用,那为什么不用方差呢,因为看sigmoid函数的图像就会发现,它的两侧几乎就是平的,导致它的方差在大部分情况下很小,这样在训练参数的时候收敛地就会很慢,交叉熵就是用来解决这个问题的,它的公式是 ,其中,y 是我们预测的概率分布, y' 是实际的分布。



4.6 梯度下降

      上面那步也说了,有个交叉熵,根据大伙对方差的理解,值越小,自然就越好,因此我们也要训练使得交叉熵最小的参数,这里梯度下降法就派上用场了,这个解释见上一篇系列文章吧,什么叫训练参数呢,可以想象一下,我们先用实际的值在二位坐标上画一条线,然后我们希望我们预测出来的那些值要尽可能地贴近这条线,我们假设生成我们这条线的公式ax+ax^2+bx^3+.....,我们需要生成这些系数,要求得这些系数,我们就需要各种点代入,然后才能求出,所以其实训练参数跟求参数是个类似的过程。


4.7 预测

      训练结束以后我们就可以用这个模型去预测新的图片了,就像我们已经求出来了方程,以后只要随意输入一个x,就能求出对应的y。
           

5 代码

[javascript] view plain copy
  1. https://github.com/wlmnzf/tensorflow-train/tree/master/mnist  

6 参考文章

[python] view plain copy
  1. <span style="font-family:Microsoft YaHei;font-size:18px;">http://blog.csdn.net/acdreamers/article/details/44663305   softmax回归</span>  
[python] view plain copy
  1. <span style="font-family:Microsoft YaHei;font-size:18px;">http://wiki.jikexueyuan.com/project/tensorflow-zh/tutorials/mnist_beginners.html    MNIST学习入门  
  2. </span>  
[python] view plain copy
  1. <span style="font-family:Microsoft YaHei;font-size:18px;">http://blog.csdn.net/u012162613/article/details/44239919   交叉熵代价函数</span>  

原创粉丝点击