膨胀卷积(空洞卷积)

373 阅读9分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路

膨胀卷积

原论文链接: 2016ICLR《Multi-Scale Context Aggregation by Dilated Convolutions》.

提出背景

膨胀卷积是为解决语义分割任务而提出的。因为深度学习的蓬勃发展,其也被迁移应用于语义分割领域。当时的SOTA方法多是基于卷积神经网络,但卷积神经网络当初是为图像分类任务而设计的。语义分割作为一种稠密预测(Dense Prediction)任务——==语义分割是像素级的分类任务==,与图像分类具有结构上的不同。这里的不同指的应该是,图像分类的网络只需输出相应的物体类别的概率,而语义分割网络则需要输出与原图像大小相同的图像。 图像分类任务为了==获取足够的感受野==(感受野的概念会在下文进行讲解),都会通过池化层或者大步长的卷积对图像和特征图进行下采样的操作,这样就减小了图像或者特征图的分辨率,这与语义分割的输出要求是相违背的。当时解决此问题主要有两种办法:

  1. 对图像或特征图进行上采样,恢复因为获取感受野进行下采样而丢失的分辨率
  2. 将输入图像缩放到多种尺寸并输入网络,结合多尺度图像得到最终的预测结果

但膨胀卷积的作者对此两种方法提出疑问:网络中的下采样层对于语义分割任务来说真的是必要的吗?多尺度图像的输入是必要的吗?有没有什么办法可以在不改变图像分辨率的前提下获取足够的感受野,使得网络关注多尺度的上下文语义信息? 基于以上疑问,作者受到小波变换领域的膨胀概念,提出了膨胀卷积,并将其做成即插即用的模块,放入卷积神经网络中。如图1所示,经测试,取得了不错的效果。 在这里插入图片描述            图1. 膨胀卷积在语义分割任务上的效果

感受野

感受野,是指在当前尺寸的特征图上的一个像素点在原图像的覆盖范围,即特征图上的这个点是由输入图像中感受野大小区域的计算得到的。举个简单的例子,如图2中所示,是一个三层的卷积神经网络,每一层的卷积核尺寸都是3×3,步长为1。可以很直观的看到,第一层的每个点都是由输入层的三个元素计算得到的,即感受野为3×3;以此类推,第二层的感受野为5×5,第三层的感受野为7×7。==注意:这里旨在利用一维的形式阐释感受野的概念,方便大家理解。如果只针对图中的计算方式,第一层、第二层以及第三次的感受野应为3、5、7。希望不要误导大家。== 在这里s插入图片描述               图2. 三层卷积神经网络的感受野计算

除此之外,感受野有比较科学的计算公式:               RFl+1=RFl+(k1)SlRF_{l+1}=RF_l+(k-1)*S_l 参数含义:

RFl+1:RF_{l+1}:l+1l+1层的感受野 RFl:RF_{l}:ll 层的感受野 k:k:l+1l+1的卷积核尺寸 Sl:S_l:==前 ll 层的步长之积== ==注意,当前层的步长并不影响当前层的感受野。==

感受野是影响深度神经网络性能的重要因素之一。所以在平时深度神经网络的设计中要注意各层特征图的感受野,以确保在当前层能获得适合所解决任务需要的感受野大小,即特征图中包含了足够多原图的语义信息,从而发挥出深度神经网络的最佳性能。 注意:从上边公式中可以看出,想要增大感受野,有两种办法。一是增大卷积核尺寸,二是增大卷积步长(池化层也可以用步长为2的卷积替代,参考Darknet53

膨胀卷积是什么

膨胀卷积,顾名思义,是经过膨胀设计的卷积运算。具体是怎么膨胀呢?我们看图3。 在这里插入图片描述          图3. 普通卷积核和膨胀卷积核的示意图

从图3可以看出,膨胀卷积的卷积核是在普通卷积核的基础上扩大了尺寸,但是真正参与运算的卷积核单元没有变化(图3中只有蓝色方块才是参与运算的单元,无色小方块中的元素用0填充。左半部分的普通卷积核尺寸为3×3,右半部分卷积核尺寸为5×5,但右半部分深蓝色的参与运算的元素依然是9 [ 3×33×3 ] 个),看到这里大家应该知道膨胀卷积是什么样的了。

膨胀卷积的设计原理

从图3中可以看出,膨胀卷积其实是通过==扩大卷积核尺寸==的方式来增大感受野,同时既没有增大计算量,也没有降低特征图的分辨率。等等...,这不正是语义分割所需要的神器吗? 除此之外,膨胀卷积有一个超参数:膨胀因子SS,通过膨胀因子我们可以控制卷积核的膨胀程度,图3中的膨胀因子为2。膨胀因子是如何控制卷积核的膨胀程度的呢?                 Kc=S×(Ko1)+1K_c=S×(K_o-1)+1 参数含义:

Kc:K_c:普通卷积核尺寸 Ko:K_o:普通卷积核通过膨胀设计后的卷积核尺寸

例如,图3中,普通卷积核尺寸3×3,SS为2,那么膨胀之后的卷积核尺寸为5×5。

==膨胀卷积核元素之间的间隔=S1膨胀卷积核元素之间的间隔=S-1==,图3中S=2S=2,行列元素间隔各为1。

接下来,如图4所示,看一下膨胀卷积的感受野的计算方式。作者说他们的架构受到以下事实的启发:膨胀卷积支持==指数级扩展的感受野==,而不会丢失分辨率或覆盖范围。 在这里插入图片描述               图4. 膨胀卷积的感受野示意图                F1,F2,F3F_1,F_2,F_3分别是第1,2,3层特征图。F1,F2,F3F_1,F_2,F_3是级联形式,即F1F_1是由原图得到的,F2F_2是由F1F_1得到的,F3F_3是由F2F_2得到的。每层特征图均采用步长为1的方式计算得到。根据上边计算感受野的公式可知: F1F_1的感受野=1+(3-1)*1=3,3×3 注意:==原图的感受野为1== F2F_2的感受野=3+(5-1)*1=7,7×7
F1F_1的感受野=7+(9-1)*1=15,15×15

作者在论文中给出的计算公式:RFi+1=(2i+21)×(2i+21)RF_{i+1}=(2^{i+2}-1)×(2^{i+2}-1) 其中,

RFi+1RF_{i+1}:第i+1i+1层特征图的感受野

根据以上计算公式,所以作者才说膨胀卷积支持==指数级扩展的感受野==,而不会丢失分辨率或覆盖范围。==这种指数级的感受野增长是作者精心设计膨胀因子的结果。== 原论文中的网络结构设计规则如图5所示。 在这里插入图片描述             图5. 原论文中网络设计及感受野详情

膨胀卷积的优缺点

优点:

  1. 使得输出更为稠密,适应语义分割任务;
  2. 在不降低分辨率的情况下,增大感受野。

缺点:

  1. ==gridding problem==,如果我们叠加多个相同的膨胀卷积,会发现感受野中有很多像素没有利用上(感受野的方阵中只有蓝色和红色方块参与计算,白色方块使用零填充,相当于没有参与运算),出现大量空洞,如图6所示。此时,会丢失数据之间的连续性及完整性,不利于学习。在这里插入图片描述        图6. 多个相同膨胀卷积堆叠带来的gridding problem        
  2. ==长距离的信息有时是不相关的==,膨胀卷积扩大了感受野,因此可以取得长距离信息(在图像中这是有利于大目标分析的),但是有些长距离信息和当前点是完全不相关的,会影响数据的一致性(对于小目标不太友好)。

膨胀卷积的改进

针对以上缺点,图森未来的研究人员对膨胀卷积进行了改进,并提出了Hybrid Dilated Convolution(HDC)。HDC主要有三个特性:

  1. 叠加卷积的膨胀因子不能有大于1的公约数。比如 [2, 4, 6] 则不是一个好的三层卷积,依然会出现 gridding effect。
  2. 膨胀因子可以设计成锯齿状结构,例如 [1, 2, 5, 1, 2, 5] 循环结构。
  3. 膨胀因子需要满足以下公式:     Mi=Max(Mi+12ri,Mi+12(Mi+1ri),ri)M_i=Max(M_{i+1}-2r_i,M_{i+1}-2(M_{i+1}-r_i),r_i) 参数含义:

rir_i:第i层的膨胀因子 MiM_i:这i层的最大的膨胀因子

假设总共有n层的话,默认 Mn=rnM_n=r_n。假设我们应用于 k×kk × k 的卷积核,我们的目标则是M2<=kM_2<=k,这样我们至少可以用膨胀因子为1(即 普通卷积)的方式来覆盖掉所有空洞。

膨胀卷积基于Pytorch的代码实现

Pytorch中膨胀卷积和普通卷积共用一个API,只是通过膨胀因子的参数进行区分,膨胀因子设置为1时就是普通卷积。

torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros', device=None, dtype=None)

参数含义:

  • in_channels (int) – Number of channels in the input image
  • out_channels (int) – Number of channels produced by the convolution
  • kernel_size (int or tuple) – Size of the convolving kernel
  • stride (int or tuple, optional) – Stride of the convolution. Default: 1
  • padding (int, tuple or str, optional) – Padding added to all four sides of the input. Default: 0
  • padding_mode (string, optional) – 'zeros', 'reflect', 'replicate' or 'circular'. Default: 'zeros'
  • dilation (int or tuple, optional) – Spacing between kernel elements. Default: 1
  • groups (int, optional) – Number of blocked connections from input channels to output channels. Default: 1
  • bias (bool, optional) – If True, adds a learnable bias to the output. Default: True

dilation为膨胀因子,默认为1,即普通卷积。

总结

这篇博客从提出背景、设计理念以及改进方向等方面介绍了膨胀卷积,膨胀卷积是一种设计简单、但是在本质上对具体任务有了很大地提升,有一种返璞归真的感觉。有时候简单的方法往往是好的。我们要做的就是怎么让膨胀卷积与其他任务更好的结合,让其优势发挥到极致,如果可能的话,还可以分析改进后的膨胀卷积还有哪些缺点和不足,并予以改进。