用 PaddlePaddle 和 Tensorflow 实现 GoogLeNet InceptionV2/V3/V4

摘要

GoogLeNet Inception V2 在《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》出现,最大亮点是提出了 Batch Normalization 方法,它起到以下作用:

 上一篇文章我们引出了 GoogLeNet InceptionV1 的网络结构,这篇文章中我们会详细讲到 Inception V2/V3/V4 的发展历程以及它们的网络结构和亮点。

GoogLeNet Inception V2

GoogLeNet Inception V2 在《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》出现,最大亮点是提出了 Batch Normalization 方法,它起到以下作用:

  • 使用较大的学习率而不用特别关心诸如梯度爆炸或消失等优化问题;

  • 降低了模型效果对初始权重的依赖;

  • 可以加速收敛,一定程度上可以不使用 Dropout 这种降低收敛速度的方法,但却起到了正则化作用提高了模型泛化性;

  • 即使不使用 ReLU 也能缓解激活函数饱和问题;

  • 能够学习到从当前层到下一层的分布缩放 ( scaling (方差),shift (期望)) 系数。

  在机器学习中,我们通常会做一种假设:训练样本独立同分布 (iid) 且训练样本与测试样本分布一致,如果真实数据符合这个假设则模型效果可能会不错,反之亦然,这个在学术上叫 Covariate Shift,所以从样本(外部)的角度说,对于神经网络也是一样的道理。从结构(内部)的角度说,由于神经网络由多层组成,样本在层与层之间边提特征边往前传播,如果每层的输入分布不一致,那么势必造成要么模型效果不好,要么学习速度较慢,学术上这个叫 InternalCovariate Shift。 

假设:yy 为样本标注,X={x1,x2,x3,......}X={x1,x2,x3,......} 为样本 xx 通过神经网络若干层后每层的输入;

理论上:p(x,y)p(x,y) 的联合概率分布应该与集合 XX 中任意一层输入的联合概率分布一致,如:p(x,y)=p(x1,y)p(x,y)=p(x1,y);

但是:p(x,y)=p(y|x)⋅p(x)p(x,y)=p(y|x)·p(x), 其中条件概率 p(y|x)p(y|x) 是一致的,即 p(y|x)=p(y|x1)=p(y|x1)=......p(y|x)=p(y|x1)=p(y|x1)=......,但由于神经网络每一层对输入分布的改变,导致边缘概率是不一致的,即 p(x)≠p(x1)≠p(x2)......p(x)≠p(x1)≠p(x2)......,甚至随着网络深度的加深,前面层微小的变化会导致后面层巨大的变化。

  BN 整个算法过程如下: 

  • 以 batch 的方式做训练,对 m 个样本求期望和方差后对训练数据做白化,通过白化操作可以去除特征相关性并把数据缩放在一个球体上,这么做的好处既可以加快优化算法的优化速度也可能提高优化精度,一个直观的解释:

  

   左边是未做白化的原始可行域,右边是做了白化的可行域;

  • 当原始输入对模型学习更有利时能够恢复原始输入(和残差网络有点神似):

  

  这里的参数γγ和σσ是需要学习的。

  卷积神经网络中的 BN

  卷积网络中采用权重共享策略,每个 feature map 只有一对γγ和σσ需要学习。

GoogLeNet Inception V3

GoogLeNet Inception V3 在《Rethinking the Inception Architecture for Computer Vision》中提出(注意,在这篇论文中作者把该网络结构叫做 v2 版,我们以最终的 v4 版论文的划分为标准),该论文的亮点在于:

  • 提出通用的网络结构设计准则

  • 引入卷积分解提高效率

  • 引入高效的 feature map 降维

网络结构设计的准则

前面也说过,深度学习网络的探索更多是个实验科学,在实验中人们总结出一些结构设计准则,但说实话我觉得不一定都有实操性:

  • 避免特征表示上的瓶颈,尤其在神经网络的前若干层 

神经网络包含一个自动提取特征的过程,例如多层卷积,直观并符合常识的理解:如果在网络初期特征提取的太粗,细节已经丢了,后续即使结构再精细也没法做有效表示了;举个极端的例子:在宇宙中辨别一个星球,正常来说是通过由近及远,从房屋、树木到海洋、大陆板块再到整个星球之后进入整个宇宙,如果我们一开始就直接拉远到宇宙,你会发现所有星球都是球体,没法区分哪个是地球哪个是水星。所以 feature map 的大小应该是随着层数的加深逐步变小,但为了保证特征能得到有效表示和组合其通道数量会逐渐增加。   

下图违反了这个原则,刚开就始直接从 35×35×320 被抽样降维到了 17×17×320,特征细节被大量丢失,即使后面有 Inception 去做各种特征提取和组合也没用。

  • 对于神经网络的某一层,通过更多的激活输出分支可以产生互相解耦的特征表示,从而产生高阶稀疏特征,从而加速收敛,注意下图的 1×3 和 3×1 激活输出:

  • 合理使用维度缩减不会破坏网络特征表示能力反而能加快收敛速度,典型的例如通过两个 3×3 代替一个 5×5 的降维策略,不考虑 padding,用两个 3×3 代替一个 5×5 能节省 1-(3×3+3×3)/(5×5)=28% 的计算消耗。

  • 以及一个 n×n 卷积核通过顺序相连的两个 1×n 和 n×1 做降维(有点像矩阵分解),如果 n=3,计算性能可以提升 1-(3+3)/9=33%,但如果考虑高性能计算性能,这种分解可能会造成 L1 cache miss 率上升。

  • 通过合理平衡网络的宽度和深度优化网络计算消耗(这句话尤其不具有实操性)。

  • 抽样降维,传统抽样方法为 pooling+卷积操作,为了防止出现特征表示的瓶颈,往往需要更多的卷积核,例如输入为 n 个 d×d 的 feature map,共有 k 个卷积核,pooling 时 stride=2,为不出现特征表示瓶颈,往往 k 的取值为 2n,通过引入 inception module 结构,即降低计算复杂度,又不会出现特征表示瓶颈,实现上有如下两种方式:

  平滑样本标注

对于多分类的样本标注一般是 one-hot 的,例如 [0,0,0,1],使用类似交叉熵的损失函数会使得模型学习中对 ground truth 标签分配过于置信的概率,并且由于 ground truth 标签的 logit 值与其他标签差距过大导致,出现过拟合,导致降低泛化性。一种解决方法是加正则项,即对样本标签给个概率分布做调节,使得样本标注变成「soft」的,例如 [0.1,0.2,0.1,0.6],这种方式在实验中降低了 top-1 和 top-5 的错误率 0.2%。

  网络结构

GoogLeNet Inception V4

GoogLeNet Inception V4/和 ResNet V1/V2 这三种结构在《Inception-v4, Inception-ResNet and the Impact of Residual Connections on Learning》一文中提出,论文的亮点是:提出了效果更好的 GoogLeNet Inception v4 网络结构;与残差网络融合,提出效果不逊于 v4 但训练速度更快的结构。

GoogLeNet Inception V4 网络结构

GoogLeNet Inception ResNet 网络结构

 代码实践

  Tensorflow 的代码在 slim 模块下有完整的实现,paddlepaddle 的可以参考上篇文章中写的 inception v1 的代码来写。

 总结 

  这篇文章比较偏理论,主要讲了 GoogLeNet 的 inception 模块的发展,包括在 v2 中提出的 batch normalization,v3 中提出的卷积分级与更通用的网络结构准则,v4 中的与残差网络结合等,在实际应用过程中可以可以对同一份数据用不同的网络结构跑一跑,看看结果如何,实际体验一下不同网络结构的 loss 下降速率,对准确率的提升等。  

 作者:Charlotte77 


最新文章

极客公园

用极客视角,追踪你最不可错过的科技圈。

极客之选

新鲜、有趣的硬件产品,第一时间为你呈现。

顶楼

关注前沿科技,发表最具科技的商业洞见。