卷积神经网络中十大拍案叫绝的操作(转)

转自https://blog.csdn.net/fu6543210/article/details/90340192

CNN从2012年的AlexNet发展至今,科学家们发明出各种各样的CNN模型,一个比一个深,一个比一个准确,一个比一个轻量。我下面会对近几年一些具有变革性的工作进行简单盘点,从这些充满革新性的工作中探讨日后的CNN变革方向。

注:水平所限,下面的见解或许有偏差,望大牛指正。另外只介绍其中具有代表性的模型,一些著名的模型由于原理相同将不作介绍,若有遗漏也欢迎指出。

一、卷积只能在同一组进行吗?-- Group convolution

Group convolution 分组卷积,最早在AlexNet中出现,由于当时的硬件资源有限,训练AlexNet时卷积操作不能全部放在同一个GPU处理,因此作者把feature maps分给多个GPU分别进行处理,最后把多个GPU的结果进行融合。

640?wx_fmt=jpeg

alexnet

分组卷积的思想影响比较深远,当前一些轻量级的SOTA(State Of The Art)网络,都用到了分组卷积的操作,以节省计算量。但题主有个疑问是,如果分组卷积是分在不同GPU上的话,每个GPU的计算量就降低到 1/groups,但如果依然在同一个GPU上计算,最终整体的计算量是否不变?找了pytorch上有关组卷积操作的介绍,望读者解答我的疑问。

640?wx_fmt=jpeg

pytroch github

EDIT:

关于这个问题,知乎用户朋友 @蔡冠羽 提出了他的见解:

我感觉group conv本身应该就大大减少了参数,比如当input channel为256,output channel也为256,kernel size为3*3,不做group conv参数为256*3*3*256,若group为8,每个group的input channel和output channel均为32,参数为8*32*3*3*32,是原来的八分之一。这是我的理解。

我的理解是分组卷积最后每一组输出的feature maps应该是以concatenate的方式组合,而不是element-wise add,所以每组输出的channel是 input channels / #groups,这样参数量就大大减少了。

二、卷积核一定越大越好?-- 3×3卷积核

AlexNet中用到了一些非常大的卷积核,比如11×11、5×5卷积核,之前人们的观念是,卷积核越大,receptive field(感受野)越大,看到的图片信息越多,因此获得的特征越好。虽说如此,但是大的卷积核会导致计算量的暴增,不利于模型深度的增加,计算性能也会降低。于是在VGG(最早使用)、Inception网络中,利用2个3×3卷积核的组合比1个5×5卷积核的效果更佳,同时参数量(3×3×2+1 VS 5×5×1+1)被降低,因此后来3×3卷积核被广泛应用在各种模型中。

640?wx_fmt=jpeg

三、每层卷积只能用一种尺寸的卷积核?-- Inception结构

传统的层叠式网络,基本上都是一个个卷积层的堆叠,每层只用一个尺寸的卷积核,例如VGG结构中使用了大量的3×3卷积层。事实上,同一层feature map可以分别使用多个不同尺寸的卷积核,以获得不同尺度的特征,再把这些特征结合起来,得到的特征往往比使用单一卷积核的要好,谷歌的GoogleNet,或者说Inception系列的网络,就使用了多个卷积核的结构:

0?wx_fmt=jpeg

最初版本的Inception结构

如上图所示,一个输入的feature map分别同时经过1×1、3×3、5×5的卷积核的处理,得出的特征再组合起来,获得更佳的特征。但这个结构会存在一个严重的问题:参数量比单个卷积核要多很多,如此庞大的计算量会使得模型效率低下。这就引出了一个新的结构:

四、怎样才能减少卷积层参数量?-- Bottleneck

发明GoogleNet的团队发现,如果仅仅引入多个尺寸的卷积核,会带来大量的额外的参数,受到Network In Network中1×1卷积核的启发,为了解决这个问题,他们往Inception结构中加入了一些1×1的卷积核,如图所示:

640?wx_fmt=jpeg

加入1×1卷积核的Inception结构

640?wx_fmt=jpeg

根据上图,我们来做个对比计算,假设输入feature map的维度为256维,要求输出维度也是256维。有以下两种操作:

  • 256维的输入直接经过一个3×3×256的卷积层,输出一个256维的feature map,那么参数量为:256×3×3×256 = 589,824

  • 256维的输入先经过一个1×1×64的卷积层,再经过一个3×3×64的卷积层,最后经过一个1×1×256的卷积层,输出256维,参数量为:256×1×1×64 + 64×3×3×64 + 64×1×1×256 = 69,632。足足把第一种操作的参数量降低到九分之一!

1×1卷积核也被认为是影响深远的操作,往后大型的网络为了降低参数量都会应用上1×1卷积核。

五、越深的网络就越难训练吗?-- Resnet残差网络

0?wx_fmt=jpeg

ResNet skip connection

传统的卷积层层叠网络会遇到一个问题,当层数加深时,网络的表现越来越差,很大程度上的原因是因为当层数加深时,梯度消散得越来越严重,以至于反向传播很难训练到浅层的网络。为了解决这个问题,何凯明大神想出了一个“残差网络”,使得梯度更容易地流动到浅层的网络当中去,而且这种“skip connection”能带来更多的好处,这里可以参考一个PPT:极深网络(ResNet/DenseNet): Skip Connection为何有效及其它(http://blog.csdn.net/malefactor/article/details/67637785) ,以及我的一篇文章:为什么ResNet和DenseNet可以这么深?一文详解残差块为何能解决梯度弥散问题(https://zhuanlan.zhihu.com/p/28124810?group_id=883267168542789632),大家可以结合下面的评论进行思考。

六、卷积操作时必须同时考虑通道和区域吗?-- DepthWise操作

640?wx_fmt=jpeg

标准的卷积过程可以看上图,一个2×2的卷积核在卷积时,对应图像区域中的所有通道均被同时考虑,问题在于,为什么一定要同时考虑图像区域和通道?我们为什么不能把通道和空间区域分开考虑?

640?wx_fmt=jpeg

Xception网络就是基于以上的问题发明而来。我们首先对每一个通道进行各自的卷积操作,有多少个通道就有多少个过滤器。得到新的通道feature maps之后,这时再对这批新的通道feature maps进行标准的1×1跨通道卷积操作。这种操作被称为 “DepthWise convolution” ,缩写“DW”。

这种操作是相当有效的,在imagenet 1000类分类任务中已经超过了InceptionV3的表现,而且也同时减少了大量的参数,我们来算一算,假设输入通道数为3,要求输出通道数为256,两种做法:

  • 直接接一个3×3×256的卷积核,参数量为:3×3×3×256 = 6,912

  • DW操作,分两步完成,参数量为:3×3×3 + 3×1×1×256 = 795,又把参数量降低到九分之一!

因此,一个depthwise操作比标准的卷积操作降低不少的参数量,同时论文中指出这个模型得到了更好的分类效果。

本文在发出12小时后,一位知乎用户私信了我,向我介绍了Depthwise和Pointwise的历史工作,而Xception和Mobilenet也引用了他们16年的工作,就是Min Wang et al 的Factorized Convolutional Neural Networks(https://arxiv.org/pdf/1608.04337v1.pdf),这篇论文的Depthwise中,每一通道输出的feature map(称为“基层”)可以不止一个,而Xception中的Depthwise separable Convolution, 正是这篇工作中“单一基层”的情况。推荐有兴趣的读者关注下他们的工作,这里有篇介绍博文:【深度学习】卷积层提速Factorized Convolutional Neural Networks(http://blog.csdn.net/shenxiaolu1984/article/details/52266391)而最早关于separable convolution的介绍,Xception作者提到,应该追溯到Lau- rent Sifre 2014年的工作 Rigid-Motion Scattering For Image Classification 6.2章节(http://www.di.ens.fr/data/publications/papers/phd_sifre.pdf)。

七、分组卷积能否对通道进行随机分组?-- ShuffleNet

在AlexNet的Group Convolution当中,特征的通道被平均分到不同组里面,最后再通过两个全连接层来融合特征,这样一来,就只能在最后时刻才融合不同组之间的特征,对模型的泛化性是相当不利的。为了解决这个问题,ShuffleNet在每一次层叠这种Group conv层前,都进行一次channel shuffle,shuffle过的通道被分配到不同组当中。进行完一次group conv之后,再一次channel shuffle,然后分到下一层组卷积当中,以此循环。

640?wx_fmt=jpeg

来自ShuffleNet论文

经过channel shuffle之后,Group conv输出的特征能考虑到更多通道,输出的特征自然代表性就更高。另外,AlexNet的分组卷积,实际上是标准卷积操作,而在ShuffleNet里面的分组卷积操作是depthwise卷积,因此结合了通道洗牌和分组depthwise卷积的ShuffleNet,能得到超少量的参数以及超越mobilenet、媲美AlexNet的准确率!

另外值得一提的是,微软亚洲研究院MSRA最近也有类似的工作,他们提出了一个IGC单元(Interleaved Group Convolution),即通用卷积神经网络交错组卷积,形式上类似进行了两次组卷积,Xception 模块可以看作交错组卷积的一个特例,特别推荐看看这篇文章:王井东详解ICCV 2017入选论文:通用卷积神经网络交错组卷积。

要注意的是,Group conv是一种channel分组的方式,Depthwise +Pointwise是卷积的方式,只是ShuffleNet里面把两者应用起来了。因此Group conv和Depthwise +Pointwise并不能划等号。

八、通道间的特征都是平等的吗? -- SEnet

无论是在Inception、DenseNet或者ShuffleNet里面,我们对所有通道产生的特征都是不分权重直接结合的,那为什么要认为所有通道的特征对模型的作用就是相等的呢? 这是一个好问题,于是,ImageNet2017 冠军SEnet就出来了。

640?wx_fmt=jpeg

SEnet 结构

一组特征在上一层被输出,这时候分两条路线,第一条直接通过,第二条首先进行Squeeze操作(Global Average Pooling),把每个通道2维的特征压缩成一个1维,从而得到一个特征通道向量(每个数字代表对应通道的特征)。然后进行Excitation操作,把这一列特征通道向量输入两个全连接层和sigmoid,建模出特征通道间的相关性,得到的输出其实就是每个通道对应的权重,把这些权重通过Scale乘法通道加权到原来的特征上(第一条路),这样就完成了特征通道的权重分配。作者详细解释可以看这篇文章:专栏 | Momenta详解ImageNet 2017夺冠架构SENet。

九、能否让固定大小的卷积核看到更大范围的区域?-- Dilated convolution

标准的3×3卷积核只能看到对应区域3×3的大小,但是为了能让卷积核看到更大的范围,dilated conv使其成为了可能。dilated conv原论文中的结构如图所示:

640?wx_fmt=jpeg

上图b可以理解为卷积核大小依然是3×3,但是每个卷积点之间有1个空洞,也就是在绿色7×7区域里面,只有9个红色点位置作了卷积处理,其余点权重为0。这样即使卷积核大小不变,但它看到的区域变得更大了。详细解释可以看知乎回答:如何理解空洞卷积(dilated convolution)?

十、卷积核形状一定是矩形吗?-- Deformable convolution 可变形卷积核

640?wx_fmt=jpeg

图来自微软亚洲研究院公众号

传统的卷积核一般都是长方形或正方形,但MSRA提出了一个相当反直觉的见解,认为卷积核的形状可以是变化的,变形的卷积核能让它只看感兴趣的图像区域 ,这样识别出来的特征更佳。

640?wx_fmt=jpeg

图来自微软亚洲研究院公众号要做到这个操作,可以直接在原来的过滤器前面再加一层过滤器,这层过滤器学习的是下一层卷积核的位置偏移量(offset),这样只是增加了一层过滤器,或者直接把原网络中的某一层过滤器当成学习offset的过滤器,这样实际增加的计算量是相当少的,但能实现可变形卷积核,识别特征的效果更好。详细MSRA的解读可以看这个链接:可变形卷积网络:计算机新“视”界(https://weibo.com/ttarticle/p/show?id=2309404116774126794221)。

启发与思考

现在越来越多的CNN模型从巨型网络到轻量化网络一步步演变,模型准确率也越来越高。现在工业界追求的重点已经不是准确率的提升(因为都已经很高了),都聚焦于速度与准确率的trade off,都希望模型又快又准。因此从原来AlexNet、VGGnet,到体积小一点的Inception、Resnet系列,到目前能移植到移动端的mobilenet、ShuffleNet(体积能降低到0.5mb!),我们可以看到这样一些趋势:

卷积核方面:

  • 大卷积核用多个小卷积核代替;

  • 单一尺寸卷积核用多尺寸卷积核代替;

  • 固定形状卷积核趋于使用可变形卷积核;

  • 使用1×1卷积核(bottleneck结构)。

卷积层通道方面:

  • 标准卷积用depthwise卷积代替;

  • 使用分组卷积;

  • 分组卷积前使用channel shuffle;

  • 通道加权计算。

卷积层连接方面:

  • 使用skip connection,让模型更深;

  • densely connection,使每一层都融合上其它层的特征输出(DenseNet)

启发

类比到通道加权操作,卷积层跨层连接能否也进行加权处理?bottleneck + Group conv + channel shuffle + depthwise的结合会不会成为以后降低参数量的标准配置?

原文链接:https://zhuanlan.zhihu.com/p/28749411?from=singlemessage

 如果还有不明白,可以参考链接,也是对同一个内容的详写,都是围绕上面的知乎原文


空洞卷积(dilated convolution)理解

Dilated/Atrous Convolution(中文叫做空洞卷积或者膨胀卷积) 或者是 Convolution with holes 从字面上就很好理解,是在标准的 convolution map 里注入空洞,以此来增加 reception field。相比原来的正常convolution,dilated convolution 多了一个 hyper-parameter 称之为 dilation rate 指的是kernel的间隔数量(e.g. 正常的 convolution 是 dilatation rate 1)。

Standard Convolution with a 3 x 3 kernel (and padding)

Dilated Convolution with a 3 x 3 kernel and dilation rate 2

Deep CNN 对于其他任务还有一些致命性的缺陷。较为著名的是 up-sampling 和 pooling layer 的设计。
主要问题有:

  • Up-sampling / pooling layer (e.g. bilinear interpolation) is deterministic. (参数不可学习)
  • 内部数据结构丢失;空间层级化信息丢失。
  • 小物体信息无法重建 (假设有四个pooling layer 则 任何小于 2^4 = 16 pixel 的物体信息将理论上无法重建。)
    在这样问题的存在下,语义分割问题一直处在瓶颈期无法再明显提高精度, 而 dilated convolution 的设计就良好的避免了这些问题。

在图像分割领域,图像输入到CNN(典型的网络比如FCN[3])中,FCN先像传统的CNN那样对图像做卷积再pooling,降低图像尺寸的同时增大感受野,但是由于图像分割预测是pixel-wise的输出,所以要将pooling后较小的图像尺寸upsampling到原始的图像尺寸进行预测(upsampling一般采用deconv反卷积操作,deconv可参见知乎答案如何理解深度学习中的deconvolution networks?),之前的pooling操作使得每个pixel预测都能看到较大感受野信息。因此图像分割FCN中有两个关键,一个是pooling减小图像尺寸增大感受野,另一个是upsampling扩大图像尺寸。在先减小再增大尺寸的过程中,肯定有一些信息损失掉了,那么能不能设计一种新的操作,不通过pooling也能有较大的感受野看到更多的信息呢?答案就是dilated conv。

下面看一下dilated conv原始论文[4]中的示意图:

dilated conv

(a)图对应3x3的1-dilated conv,和普通的卷积操作一样,(b)图对应3x3的2-dilated conv,实际的卷积kernel size还是3x3,但是空洞为1,也就是对于一个7x7的图像patch,只有9个红色的点和3x3的kernel发生卷积操作,其余的点略过。也可以理解为kernel的size为7x7,但是只有图中的9个点的权重不为0,其余都为0。 可以看到虽然kernel size只有3x3,但是这个卷积的感受野已经增大到了7x7(如果考虑到这个2-dilated conv的前一层是一个1-dilated conv的话,那么每个红点就是1-dilated的卷积输出,所以感受野为3x3,所以1-dilated和2-dilated合起来就能达到7x7的conv),(c)图是4-dilated conv操作,同理跟在两个1-dilated和2-dilated conv的后面,能达到15x15的感受野。对比传统的conv操作,3层3x3的卷积加起来,stride为1的话,只能达到(kernel-1)*layer+1=7的感受野,也就是和层数layer成线性关系,而dilated conv的感受野是指数级的增长。

dilated的好处是不做pooling损失信息的情况下,加大了感受野,让每个卷积输出都包含较大范围的信息。

空洞卷积存在的问题

潜在问题 1:The Gridding Effect

假设我们仅仅多次叠加 dilation rate 2 的 3 x 3 kernel 的话,则会出现这个问题:

image

我们发现我们的 kernel 并不连续,也就是并不是所有的 pixel 都用来计算了,因此这里将信息看做 checker-board 的方式会损失信息的连续性。这对 pixel-level dense prediction 的任务来说是致命的。

潜在问题 2:Long-ranged information might be not relevant.

我们从 dilated convolution 的设计背景来看就能推测出这样的设计是用来获取 long-ranged information。然而光采用大 dilation rate 的信息或许只对一些大物体分割有效果,而对小物体来说可能则有弊无利了。如何同时处理不同大小的物体的关系,则是设计好 dilated convolution 网络的关键。

通向标准化设计:Hybrid Dilated Convolution (HDC)

对于上个 section 里提到的几个问题,图森组的文章对其提出了较好的解决的方法。他们设计了一个称之为 HDC 的设计结构。

  • 第一个特性是,叠加卷积的 dilation rate 不能有大于1的公约数。比如 [2, 4, 6] 则不是一个好的三层卷积,依然会出现 gridding effect。

  • 第二个特性是,我们将 dilation rate 设计成锯齿状结构,例如 [1, 2, 5, 1, 2, 5] 循环结构。

  • 第三个特性是,我们需要满足一下这个式子:

其中 r_i是 i 层的 dilation rate 而 M_i是指在 i 层的最大dilation rate,那么假设总共有n层的话,默认 M_n=r_n 。假设我们应用于 kernel 为 k x k 的话,我们的目标则是M_2 leq k,这样我们至少可以用 dilation rate 1 即 standard convolution 的方式来覆盖掉所有洞。

一个简单的例子: dilation rate [1, 2, 5] with 3 x 3 kernel (可行的方案)

image

而这样的锯齿状本身的性质就比较好的来同时满足小物体大物体的分割要求(小 dilation rate 来关心近距离信息,大 dilation rate 来关心远距离信息)。

这样我们的卷积依然是连续的也就依然能满足VGG组观察的结论,大卷积是由小卷积的 regularisation 的 叠加。

以下的对比实验可以明显看出,一个良好设计的 dilated convolution 网络能够有效避免 gridding effect.

image

多尺度分割的另类解:Atrous Spatial Pyramid Pooling (ASPP)

在处理多尺度物体分割时,我们通常会有以下几种方式来操作:

image

然仅仅(在一个卷积分支网络下)使用 dilated convolution 去抓取多尺度物体是一个不正统的方法。比方说,我们用一个 HDC 的方法来获取一个大(近)车辆的信息,然而对于一个小(远)车辆的信息都不再受用。假设我们再去用小 dilated convolution 的方法重新获取小车辆的信息,则这么做非常的冗余。

基于港中文和商汤组的 PSPNet 里的 Pooling module (其网络同样获得当年的SOTA结果),ASPP 则在网络 decoder 上对于不同尺度上用不同大小的 dilation rate 来抓去多尺度信息,每个尺度则为一个独立的分支,在网络最后把他合并起来再接一个卷积层输出预测 label。这样的设计则有效避免了在 encoder 上冗余的信息的获取,直接关注与物体之间之内的相关性。

总结

Dilated Convolution 个人认为想法简单,直接且优雅,并取得了相当不错的效果提升。他起源于语义分割,大部分文章也用于语义分割,具体能否对其他应用有价值姑且还不知道,但确实是一个不错的探究方向。有另外的答主提到WaveNet, ByteNet 也用到了 dilated convolution 确实是一个很有趣的发现,因为本身 sequence-to-sequence learning 也是一个需要关注多尺度关系的问题。则在 sequence-to-sequence learning 如何实现,如何设计,跟分割或其他应用的关联是我们可以重新需要考虑的问题。

推荐阅读

图森组和 Google Brain 都对于 dilated convolution 有着更细节的讨论,推荐阅读:

 参考:https://www.jianshu.com/p/f743bd9041b3

原文地址:https://www.cnblogs.com/smileglaze/p/13954855.html