膨胀卷积是为解决语义分割任务而提出的。因为深度学习的蓬勃发展,其也被迁移应用于语义分割领域。当时的SOTA方法多是基于卷积神经网络,但卷积神经网络当初是为图像分类任务而设计的。语义分割作为一种稠密预测(Dense Prediction)任务——语义分割是像素级的分类任务,与图像分类具有结构上的不同。这里的不同指的应该是,图像分类的网络只需输出相应的物体类别的概率,而语义分割网络则需要输出与原图像大小相同的图像。
图像分类任务为了获取足够的感受野(感受野的概念会在下文进行讲解),都会通过池化层或者大步长的卷积对图像和特征图进行下采样的操作,这样就减小了图像或者特征图的分辨率,这与语义分割的输出要求是相违背的。当时解决此问题主要有两种办法:
但膨胀卷积的作者对此两种方法提出疑问:网络中的下采样层对于语义分割任务来说真的是必要的吗?多尺度图像的输入是必要的吗?有没有什么办法可以在不改变图像分辨率的前提下获取足够的感受野,使得网络关注多尺度的上下文语义信息?
基于以上疑问,作者受到小波变换领域的膨胀概念,提出了膨胀卷积,并将其做成即插即用的模块,放入卷积神经网络中。如图1所示,经测试,取得了不错的效果。
图1. 膨胀卷积在语义分割任务上的效果
感受野,是指在当前尺寸的特征图上的一个像素点在原图像的覆盖范围,即特征图上的这个点是由输入图像中感受野大小区域的计算得到的。举个简单的例子,如图2中所示,是一个三层的卷积神经网络,每一层的卷积核尺寸都是3×3,步长为1。可以很直观的看到,第一层的每个点都是由输入层的三个元素计算得到的,即感受野为3×3;以此类推,第二层的感受野为5×5,第三层的感受野为7×7。
图2. 三层卷积神经网络的感受野计算
除此之外,感受野有比较科学的计算公式:
R F l + 1 = R F l + ( k − 1 ) ∗ S l RF_{l+1}=RF_l+(k-1)*S_l RFl+1=RFl+(k−1)∗Sl
参数含义:
R F l + 1 : RF_{l+1}: RFl+1:第 l + 1 l+1 l+1层的感受野
R F l : RF_{l}: RFl:第 l l l 层的感受野
k : k: k:第 l + 1 l+1 l+1的卷积核尺寸
S l : S_l: Sl:前 l l l 层的步长之积
注意,当前层的步长并不影响当前层的感受野。
感受野是影响深度神经网络性能的重要因素之一。所以在平时深度神经网络的设计中要注意各层特征图的感受野,以确保在当前层能获得适合所解决任务需要的感受野大小,即特征图中包含了足够多原图的语义信息,从而发挥出深度神经网络的最佳性能。
注意:从上边公式中可以看出,想要增大感受野,有两种办法。一是增大卷积核尺寸,二是增大卷积步长(池化层也可以用步长为2的卷积替代,参考Darknet53)
膨胀卷积,顾名思义,是经过膨胀设计的卷积运算。具体是怎么膨胀呢?我们看图3。
图3. 普通卷积核和膨胀卷积核的示意图
从图3可以看出,膨胀卷积的卷积核是在普通卷积核的基础上扩大了尺寸,但是真正参与运算的卷积核单元没有变化(图3中只有蓝色方块才是参与运算的单元,无色小方块中的元素用0填充。左半部分的普通卷积核尺寸为3×3,右半部分卷积核尺寸为5×5,但右半部分深蓝色的参与运算的元素依然是9 [ 3 × 3 3×3 3×3 ] 个),看到这里大家应该知道膨胀卷积是什么样的了。
从图3中可以看出,膨胀卷积其实是通过扩大卷积核尺寸的方式来增大感受野,同时既没有增大计算量,也没有降低特征图的分辨率。等等…,这不正是语义分割所需要的神器吗?
除此之外,膨胀卷积有一个超参数:膨胀因子 S S S,通过膨胀因子我们可以控制卷积核的膨胀程度,图3中的膨胀因子为2。膨胀因子是如何控制卷积核的膨胀程度的呢?
K c = S × ( K o − 1 ) + 1 K_c=S×(K_o-1)+1 Kc=S×(Ko−1)+1
参数含义:
K c : K_c: Kc:普通卷积核尺寸
K o : K_o: Ko:普通卷积核通过膨胀设计后的卷积核尺寸
例如,图3中,普通卷积核尺寸3×3, S S S为2,那么膨胀之后的卷积核尺寸为5×5。
膨 胀 卷 积 核 元 素 之 间 的 间 隔 = S − 1 膨胀卷积核元素之间的间隔=S-1 膨胀卷积核元素之间的间隔=S−1,图3中 S = 2 S=2 S=2,行列元素间隔各为1。
接下来,如图4所示,看一下膨胀卷积的感受野的计算方式。作者说他们的架构受到以下事实的启发:膨胀卷积支持指数级扩展的感受野,而不会丢失分辨率或覆盖范围。
图4. 膨胀卷积的感受野示意图
F 1 , F 2 , F 3 F_1,F_2,F_3 F1,F2,F3分别是第1,2,3层特征图。 F 1 , F 2 , F 3 F_1,F_2,F_3 F1,F2,F3是级联形式,即 F 1 F_1 F1是由原图得到的, F 2 F_2 F2是由 F 1 F_1 F1得到的, F 3 F_3 F3是由 F 2 F_2 F2得到的。每层特征图均采用步长为1的方式计算得到。根据上边计算感受野的公式可知:
F 1 F_1 F1的感受野=1+(3-1)*1=3,3×3 注意:原图的感受野为1
F 2 F_2 F2的感受野=3+(5-1)*1=7,7×7
F 1 F_1 F1的感受野=7+(9-1)*1=15,15×15
作者在论文中给出的计算公式: R F i + 1 = ( 2 i + 2 − 1 ) × ( 2 i + 2 − 1 ) RF_{i+1}=(2^{i+2}-1)×(2^{i+2}-1) RFi+1=(2i+2−1)×(2i+2−1)
其中,
R F i + 1 RF_{i+1} RFi+1:第 i + 1 i+1 i+1层特征图的感受野
根据以上计算公式,所以作者才说膨胀卷积支持指数级扩展的感受野,而不会丢失分辨率或覆盖范围。这种指数级的感受野增长是作者精心设计膨胀因子的结果。
原论文中的网络结构设计规则如图5所示。
图5. 原论文中网络设计及感受野详情
优点:
缺点:
针对以上缺点,图森未来的研究人员对膨胀卷积进行了改进,并提出了Hybrid Dilated Convolution(HDC)。HDC主要有三个特性:
r i : r_i: ri:第i层的膨胀因子
M i : M_i: Mi:这i层的最大的膨胀因子
假设总共有n层的话,默认 M n = r n M_n=r_n Mn=rn。假设我们应用于 k × k k × k k×k 的卷积核,我们的目标则是 M 2 < = k M_2<=k M2<=k,这样我们至少可以用膨胀因子为1(即 普通卷积)的方式来覆盖掉所有空洞。
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,即普通卷积。
这篇博客从提出背景、设计理念以及改进方向等方面介绍了膨胀卷积,膨胀卷积是一种设计简单、但是在本质上对具体任务有了很大地提升,有一种返璞归真的感觉。有时候简单的方法往往是好的。我们要做的就是怎么让膨胀卷积与其他任务更好的结合,让其优势发挥到极致,如果可能的话,还可以分析改进后的膨胀卷积还有哪些缺点和不足,并予以改进。