深入浅出Tensorflow(四):卷积神经网络

作者 | 郑泽宇

AI前线出品| ID:ai-front

2017年2月16日,Google正式对外发布Google TensorFlow 1.0版本,并保证本次的发布版本API接口完全满足生产环境稳定性要求。这是TensorFlow的一个重要里程碑,标志着它可以正式在生产环境放心使用。在国内,从InfoQ的判断来看,TensorFlow仍处于创新传播曲线的创新者使用阶段,大部分人对于TensorFlow还缺乏了解,社区也缺少帮助落地和使用的中文资料。InfoQ期望通过深入浅出TensorFlow系列文章能够推动Tensorflow在国内的发展。欢迎加入QQ群(群号:183248479)深入讨论和交流。下面为本系列的前三篇文章:

深入浅出Tensorflow(一):深度学习及TensorFlow简介

深入浅出TensorFlow(二):TensorFlow解决MNIST问题入门

深入浅出Tensorflow(三):训练神经网络模型的常用方法

卷积神经网络简介

斯坦福大学(Stanford University)李飞飞(Feifei Li)教授带头整理的ImageNet是图像识别领域非常有名的数据集。在ImageNet中,将近1500万图片被关联到了WordNet的大约20000个名词同义词集上。ImageNet每年都举办图像识别相关的竞赛(ImageNet Large Scale Visual Recognition Challenge,ILSVRC),其中最有名的就是ILSVRC2012图像分类数据集。ILSVRC2012图像分类数据集包含了来自1000个类别的120万张图片,其中每张图片属于且只属于一个类别。因为ILSVRC2012图像分类数据集中的图片是直接从互联网上爬取得到的,图片的大小从几千字节到几百万字节不等。

《深入浅出Tensorflow(四):卷积神经网络》 图1 不同算法在ImageNet ILSVRC2012图像分类数据集上的正确率

图1给出了不同算法在ImageNet图像分类数据集上的top-5正确率。top-N正确率指的是图像识别算法给出前N个答案中有一个是正确的概率。在图像分类问题上,很多学术论文都将前N个答案的正确率作为比较的方法,其中N的取值一般为3或5。从图1中可以看出,在ImageNet问题上,基于卷积神经网络的图像识别算法可以远远超过人类的表现。在图1的左侧对比了传统算法与深度学习算法的正确率。从图中可以看出,深度学习,特别是卷积神经网络,给图像识别问题带来了质的飞跃。2013年之后,基本上所有的研究都集中到了深度学习算法上。

《深入浅出Tensorflow(四):卷积神经网络》 全连接神经网络(a)

《深入浅出Tensorflow(四):卷积神经网络》 卷积神经网络(b)

                                             图2 全连接神经网络与卷积神经网络结构示意图

在前面的文章中所介绍的神经网络每两层之间的所有结点都是有边相连的,所以我们称这种网络结构为全连接层网络结构。图2显示了全连接神经网络与卷积神经网络的结构对比图。虽然图2中显示的全连接神经网络结构和卷积神经网络的结构直观上差异比较大,但实际上它们的整体架构是非常相似的。从图2中可以看出,卷积神经网络也是通过一层一层的节点组织起来的。和全连接神经网络一样,卷积神经网络中的每一个节点都是一个神经元。在全连接神经网络中,每相邻两层之间的节点都有边相连,于是一般会将每一层全连接层中的节点组织成一列,这样方便显示连接结构。而对于卷积神经网络,相邻两层之间只有部分节点相连,为了展示每一层神经元的维度,一般会将每一层卷积层的节点组织成一个三维矩阵。

除了结构相似,卷积神经网络的输入输出以及训练流程与全连接神经网络也基本一致。以图像分类为例,卷积神经网络的输入层就是图像的原始像素,而输出层中的每一个节点代表了不同类别的可信度。这和全连接神经网络的输入输出是一致的。在TensorFlow中训练一个卷积神经网络的流程和训练一个全连接神经网络没有任何区别。卷积神经网络和全连接神经网络的唯一区别就在于神经网络中相邻两层的连接方式。

使用全连接神经网络处理图像的最大问题在于全连接层的参数太多。对于MNIST数据,每一张图片的大小是,其中为图片的大小,表示图像是黑白的,只有一个色彩通道。假设第一层隐藏层的节点数为500个,那么一个全链接层的神经网络将有个参数。当图片更大时,比如在Cifar-10数据集中,图片的大小为,其中表示图片的大小,表示图片是通过红绿蓝三个色彩通道(channel)表示的。这样输入层就有3072个节点,如果第一层全连接层仍然是500个节点,那么这一层全链接神经网络将有个参数。参数增多除了导致计算速度减慢,还很容易导致过拟合问题。所以需要一个更合理的神经网络结构来有效地减少神经网络中参数个数。卷积神经网络就可以达到这个目的。

《深入浅出Tensorflow(四):卷积神经网络》 图3 用于图像分类问题的一种卷积神经网络架构图

图3给出了一个更加具体的卷积神经网络架构图。在卷积神经网络的前几层中,每一层的节点都被组织成一个三维矩阵。比如处理Cifar-10数据集中的图片时,可以将输入层组织成一个的三维矩阵。图3中虚线部分展示了卷积神经网络的一个连接示意图,从图中可以看出卷积神经网络中前几层中每一个节点只和上一层中部分的节点相连。卷积神经网络的具体连接方式将在下文中介绍。

卷积层网络结构

图4中显示了卷积层神经网络结构中最重要的部分,这个部分被称之为过滤器(filter)或者内核(kernel)。因为TensorFlow文档中将这个结构称之为过滤器(filter),所以我们将统称这个结构为过滤器。如图4所示,过滤器可以将当前层神经网络上的一个子节点矩阵转化为下一层神经网络上的一个单位节点矩阵。单位节点矩阵指的是一个长和宽都为1,但深度不限的节点矩阵。

《深入浅出Tensorflow(四):卷积神经网络》 图4  卷积层过滤器(filter)结构示意图

在一个卷积层中,过滤器所处理的节点矩阵的长和宽都是由人工指定的,这个节点矩阵的尺寸也被称之为过滤器的尺寸。常用的过滤器尺寸有3×3或5×5。因为过滤器处理的矩阵深度和当前层神经网络节点矩阵的深度是一致的,所以虽然节点矩阵是三维的,但过滤器的尺寸只需要指定两个维度。过滤器中另外一个需要人工指定的设置是处理得到的单位节点矩阵的深度,这个设置称为过滤器的深度。注意过滤器的尺寸指的是一个过滤器输入节点矩阵的大小,而深度指的是输出单位节点矩阵的深度。如图4所示,左侧小矩阵的尺寸为过滤器的尺寸,而右侧单位矩阵的深度为过滤器的深度。

如图4所示,过滤器的前向传播过程就是通过左侧小矩阵中的节点计算出右侧单位矩阵中节点的过程。为了直观地解释过滤器的前向传播过程,在下面的篇幅中将给出一个具体的样例。在这个样例中将展示如何通过过滤器将一个2×2×3的节点矩阵变化为一个1×1×5的单位节点矩阵。一个过滤器的前向传播过程和全连接层相似,它总共需要个参数,其中最后的+5为偏置项参数的个数。假设使用来表示对于输出单位节点矩阵中的第i个节点,过滤器输入节点的权重,使用表示第i个输出节点对应的偏置项参数,那么单位矩阵中的第i个节点的取值为:

《深入浅出Tensorflow(四):卷积神经网络》

其中为过滤器中节点的取值,为激活函数。如果将和组织成两个向量,那么一个过滤器的计算过程完全可以通过向量乘法来完成。卷积层结构的前向传播过程就是通过将一个过滤器从神经网络当前层的左上角移动到右下角,并且在移动中计算每一个对应的单位矩阵得到的。图5展示了卷积层结构前向传播的过程。为了更好地可视化过滤器的移动过程,图5中使用的节点矩阵深度都为1。在图5中,展示了在3×3矩阵上使用2×2过滤器的卷积层前向传播过程。在这个过程中,首先将这个过滤器用于左上角子矩阵,然后移动到左下角矩阵,再到右上角矩阵,最后到右下角矩阵。过滤器每移动一次,可以计算得到一个值(当深度为k时会计算出k个值)。将这些数值拼接成一个新的矩阵,就完成了卷积层前向传播的过程。图5的右侧显示了过滤器在移动过程中计算得到的结果与新矩阵中节点的对应关系。

《深入浅出Tensorflow(四):卷积神经网络》 图5 卷积层前向传播过程示意图

在图5中,只讲解了移动过滤器的方式,没有涉及到过滤器中的参数如何设定。在卷积神经网络中,每一个卷积层中使用的过滤器中的参数都是一样的。这是卷积神经网络一个非常重要的性质。从直观上理解,共享过滤器的参数可以使得图像上的内容不受位置的影响。以MNIST手写体数字识别为例,无论数字“1”出现在左上角还是右下角,图片的种类都是不变的。因为在左上角和右下角使用的过滤器参数相同,所以通过卷积层之后无论数字在图像上的哪个位置,得到的结果都一样。

共享每一个卷积层中过滤器中的参数可以巨幅减少神经网络上的参数。以Cifar-10问题为例,输入层矩阵的维度是32×32×3。假设第一层卷积层使用尺寸为5×5,深度为16的过滤器,那么这个卷积层的参数个数为个。上文提到过,使用500个隐藏节点的全连接层将有150万个参数。相比之下,卷积层的参数个数要远远小于全连接层。而且卷积层的参数个数和图片的大小无关,它只和过滤器的尺寸、深度以及当前层节点矩阵的深度有关。这使得卷积神经网络可以很好地扩展到更大的图像数据上。

《深入浅出Tensorflow(四):卷积神经网络》 图6 卷积层前向传播过程样例图

结合过滤器的使用方法和参数共享的机制,图6给出了使用了全0填充、移动步长为2的卷积层前向传播的计算流程。下面的公式给出了左上角格子取值的计算方法,其他格子可以依次类推。

                            ReLu(0×1+0×(-1)+0×0+1×2+1)=ReLu(3)=3

TensorFlow对卷积神经网络提供了非常好的支持,下面的程序实现了一个卷积层的前向传播过程。从以下代码可以看出,通过TensorFlow实现卷积层是非常方便的。

《深入浅出Tensorflow(四):卷积神经网络》

池化层网络结构

在卷积神经网络中,卷积层之间往往会加上一个池化层(pooling layer)。池化层可以非常有效地缩小矩阵的尺寸,从而减少最后全连接层中的参数。使用池化层既可以加快计算速度也有防止过拟合问题的作用。和卷积层类似,池化层前向传播的过程也是通过移动一个类似过滤器的结构完成的。不过池化层过滤器中的计算不是节点的加权和,而是采用更加简单的最大值或者平均值运算。使用最大值操作的池化层被称之为最大池化层(max pooling),这是被使用得最多的池化层结构。使用平均值操作的池化层被称之为平均池化层(average pooling)。

与卷积层的过滤器类似,池化层的过滤器也需要人工设定过滤器的尺寸、是否使用全0填充以及过滤器移动的步长等设置,而且这些设置的意义也是一样的。卷积层和池化层中过滤器移动的方式是相似的,唯一的区别在于卷积层使用的过滤器是横跨整个深度的,而池化层使用的过滤器只影响一个深度上的节点。所以池化层的过滤器除了在长和宽两个维度移动之外,它还需要在深度这个维度移动。下面的TensorFlow程序实现了最大池化层的前向传播算法。

《深入浅出Tensorflow(四):卷积神经网络》

对比池化层和卷积层前向传播在TensorFlow中的实现,可以发现函数的参数形式是相似的。在tf.nn.max_pool函数中,首先需要传入当前层的节点矩阵,这个矩阵是一个四维矩阵,格式和tf.nn.conv2d函数中的第一个参数一致。第二个参数为过滤器的尺寸。虽然给出的是一个长度为4的一维数组,但是这个数组的第一个和最后一个数必须为1。这意味着池化层的过滤器是不可以跨不同输入样例或者节点矩阵深度的。在实际应用中使用得最多的池化层过滤器尺寸为[1,2,2,1]或者[1,3,3,1]。

tf.nn.max_pool函数的第三个参数为步长,它和tf.nn.conv2d函数中步长的意义是一样的,而且第一维和最后一维也只能为1。这意味着在TensorFlow中,池化层不能减少节点矩阵的深度或者输入样例的个数。tf.nn.max_pool函数的最后一个参数指定了是否使用全0填充。这个参数也只有两种取值——VALID或者SAME,其中VALID表示不使用全0填充,SAME表示使用全0填充。TensorFlow还提供了tf.nn.avg_pool来实现平均池化层。tf.nn.avg_pool函数的调用格式和tf.nn.max_pool函数是一致的。

LeNet-5模型

LeNet-5模型是Yann LeCun教授于1998年在论文Gradient-based learning applied to document recognition中提出的,它是第一个成功应用于数字识别问题的卷积神经网络。在MNIST数据集上,LeNet-5模型可以达到大约99.2%的正确率。LeNet-5模型总共有7层,图7展示了LeNet-5模型的架构。

《深入浅出Tensorflow(四):卷积神经网络》 图7 LeNet-5模型结构图。

在下面的篇幅中将详细介绍LeNet-5模型每一层的结构。论文GradientBased Learning

Applied to Document Recognition提出的LeNet-5模型中,卷积层和池化层的实现与上文中介绍的TensorFlow的实现有细微的区别,这里不过多的讨论具体细节,而是着重介绍模型的整体框架。

第一层,卷积层

这一层的输入就是原始的图像像素,LeNet-5模型接受的输入层大小为32×32×1。第一个卷积层过滤器的尺寸为5×5,深度为6,不使用全0填充,步长为1。因为没有使用全0填充,所以这一层的输出的尺寸为,深度为6。这一个卷积层总共有个参数,其中6个为偏置项参数。因为下一层的节点矩阵有个节点,每个节点和个当前层节点相连,所以本层卷积层总共有个连接。

第二层,池化层

这一层的输入为第一层的输出,是一个28×28×6的节点矩阵。本层采用的过滤器大小为2×2,长和宽的步长均为2,所以本层的输出矩阵大小为14×14×6。原始的LeNet-5模型中使用的过滤器和本文中介绍的有些细微差别,这里不做具体介绍。

第三层,卷积层

本层的输入矩阵大小为14×14×6,使用的过滤器大小为5×5,深度为16。本层不使用全0填充,步长为1。本层的输出矩阵大小为10×10×16。按照标准的卷积层,本层应该有个参数,个连接。

第四层,池化层

本层的输入矩阵大小为10×10×16,采用的过滤器大小为2×2,步长为2。本层的输出矩阵大小为5×5×16。

第五层,全连接层

本层的输入矩阵大小为5×5×16,在LeNet-5模型的论文中将这一层称为卷积层,但是因为过滤器的大小就是5×5,所以和全连接层没有区别,在之后的TensorFlow程序实现中也会将这一层看成全连接层。如果将5×5×16矩阵中的节点拉成一个向量,那么这一层和在第四章中介绍的全连接层输入就一样了。本层的输出节点个数为120,总共有个参数。

第六层,全连接层

本层的输入节点个数为120个,输出节点个数为84个,总共参数为个。

第七层,全连接层

本层的输入节点个数为84个,输出节点个数为10个,总共参数为个。

上面介绍了LeNet-5模型每一层结构和设置,下面给出一个TensorFlow的程序来实现一个类似LeNet-5模型的卷积神经网络来解决MNIST数字识别问题。通过TensorFlow训练卷积神经网络的过程和第五章中介绍的训练全连接神经网络是完全一样的。损失函数的计算、反向传播过程的实现都可以复用上一篇中给出的mnist_train.py程序。唯一的区别在于因为卷积神经网络的输入层为一个三维矩阵,所以需要调整一下输入数据的格式:

《深入浅出Tensorflow(四):卷积神经网络》

在调整完输入格式之后,只需要在程序mnist_inference.py中实现类似LeNet-5模型结构的前向传播过程即可。下面给出了修改后的mnist_infernece.py程序。

《深入浅出Tensorflow(四):卷积神经网络》
《深入浅出Tensorflow(四):卷积神经网络》
《深入浅出Tensorflow(四):卷积神经网络》

运行修改后的mnist_train.py和mnist_eval.py,可以得到一下测试结果:

《深入浅出Tensorflow(四):卷积神经网络》

上面的程序可以将MNIST正确率达到~99.4%。

本文内容来自作者图书作品《TensorFlow:实战Google深度学习框架》

作者介绍

郑泽宇,才云首席大数据科学家,前谷歌高级工程师。从 2013 年加入谷歌至今,郑泽宇作为主要技术人员参与并领导了多个大数据项目,拥有丰富机器学习、数据挖掘工业界及科研项目经验。2014 年,他提出产品聚类项目用于衔接谷歌购物和谷歌知识图谱(Knowledge Graph)数据,使得知识卡片形式的广告逐步取代传统的产品列表广告,开启了谷歌购物广告在搜索页面投递的新纪元。他于2013 年 5 月获得美国 Carnegie Mellon University(CMU)大学计算机硕士学位, 期间在顶级国际学术会议上发表数篇学术论文,并获得西贝尔奖学金。

-全文完-

关注人工智能的落地实践,与企业一起探寻 AI 的边界,AICon 全球人工智能技术大会火热售票中,8 折倒计时一周抢票,详情点击:

https://aicon.geekbang.org/?utm_source=ai-front&utm_medium=zhihu

《深入浅出TensorFlow》迷你书现已发布,关注公众号“AI前线”,ID:ai-front,回复关键字:TF,获取下载链接!

《深入浅出Tensorflow(四):卷积神经网络》

    原文作者:AI前线
    原文地址: https://www.jianshu.com/p/1b55850c1d62
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞