DeepLab全家桶小结

DeepLab全家桶小结_第1张图片

  • 目标分割经过了FCN->U-net->U-net++等等的迭代之后,出现了一个通过改良VGG网络融合机器学习方法CRF得到的全新网络DeepLab。然而,为了让网络能够更加简洁,使用推广起来更加方便,作者又放弃了可解释性强的CRF方法,把整个网络变成了一个end2end的全深度学习网络。目标分割网络的迭代过程也是令人心潮澎湃,值得好好的学习和整理,为将来的论文改进提供思想上的指导。
  • 在进行DeepLab的介绍之前,我想先讲一下空洞卷积和感受野的计算方法,在这两个概念明确了之后,我们能够更好的理解DeepLab的运算流程。

膨胀卷积(相当于空洞卷积):

DeepLab全家桶小结_第2张图片

  • 直接上图片比较清晰直观。我们可以看到,7x7的feature map经过3x3kernel (dilation = 2),我们可以代入计算公式:Hout = (7 - 2 x (3-1) -1 + 1) = 3。当然stride = 2的话可以自己另外计算。

  • 虽然空洞卷积能够增加感受野,增加在下采样过程中空间信息的保留。但是它也存在一些缺点:

    • 由于空洞卷积是对feature map离散的像素进行处理,处理的并不是临近的像素,很可能在预测的时候会出现一些栅格化的效应。
      DeepLab全家桶小结_第3张图片

    • 对于大物体比较友好,小物体就不好说了

  • 空洞卷积和转置卷积的区别是,空洞卷积是卷积核裂开,转置卷积是feature map裂开,加padding。这个原来已经整理过,在FCN大总结中。

  • 空洞卷积能够在计算量不变的情况下增加感受野,我们可以从这一张图片看到空洞卷积在每一层的感受野变化
    DeepLab全家桶小结_第4张图片

  • 为了防止出现栅格化的现象,一般在使用block的第一个卷积层的dilation rate是1,就像图a所示,这样能够让经过空洞卷积的feature map的感受野有连续性。否则,从第一个卷积层是2的话,感受野就会不连续,出现栅格化效应也就不奇怪了。
    DeepLab全家桶小结_第5张图片

感受野的计算公式:

  • R n = R n − 1 + ( k n − 1 ) ∗ ∏ i = 1 n − 1 s i R_{n}=R_{n-1}+\left(k_{n}-1\right) * \prod_{i=1}^{n-1} s_{i} Rn=Rn1+(kn1)i=1n1si k n − 1 k_{n}-1 kn1$ = dilation * (kernel size - 1)$.
  • R指的是层数。具体感受野公式推导如下链接:https://zhuanlan.zhihu.com/p/375100687
  • 相对感受野的公式是: R n , m = k m + ( R n , m + 1 − 1 ) ∗ s m + 1 R_{n, m}=k_{m}+\left(R_{n, m+1}-1\right) * s_{m+1} Rn,m=km+(Rn,m+11)sm+1 如果是膨胀卷积的话,用
  • 笔记还是上面的知乎专栏比较完整。

DeepLabV1:

  • 这个网络是从VGG-16网络改变而来的。其实主要做了以下的一些改变:

    • 全连接层变成卷积层
    • 把最后两个pooling层给丢掉,变成空洞卷积(通过stride = 2进行下采样),在代码上是把max pooling的stride从2变成1,简直就是为了用VGG的所有参数,省的写代码定制的。
    • 把全连接层的4096维度变成1024,效果没有降低,让速度提升
    • 最开始的FC全卷积层从是7 x 7的kernel size(膨胀卷积),但是作者把这里的卷积核变成了3 x 3(或者4 x 4).VGG直接有的膨胀卷积,这个计算量会太大,当时也就是因为计算量太大之后才开始优化计算量的。
    • 具体的改进已经在图上表明
    • 最后的变成28 x 28,之后直接用双线性上采样8倍之后再用crf

DeepLab全家桶小结_第6张图片

  • 在这里再总结一下V1的流程:

    • 首先采用VGG的backbone进行特征提取。但是这个是经过修改之后的backbone,VGG一共有5次pooling,在第四次和第五次pooling中,作者把pooling的stride变成1,使得之后的feature map的size都是28 x 28.最后的VGG有两个4096的FC层,作者把4096变成1024,减少计算量。这些是backbone的比较大的改动总结
    • 在分类的时候,首先对28 x 28 x 21的feature map进行8倍上采样到224 x 224 x21大小,连接CRF,对最后的数据进行处理
    • 接入损失函数,用的是mIOU指标,通过它进行反向传播计算。
  • 至于CRF,觉得不知道它为什么能够提高分辨的精确率

  • Multi-scale 就是把相同图片,变成不懂大小一起输入,之后把结果平均一下。

  • CRF:觉得就是用这个当损失函数?或者是用机器学习方法求解参数

  • E ( x ) = ∑ i θ i ( x i ) + ∑ i j θ i j ( x i , x j ) E(\boldsymbol{x})=\sum_{i} \theta_{i}\left(x_{i}\right)+\sum_{i j} \theta_{i j}\left(x_{i}, x_{j}\right) E(x)=iθi(xi)+ijθij(xi,xj) x表示每一个像素的类别, x i x_i xi 表示第i个像素的类别。每一个点有21个取值情况。
    θ i ( x i ) = − log ⁡ P ( x i ) \theta_{i}\left(x_{i}\right)=-\log P\left(x_{i}\right) θi(xi)=logP(xi)
    θ i j ( x i , x j ) = μ ( x i , x j ) ∑ m = 1 K w m ⋅ k m ( f i , f i ) \theta_{i j}\left(x_{i}, x_{j}\right)=\mu\left(x_{i}, x_{j}\right) \sum_{m=1}^{K} w_{m} \cdot k^{m}\left(\boldsymbol{f}_{i}, \boldsymbol{f}_{i}\right) θij(xi,xj)=μ(xi,xj)m=1Kwmkm(fi,fi)
    = μ ( x i , x j ) [ w 1 exp ⁡ ( − ∥ p i − p j ∥ 2 2 σ α 2 − ∥ I i − I j ∥ 2 2 σ β 2 ) + w 2 exp ⁡ ( − ∥ p i − p j ∥ 2 2 σ γ 2 ) ] μ ( x i , x j ) = 0 \quad=\mu\left(x_{i}, x_{j}\right)\left[w_{1} \exp \left(-\frac{\left\|p_{i}-p_{j}\right\|^{2}}{2 \sigma_{\alpha}^{2}}-\frac{\left\|I_{i}-I_{j}\right\|^{2}}{2 \sigma_{\beta}^{2}}\right)+w_{2} \exp \left(-\frac{\left\|p_{i}-p_{j}\right\|^{2}}{2 \sigma_{\gamma}^{2}}\right)\right] \quad \mu\left(x_{i}, x_{j}\right)=0 =μ(xi,xj)[w1exp(2σα2pipj22σβ2IiIj2)+w2exp(2σγ2pipj2)]μ(xi,xj)=0 if x i = x j x_{i}=x_{j} xi=xj

  • μ ( x i , x j ) = 1 \mu\left(x_{i}, x_{j}\right)=1 μ(xi,xj)=1 if x i ≠ x j x_{i}≠x_{j} xi=xj,让这个θ变小一些。不过这一部分在DeepLabV3里面就被干掉了。

  • 更多的是求解,和梯度下降。

  • large-FOV就是把3x3的空洞卷积stride变成12.让感受野变得更大,甚至是比原图的更大。

DeepLabV2:

DeepLab全家桶小结_第7张图片

  • 第二版有以下的改变:首先是用了ResNet作为backbone,然后用了ASPP(空洞空间金字塔池化)模块进行多尺度特征融合,在学习率调整上,这一片论文也提出了自己的一些见解。对于ResNet我就不做更多的解释了,在之前的文章已经写过了。我们先来看看ASPP模块。

ASPP:

DeepLab全家桶小结_第8张图片

  • 这个rate的意思就是dilation rate,其实现在看来还是写得比较清楚的。经过这4个卷积块之后,能够实现对不同尺度(感受野)的特征进行融合,提取到更加丰富的信息。
    DeepLab全家桶小结_第9张图片

  • 论文里面对ASPP还进行了一些说明和实验,在这里就把图片先贴出来。这个r就是rate,里面的列表表示的是每一个卷积层对应的dilation rate。实验中,数据占优的是ASPP-L,它的rate是比较大的,都是6的倍数。有些事情就是人肉搜索出来的,强硬解释为什么这个效果好的方法就只能说,这个卷积的感受野更大,融合的特征感受野也更大,有利于分割任务的完成。

  • 在这里加一下ASPP的代码实现,这个还是比较重要的,因为自己对于代码实现还是比较薄弱的。需要增强一下这方面的知识。

import torch
import torch.nn as nn
import torch.nn.functional as F

class ASPP(nn.Module):

    def __init__(self, in_chans, out_chans, rate=1):
        super(ASPP, self).__init__()

        # 1 x 1 无孔洞卷积
        # conv2d 参数先是输入输出通道,然后是kernel size,stride padding dilation默认一般是1,
        # bias看看能不能要
        self.conv_part1 = nn.Sequential(
            nn.Conv2d(in_chans,out_chans,1,1,padding=0,dilation=rate,bias=True),
            nn.BatchNorm2d(out_chans),
            nn.ReLU(inplace=True)
        )

        # 3 x 3 空洞6卷积
        self.conv_part2 = nn.Sequential(
            nn.Conv2d(in_chans, out_chans, 3, 1, padding = 6*rate, dilation= 6*rate,bias = True),
            nn.BatchNorm2d(out_chans),
            nn.ReLU(inplace= True)
        )

        self.conv_part3 = nn.Sequential(
            nn.Conv2d(in_chans,out_chans,3,1,padding=12 * rate,dilation=12 * rate, bias = True),
            nn.BatchNorm2d(out_chans),
            nn.ReLU(inplace=True)
        )
		# 为什么没有24的dilation,因为在deeplabV3+中24的dilation被去除了
        self.conv_part4 = nn.Sequential(
            nn.Conv2d(in_chans,out_chans,3,1,padding=18*rate, dilation=18*rate,bias = True),
            nn.BatchNorm2d(out_chans),
            nn.ReLU(inplace=True)
        )

        # 全局池化:里面的参数output size,这部分代码,就是对合并之后的feature map处理的代码作者
        # 在论文里面并没有写。
        self.conv_part5_avg = nn.AdaptiveAvgPool2d(1)
        # 1 x 1的cbr用来处理平均池化所得到的特征图
        self.conv_part5_conv = nn.Conv2d(in_chans,out_chans,1,1,bias = True)
        self.conv_part5_bn = nn.BatchNorm2d(out_chans)
        self.conv_part5_relu = nn.ReLU(inplace=True)
        self.conv_cat = nn.Sequential(
            nn.Conv2d(out_chans * 5,out_chans, 1,1,padding=0,bias=True),
            nn.BatchNorm2d(out_chans),
            nn.ReLU(inplace=True)
        )


    def forward(self, x):
        b, c, h, w = x.size()
        conv1x1 = self.conv_part1(x)
        conv3x3_1 = self.conv_part2(x)
        conv3x3_2 = self.conv_part3(x)
        conv3x3_3 = self.conv_part4(x)
        global_feature = self.conv_part5_avg(x)
        # 对全局池化的特征要进行处理
        global_feature = self.conv_part5_relu(self.conv_part5_bn(self.conv_part5_conv(global_feature)))
        # 上采样到原图的大小,一直到deeplabV3+作者才用了了转置卷积
        global_feature = F.interpolate(global_feature,(h,w),None,'bilinear',True)
        # 在bchw上contact,所以dim必须是1
        feature_cat = torch.cat([conv1x1,conv3x3_1,conv3x3_2,conv3x3_3,global_feature],dim = 1)
        result = self.conv_cat(feature_cat)
        return result

learning rate policy

  • KaTeX parse error: Expected '}', got '_' at position 42: … }}{\text { max_̲iter }}\right)^… 这个是作者在训练的时候对学习率的调整策略,和原来百度的三角调整策略很相似。

  • 在论文中,作者实验的power值是0.9.iter是每一次迭代(不是epoch的意思,max_iter = epoch * iter_per_epoch)。当然这个应该只是一个权重,前面应该还需要乘上一个系数,也就是lr。
    DeepLab全家桶小结_第10张图片

  • 作者在计算的时候发现,batch_size减小的时候mean_IOU也不会降低,于是就减小了它,加快训练速度。

  • 论文的剩下部分就是实验结果部分了。我们可以大踏步来到V3

DeepLabV3:

  • 作者一直在想方设法把CRF给去掉,终于在这一个版本,作者成功去掉了CRF这个模块。在这一个版本,作者的改动其实并不太多。用的block都是resnet_block。只不过在使用的时候,作者把block4重复了好几次,做了一个Cascade。在block内部,作者对每一个conv的dilation rate进行了调整。当然作者也不会忘记对ASPP进行调整,作者也做了一个parallel网络,最终选择的网络还是parallel,说明特征融合的强大。

  • 我们首先来看看Cascade模块:

DeepLab全家桶小结_第11张图片

  • 上面的图是原始的resnet和加了dilation rate 的deeplab的结构比较图。我们看到,从block3之后,feature map就不再减小了。我们在论文里面可以看到OS这个东西,这个的意思是output_stride,就是下采样的倍数。在resnet的conv1和pooling1中,已经下采样了4倍,经过block1,block2再下采样4倍合起来就是16。具体可以看deeplabv3代码。

DeepLab全家桶小结_第12张图片

  • 在级联的网络中,我们可以看到Multi_Grid这个东西,其实这个代表了初始block中三个卷积层每一个的dilation rate。最终经过实验证明,初始的Multi_grid = (1,2,1)效果最好。rate就是这一个block中Multi_grid的值是rate x (1,2,1)。具体实验图表如下图所示:

DeepLab全家桶小结_第13张图片

  • 作者还对网络结构进行了调整,作者试试如果把ASPP稍微改了一下,把V2中有一个rate = 24的conv给删除了,改成了1 x1的conv层,之后contact。于是出现了这个parallel结构:

DeepLab全家桶小结_第14张图片

  • 其中image Pooling的代码如下:

  • global_feature = self.conv_part5_avg(x)
            # 对全局池化的特征要进行处理
    global_feature = self.conv_part5_relu(self.conv_part5_bn(self.conv_part5_conv(global_feature)))
    global_feature = F.interpolate(global_feature,(h,w),None,'bilinear',True)	
    
  • 经过作者不断地人肉搜索结构之后,得到的结果还是比较好的。在之后也成功地删除了CRF,终于不用搞这个麻烦的公式了。

DeepLab全家桶小结_第15张图片

DeepLabV3+:

  • 这个论文只是对DeepLabV3的补充,并没有提出太多的东西。主要的创新点在这里:
    DeepLab全家桶小结_第16张图片

  • backbone使用了Xception,这个结构之后再看。内容太多了。

  • 然后把卷积变成了深度可分离空洞卷积。加上了一个Decoder的模块,终于用上了转置卷积。具体的等到我看完论文再整理吧。

你可能感兴趣的:(AI保研之旅,神经网络,pytorch,深度学习)