1.摘要

​ 空洞卷积被大家所熟知的常见的卷积网络的一种,被广泛应用在深度卷积神经网络中(DCNN),例如图像语义分割任务、目标检测、音频生成、视频建模、机器翻译等等。然而,空洞卷积也会造成网格伪影的现象,这严重阻碍了在DCNN中应用了空洞卷积的表现。在本工作中,作者提出了两种简单但有效的去网格方法,是通过研究分解空洞卷积实现来完成的。该工作不像目前已经存在的方法,那些通过堆叠级联空洞卷积层来探索解决方案。而该工作解决网络伪影是通过平滑空洞卷积本身来实现的。通过分析它们在原本操作和分解视图,作者进一步提出了两种去网格方法,定义出了分离共享操作,这进一步概括了本文提出的方法。我们通过两组数据评估我们的方法,并通过有效的感受野分析可视化平滑效果。实验结果表明,我们的方法在增加可忽略的额外训练参数的同时,显著地、持续地提高了使用过空洞卷积的dcnn的性能。

2.空洞卷积的原理

1.一维的空洞卷积

对于1D的输入f,空洞卷积的过滤器W的尺寸为S,该空洞卷积在位置i处的输出O如下,r为空洞率:
O [ i ] = ∑ s = 1 S f [ i + r ∗ s ] w [ i ] O[i]=\sum_{s=1}^{S}f[i+r*s]w[i] O[i]=s=1Sf[i+rs]w[i]

2.二维的空洞卷积

在这里插入图片描述

二维的空洞卷积核是通过插入在权重之间插入0实现的,如上图所示,不同的空洞率对应着不同的感受野大小,感受野扩大了,也没需要额外的训练参数。

有两种方式可以说明空洞卷积的实现方式:

  1. 第一种的方式是按照空洞率r插入了0的空洞卷积过滤器可以视为将卷积核进行了上采样的标准卷积过滤器。

  2. 第二种是从空洞卷积操作分解的角度进行理解。空洞卷积的空洞率为r,第一步按照因子r对输入的特征图进行间隔子采样。这样输入的特征图就会被重新采样成 r d r^d rd组低分辨率的特征图,其中d是输入特征图的空间维度(若是2D特征图,d=2)。第二步,这些中间特征图组进行标准卷积。但是这个标准卷积为所有特征图组共享,意味着每个低分辨率特征图组都经过一个标准卷积处理,然后得到新的特征图组。第三步,对所有的新特征图组进行重新间隔组合,构成原始分辨率的特征图,作为空洞卷积的最终输出。其图解过程如下图:

在这里插入图片描述

在深度卷积神经网络中使用空洞卷积很有必要,比如在图像分割领域,希望输出的特征图不变小而感受野又足够大,那么这时就需要使用到空洞卷积。

3.平滑空洞卷积的动机

面对使用空洞卷积会造成网格伪影的情况,已有常见的做法是堆叠不同空洞率的空洞卷积进行消除这种影响,而平滑空洞卷积则从空洞卷积的本身出发,通过分解空洞卷积实现的视图,从而提出了 ss(分离共享)操作。

4.平滑空洞卷积实现的两种方式

4.1通过组交互层平滑空洞卷积

​ 这种方式是在空洞卷积的图解的第二步完成后,再对新的特征图组进行重新间隔重组之前,对所有的新的特征图组进行操作,作者主要是想建立不同特征图组之间的关系。提出了一个组交互层,这一层实际上就是通过线性组合实现的,每一个特征图组都可以从其他的特征图组获取到局部信息。其图示过程如下图:

在这里插入图片描述

4.2使用分离共享卷积的平滑空洞卷积

​ 该方法是在空洞卷积分解操作的第一步建立各组之间的联系。对于2维输入特征图上空洞率为r的空洞卷积而言,在间隔子采样期间会将特征图中局部区域中的各个单元被分配到不同的组中吗,因此,对于一个特定组中的单元,其在输入特征图中的邻居单元均在其它独立的 r d − 1 r^d -1 rd1组中,因此导致了局部不一致,如果在间隔子采样之前就能够合并局部信息,那么就可能缓解网格伪影现象。

为了达到这一想法,作者基于分离卷积的思想提出了分离共享卷积。对于C通道的输入和C通道的输出,分离卷积和标准卷积是一样的,不同点在于分离卷积是分离地单独处理每个通道的,而标准卷积连接输出中所有C个通道和输出中的所有C个通道,产生 C 2 C^2 C2个不同的过滤器。对于分离卷积只连接输出中第i个通道和输出中第i个通道,产生C个过滤器。在提出的分离共享卷积(ss),共享意味着基于可分离卷积,这C个过滤器是一样的,并且被所有输入通道和输出通道共享。对于 C 个通道的输入和输出,SS 卷积只使用一个过滤器扫面所有空间位置,并且在所有通道上共享该过滤器。下图提供一个可分离卷积和 SS 卷积的对比样例。

在这里插入图片描述

就平滑空洞卷积而言,作者使用 SS 卷积来组合输入特征图中每个单元的相邻信息。特别地,在间隔子采样之前插入一个卷积核为 ( 2 r − 1 ) d (2r-1)^d (2r1)d 的 SS 卷积,能够在间隔子采样生成的 r d r^d rd组特征图之间添加依赖。

在这里插入图片描述

对于使用3x3的卷积核,孔洞率为r=2来说。通过增加分离共享卷积,这4( r d r^d rd)组子采样特征图组被建立了与彼此的关系。由于输入只有一个通道,此例子中 SS 卷积、分离卷积以及标准卷积是等价的。然而,当输入通道 C>1 时,他们三个将不是等价的了。重要的是,对于具有多个通道的输入,SS 卷积的训练参数个数并不会改变(因为所有通道共享同一个过滤器),而其它两类卷积的训练参数个数会增加(因为过滤器个数与通道个数相关)。这意味着作者提出的解网格方法有 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tkGcStc7-1625725187669)(https://www.zhihu.com/equation?tex=%282r-1%29%5Ed)] 个参数,与通道个数无关,即在实际中最多只有数十个额外的参数。

#第二种方法的实现

#1.第一分离共享操作
class ShareSepConv(nn.Module):
    def __init__(self, kernel_size):
        super(ShareSepConv, self).__init__()
        assert kernel_size % 2 == 1, 'kernel size should be odd'
        self.padding = (kernel_size - 1)//2#设置该大小的padding,能使得进行卷积后,输出的特征图的尺寸大小不变
        weight_tensor = torch.zeros(1, 1, kernel_size, kernel_size)#定义一个1个种类,一个通道,大小为kernel_size的卷积核
        weight_tensor[0, 0, (kernel_size-1)//2, (kernel_size-1)//2] = 1#将卷积核中间那个数值设为1
        self.weight = nn.Parameter(weight_tensor)#将其卷积核变为可学习的参数
        print('self.weight_shape:',self.weight.shape)
        self.kernel_size = kernel_size

    def forward(self, x):
        inc = x.size(1)#获取输入特征图的通道数
        expand_weight = self.weight.expand(inc, 1, self.kernel_size, self.kernel_size).contiguous()#为那个共享的卷积核进行复制,复制到与输入特征图具有一样的通道数,输出也是该通道数
        return F.conv2d(input=x, weight=expand_weight,bias=None, stride=1, padding=self.padding, dilation=1, groups=inc)#对输入的特征图进行指定的卷积核进行卷积操作,group参数可以使得卷积核与输入的特征图的通道数不一致

#2.平滑空洞卷积,带有残差结构
class SmoothDilatedResidualBlock(nn.Module):
    def __init__(self, channel_num, dilation=1, group=1):
        super(SmoothDilatedResidualBlock, self).__init__()
        self.pre_conv1 = ShareSepConv(dilation*2-1)#在空洞卷积前执行SS,分离共享操作。
        self.conv1 = nn.Conv2d(channel_num, channel_num, 3, 1, padding=dilation, dilation=dilation, groups=group, bias=False)#空洞卷积,
        self.norm1 = nn.InstanceNorm2d(channel_num, affine=True)#实例化归一层

        self.pre_conv2 = ShareSepConv(dilation*2-1)
        self.conv2 = nn.Conv2d(channel_num, channel_num, 3, 1, padding=dilation, dilation=dilation, groups=group, bias=False)
        self.norm2 = nn.InstanceNorm2d(channel_num, affine=True)

    def forward(self, x):
        y = F.relu(self.norm1(self.conv1(self.pre_conv1(x))))
        y = self.norm2(self.conv2(self.pre_conv2(y)))
        return F.relu(x+y)

验证:

img_map=torch.rand(4,3,10,10)
SmoothDilated=SmoothDilatedResidualBlock(3,dilation=2)
resutl=SmoothDilated(img_map)
print('img shape:',img_map.shape)
print('result.shape',resutl.shape)

在这里插入图片描述

参考文献

1.Smoothed Dilated Convolutions for Improved Dense Prediction
2.用于提升密集预测性能的平滑空洞卷积

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐