原文
卷积网络LeNet5
LeNet5 诞生于1994年,是最早的深层卷积神经网络之一,并且推动了深度学习的发展。从1988年开始,在多次成功的迭代后,这项由Yann LeCun完成的开拓性成果被命名为LeNet5。
LeCun认为,可训练参数的卷积层是一种用少量参数在图像的多个位置上提取相似特征的有效方式,这和直接把每个像素作为多层神经网络的输入不同。像素不应该被使用在输入层,因为图像具有很强的空间相关性,而使用图像中独立的像素直接作为输入则利用不到这些相关性。LeNet5当时的特性有如下几点:
每个卷积层包含三个部分:卷积、池化和非线性激活函数
使用卷积提取空间特征
降采样(Subsample)的平均池化层(Average Pooling)
双曲正切(Tanh)或S型(Sigmoid)的激活函数
MLP作为最后的分类器
层与层之间的稀疏连接减少计算复杂度
LeNet5中的诸多特性现在依然在state-of-the-art卷积神经网络中使用,可以说LeNet5是奠定了现代卷积神经网络的基石之作。Lenet-5的结构下图所示。
它的输入图像为32×32的灰度值图像,后面有3个卷积层,1个全连接层和1个高斯连接层。
下面介绍一些其他几个经典的卷积网络结构,AlexNet、VGGNet、Google Inception Net和ResNet,这4种网络依照出现的先后顺序排列,深度和复杂度也依次递进。它们分别获得了ILSVRC(ImageNet Large Scale Visual Recognition Challenge)比赛分类项目的2012年冠军(AlexNet, top-5错误率16.4%,使用额外数据可达到15.3%,8层神经网络)、2014年亚军(VGGNet,top-5错误率7.3%,19层神经网络),2014年冠军(InceptionNet,top-5错误率6.7%,22层神经网络)和2015年的冠军(ResNet,top-5错误率3.57%,152层神经网络)。
如图所示,ILSVRC的top-5错误率在最近几年取得重大突破,而主要的突破点都是在深度学习和卷积神经网络,成绩的大幅提升几乎都伴随着卷积神经网络的层数加深。
前面提到的计算机视觉比赛ILSVRC使用的数据都来自ImageNet,如上图所示。ImageNet项目于2007年由斯坦福大学华人教授李飞飞创办,目标是收集大量带有标注信息的图片数据供计算机视觉模型训练。ImageNet拥有1500万张标注过的高清图片,总共拥有22000类,其中约有100万张标注了图片中主要物体的定位边框。
每年度的ILSVRC比赛数据集中大概拥有120万张图片,以及1000类的标注,是ImageNet全部数据的一个子集。比赛一般采用top-5和top-1分类错误率作为模型性能的评测指标,上图所示为AlexNet识别ILSVRC数据集中图片的情况,每张图片下面是分类预测得分最高的5个分类及其分值。
AlexNet技术特点概要AlexNet是现代深度CNN的奠基之作。2012年,Hinton的学生Alex Krizhevsky提出了深度卷积神经网络模型AlexNet,它可以算是LeNet的一种更深更宽的版本。AlexNet中包含了几个比较新的技术点,也首次在CNN中成功应用了ReLU、Dropout和LRN等Trick。同时AlexNet也使用了GPU进行运算加速,作者开源了他们在GPU上训练卷积神经网络的CUDA代码。
AlexNet包含了6亿3000万个连接,6000万个参数和65万个神经元,拥有5个卷积层,其中3个卷积层后面连接了最大池化层,最后还有3个全连接层。AlexNet以显著的优势赢得了竞争激烈的ILSVRC 2012比赛,top-5的错误率降低至了16.4%,相比第二名的成绩26.2%错误率有了巨大的提升。
AlexNet将LeNet的思想发扬光大,把CNN的基本原理应用到了很深很宽的网络中。AlexNet主要使用到的新技术点如下。
成功使用ReLU作为CNN的激活函数,并验证其效果在较深的网络超过了Sigmoid,成功解决了Sigmoid在网络较深时的梯度弥散问题。虽然ReLU激活函数在很久之前就被提出了,但是直到AlexNet的出现才将其发扬光大。
训练时使用Dropout随机忽略一部分神经元,以避免模型过拟合。Dropout虽有单独的论文论述,但是AlexNet将其实用化,通过实践证实了它的效果。在AlexNet中主要是最后几个全连接层使用了Dropout。
在CNN中使用重叠的最大池化。此前CNN中普遍使用平均池化,AlexNet全部使用最大池化,避免平均池化的模糊化效果。并且AlexNet中提出让步长比池化核的尺寸小,这样池化层的输出之间会有重叠和覆盖,提升了特征的丰富性。
提出了LRN层,对局部神经元的活动创建竞争机制,使得其中响应比较大的值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力。
使用CUDA加速深度卷积网络的训练,利用GPU强大的并行计算能力,处理神经网络训练时大量的矩阵运算。AlexNet使用了两块GTX 580 GPU进行训练,单个GTX 580只有3GB显存,这限制了可训练的网络的最大规模。因此作者将AlexNet分布在两个GPU上,在每个GPU的显存中储存一半的神经元的参数。
数据增强,随机地从256*256的原始图像中截取224*224大小的区域(以及水平翻转的镜像),相当于增加了(256224)2*2=2048倍的数据量。如果没有数据增强,仅靠原始的数据量,参数众多的CNN会陷入过拟合中,使用了数据增强后可以大大减轻过拟合,提升泛化能力。进行预测时,则是取图片的四个角加中间共5个位置,并进行左右翻转,一共获得10张图片,对他们进行预测并对10次结果求均值。
整个AlexNet有8个需要训练参数的层(不包括池化层和LRN层),前5层为卷积层,后3层为全连接层,上图所示。AlexNet最后一层是有1000类输出的Softmax层用作分类。LRN层出现在第1个及第2个卷积层后,而最大池化层出现在两个LRN层及最后一个卷积层后。
AlexNet每层的超参数、参数量、计算量上图所示。
我们可以发现一个比较有意思的现象,在前几个卷积层,虽然计算量很大,但参数量很小,都在1M左右甚至更小,只占AlexNet总参数量的很小一部分。这就是卷积层有用的地方,可以通过较小的参数量提取有效的特征。虽然每一个卷积层占整个网络的参数量的1%都不到,但是如果去掉任何一个卷积层,都会使网络的分类性能大幅地下降。
VGGNet技术特点概要VGGNet是牛津大学计算机视觉组(Visual Geometry Group)和Google DeepMind公司的研究员一起研发的的深度卷积神经网络。VGGNet探索了卷积神经网络的深度与其性能之间的关系,通过反复堆叠3*3的小型卷积核和2*2的最大池化层,VGGNet成功地构筑了16~19层深的卷积神经网络。VGGNet相比之前state-of-the-art的网络结构,错误率大幅下降,并取得了ILSVRC 2014比赛分类项目的第2名和定位项目的第1名。
VGGNet论文中全部使用了3*3的卷积核和2*2的池化核,通过不断加深网络结构来提升性能。下图所示为VGGNet各级别的网络结构图,和每一级别的参数量,从11层的网络一直到19层的网络都有详尽的性能测试。
虽然从A到E每一级网络逐渐变深,但是网络的参数量并没有增长很多,这是因为参数量主要都消耗在最后3个全连接层。前面的卷积部分虽然很深,但是消耗的参数量不大,不过训练比较耗时的部分依然是卷积,因其计算量比较大。
VGGNet拥有5段卷积,每一段内有2~3个卷积层,同时每段尾部会连接一个最大池化层用来缩小图片尺寸。每段内的卷积核数量一样,越靠后的段的卷积核数量越多:64 – 128 – 256 – 512 – 512。其中经常出现多个完全一样的3*3的卷积层堆叠在一起的情况,这其实是非常有用的设计。
如上图所示,两个3*3的卷积层串联相当于1个5*5的卷积层,即一个像素会跟周围5*5的像素产生关联,可以说感受野大小为5*5。而3个3*3的卷积层串联的效果则相当于1个7*7的卷积层。除此之外,3个串联的3*3的卷积层,拥有比1个7*7的卷积层更少的参数量,只有后者的55%。最重要的是,3个3*3的卷积层拥有比1个7*7的卷积层更多的非线性变换(前者可以使用三次ReLU激活函数,而后者只有一次),使得CNN对特征的学习能力更强。
作者在对比各级网络时总结出了以下几个观点。
LRN层作用不大。
越深的网络效果越好。
1*1的卷积也是很有效的,但是没有3*3的卷积好,大一些的卷积核可以学习更大的空间特征。
Google Inception Net首次出现在ILSVRC 2014的比赛中(和VGGNet同年),就以较大优势取得了第一名。那届比赛中的Inception Net通常被称为Inception V1,它最大的特点是控制了计算量和参数量的同时,获得了非常好的分类性能——top-5错误率6.67%,只有AlexNet的一半不到。
Inception V1有22层深,比AlexNet的8层或者VGGNet的19层还要更深。但其计算量只有15亿次浮点运算,同时只有500万的参数量,仅为AlexNet参数量(6000万)的1/12,却可以达到远胜于AlexNet的准确率,可以说是非常优秀并且非常实用的模型。
Inception V1降低参数量的目的有两点:第一,参数越多模型越庞大,需要供模型学习的数据量就越大,而目前高质量的数据非常昂贵;第二,参数越多,耗费的计算资源也会更大。
Inception V1参数少但效果好的原因除了模型层数更深、表达能力更强外,还有两点:一是去除了最后的全连接层,用全局平均池化层(即将图片尺寸变为1*1)来取代它。全连接层几乎占据了AlexNet或VGGNet中90%的参数量,而且会引起过拟合,去除全连接层后模型训练更快并且减轻了过拟合。二是Inception V1中精心设计的Inception Module提高了参数的利用效率,其结构如图10所示。这一部分也借鉴了Network In Network的思想,形象的解释就是Inception Module本身如同大网络中的一个小网络,其结构可以反复堆叠在一起形成大网络。
我们再来看Inception Module的基本结构,其中有4个分支:第一个分支对输入进行1*1的卷积,这其实也是NIN中提出的一个重要结构。1*1的卷积是一个非常优秀的结构,它可以跨通道组织信息,提高网络的表达能力,同时可以对输出通道升维和降维。
可以看到Inception Module的4个分支都用到了1*1卷积,来进行低成本(计算量比3*3小很多)的跨通道的特征变换。第二个分支先使用了1*1卷积,然后连接3*3卷积,相当于进行了两次特征变换。第三个分支类似,先是1*1的卷积,然后连接5*5卷积。最后一个分支则是3*3最大池化后直接使用1*1卷积。Inception Module的4个分支在最后通过一个聚合操作合并(在输出通道数这个维度上聚合)。
同时,Google Inception Net还是一个大家族,包括:
2014年9月的论文Going Deeper with Convolutions提出的Inception V1(top-5错误率6.67%)。
2015年2月的论文Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate提出的Inception V2(top-5错误率4.8%)。
2015年12月的论文Rethinking the Inception Architecture for Computer Vision提出的Inception V3(top-5错误率3.5%)。
2016年2月的论文Inception-v4, Inception-ResNet and the Impact of Residual Connections on Learning提出的Inception V4(top-5错误率3.08%)。
Inception V2学习了VGGNet,用两个3*3的卷积代替5*5的大卷积(用以降低参数量并减轻过拟合),还提出了著名的Batch Normalization(以下简称BN)方法。BN是一个非常有效的正则化方法,可以让大型卷积网络的训练速度加快很多倍,同时收敛后的分类准确率也可以得到大幅提高。
BN在用于神经网络某层时,会对每一个mini-batch数据的内部进行标准化(normalization)处理,使输出规范化到N(0,1)的正态分布,减少了Internal Covariate Shift(内部神经元分布的改变)。
BN的论文指出,传统的深度神经网络在训练时,每一层的输入的分布都在变化,导致训练变得困难,我们只能使用一个很小的学习速率解决这个问题。而对每一层使用BN之后,我们就可以有效地解决这个问题,学习速率可以增大很多倍,达到之前的准确率所需要的迭代次数只有1/14,训练时间大大缩短。而达到之前的准确率后,可以继续训练,并最终取得远超于Inception V1模型的性能——top-5错误率4.8%,已经优于人眼水平。因为BN某种意义上还起到了正则化的作用,所以可以减少或者取消Dropout,简化网络结构。
ResNet技术特点概要ResNet(Residual Neural Network)由微软研究院的Kaiming He等4名华人提出,通过使用Residual Unit成功训练152层深的神经网络,在ILSVRC 2015比赛中获得了冠军,取得3.57%的top-5错误率,同时参数量却比VGGNet低,效果非常突出。
ResNet的结构可以极快地加速超深神经网络的训练,模型的准确率也有非常大的提升。
ResNet最初的灵感出自这个问题:在不断加神经网络的深度时,会出现一个Degradation的问题,即准确率会先上升然后达到饱和,再持续增加深度则会导致准确率下降。
这并不是过拟合的问题,因为不光在测试集上误差增大,训练集本身误差也会增大。假设有一个比较浅的网络达到了饱和的准确率,那么后面再加上几个的全等映射层,起码误差不会增加,即更深的网络不应该带来训练集上误差上升。
而这里提到的使用全等映射直接将前一层输出传到后面的思想,就是ResNet的灵感来源。假定某段神经网络的输入是x,期望输出是H(x),如果我们直接把输入x传到输出作为初始结果,那么此时我们需要学习的目标就是F(x)=H(x)-x。
这就是一个ResNet的残差学习单元(Residual Unit),ResNet相当于将学习目标改变了,不再是学习一个完整的输出H(x),只是输出和输入的差别H(x)-x,即残差。
上图所示为VGGNet-19,以及一个34层深的普通卷积网络,和34层深的ResNet网络的对比图。可以看到普通直连的卷积神经网络和ResNet的最大区别在于,ResNet有很多旁路的支线将输入直接连到后面的层,使得后面的层可以直接学习残差,这种结构也被称为shortcut或skip connections。传统的卷积层或全连接层在信息传递时,或多或少会存在信息丢失、损耗等问题。ResNet在某种程度上解决了这个问题,通过直接将输入信息绕道传到输出,保护信息的完整性,整个网络则只需要学习输入、输出差别的那一部分,简化学习目标和难度。
上图所示为ResNet在不同层数时的网络配置,其中基础结构很类似,都是前面提到的两层和三层的残差学习单元的堆叠。
在使用了ResNet的结构后,可以发现层数不断加深导致的训练集上误差增大的现象被消除了,ResNet网络的训练误差会随着层数增大而逐渐减小,并且在测试集上的表现也会变好。
Q1:tensorflow的学习路线?
黄文坚:如果想快速入门,可以结合MNIST数据集,尝试MLP、CNN进行图像分类,而后尝试在MNSIT上实现AutoEncoder。此后,可以学习TensorBoard,这是一个非常方便的可视化工具。之后掌握进阶的CNN、RNN,强化学习训练方式。然后如果有兴趣,可以掌握单机多GPU并行计算,多机多GPU分布式训练。目前TensorFlow中还推出了很多组件,比如TF.Learn,Slim,XLA、Fold等,可以针对需求探索。
Q2:目前主流的深度学习工具主要包括TensorFlow,Caffe和Mxnet。相比于其他两个库,您认为TensorFlow的主要优势是哪些?未来TensorFlow的发展趋势着眼于哪些方面,谢谢老师~
黄文坚:Caffe是比较经典的老框架,缺陷在于使用配置文件定义网络结构,调试网络不是很方便,并且基于层的构筑方式,一层一层的堆叠网络,对于一些更灵活的图的结构,表示不方便,并且分布式也不完善。
MXnet是国人推出的框架,主要作者是陈天奇和李沐。MXNet非常灵活,支持多种编程范式,并且分布式性能很好,支持的前端语言绑定很多。缺点是,开发团队小,框架产品代码质量稳定性不如TensorFlow。并且非常缺完善的文档和资料。
TensorFlow是Google大力研发的框架,大约有100-200人的全职的Engineer在协作开发,拥有产品级的代码质量,完善的稳定,高可靠性,适合生产环境使用。同时其计算图定义模式,也非常灵活,可以进行各种灵活的调试。并且目前大部分新推出的Paper和研究,都使用TensorFlow进行实现,可用的模型代码非常多。
在TensorFlow Models库中,也有大量可靠的开源模型实现,比如SyntaxNet,TextSum等。并且TensorFlow在Github上,获得的star数名列机器学习库第一,基本是第2-第10名之和。
Q3:tensorflow在文本领域表现如何?
黄文坚:做文本分析和处理,主要使用RNN,少数情况使用CNN。这两种网络TensorFlow都支持的非常好和完善。并且新推出的TensorFLow Fold支持动态的批输入,可以对动态的RNN结构产生巨大的提速。
Q4:如何选择网络的层数和神经元个数?
黄文坚:深度学习的层数和神经元个数条数一直是一个经验占比非常重的问题。在TensorFlow中,可以使用TensorBoard观察train loss和test loss,如果train loss下降慢,并且test loss没有上升,可以加大模型拟合能力,即加深网络和增大神经元个数。如果train loss难以下降,并且test loss开始反弹,则应控制模型的容量,即模型的拟合能力,保持层数和神经元个数不过大,同时使用各种减轻过拟合的方法,比如dropout、batch normalization等。
Q5:如何将tensorflow应用在实际项目中,涉及的数据转换及数据结构应该是怎样定的?
黄文坚:TensorFlow的格式可以使用numpy的数组,输入数据通过placeholder转为tensor,即多维数组格式,这是TensorFlow的核心数据格式。同时对有空间关联性和时间管理性的数据,应连接CNN、RNN进行处理,其他类型数据,应使用MLP。
Q6:RNN和CNN分别适用哪些场景?
黄文坚:CNN适合空间和时间有关联性的场景,比如图片分类,文本分类,时间序列分类等。
RNN主要适合有时间关联性的场景,并且对时间先后顺序敏感,适合文本分类,语言模型等。
Q7:我是java程序员,5年工作经验,如何更好学习TensorFlow?
黄文坚:TensorFlow最主流的接口是Python,不过目前也推出了Java接口。如果感兴趣,可以直接先从Java接口入手,不过非脚本语言,调试可能不方便,后期可以再学习Python接口。
Q8:黄老师您好。请问如何看待Keras和Tensorflow的关系?Keras作为更高层的库,应该和TF一起学习掌握还是更推荐底层的TF作为深度学习框架的入门呢?
黄文坚:keras已经被合并到TensorFlow中了,目前可以属于TF的一个组件。推荐先学习TensorFlow,掌握一些底层机制,后面当需要快速构建大型神经网络实验时,可以学习keras。并且学习过tensorflow后,keras将非常简单。