1. 引言
1.1 本文目的
本文主要对前段时间学习的 ASPP 模块进行对比,涉及到的 ASPP 有:
- ASPP in DeepLab v2,简称 ASPP v2
- ASPP in DeepLab v3,简称 ASPP v3
- ASPP in DeepLab v3+,简称 ASPP v3+
- ASPP in MobileNet v3,简称 LR-ASPP
这里的 v1、v2 是与 DeepLab 的版本号对应,因此没有 v1 😬
1.2 语义分割大致流程
语义分割是计算机视觉中的一项重要任务,它的目标是对图像中的每个像素进行分类,将相同语义类别的像素标记为同一类别。下面是大致的流程:
流程说明:
-
输入图像:将待分割的图像作为输入。
-
选择语义分割模型:选择适合任务的语义分割模型,常用的模型包括 U-Net、SegNet、DeepLab 等。
-
加载预训练权重:如果可用,加载预训练模型的权重,这有助于提高分割性能。
-
进行图像预处理:对输入图像进行预处理,包括大小调整、归一化、数据增强等,以提高模型的鲁棒性和准确性。
-
使用模型进行推理:将预处理后的图像输入语义分割模型,进行推理得到像素级别的预测结果。
-
获取像素类别预测:从模型输出中获取每个像素的语义类别预测,通常使用 softmax 函数将预测转换为概率分布。
-
后处理与可视化:对预测结果进行后处理,可能包括阈值处理、连通组件分析等,以生成最终的分割结果。同时,可以将分割结果可视化,将不同类别的像素着色,以便观察和验证分割效果。
其实语义分割和分类任务是差不多的,都是属于比较简单的。
因为本文主要讲不同 ASPP,因此我们简化语义分割流程,并加入 ASPP 模块,如下图所示。
从图中我们可以知道,与分类任务相同,首先给模型输入 RGB 图片 I m a g e \mathrm{Image} Image,之后经过 Backbone 进行推理。值得注意的是,在分类任务中,我们可能直接通过 Backbone 加上一个分类头(Classification Head)就可以得到最终的结果了。但在语义分割中,我们不使用全部的 Backbone(一般而言,这里所说的 Backbone 是分类网络中 真正的Backbone + Classification Head),而是去除最后几层(一般是去掉 Classification Head)。
- 如上图所示,输入图片 I m a g e \mathrm{Image} Image 经过 Backbone 后输出一个 28 × 28 × 2048 28 \times 28 \times 2048 28×28×2048 的特征图 F 1 \mathcal{F}_1 F1。
- 之后再将 F 1 \mathcal{F}_1 F1 送入 ASPP 模块,得到 shape 为 28 × 28 × c h a n n e l b y c o n c a t e n a t e d 28 \times 28 \times \mathrm{channel \ by \ concatenated} 28×28×channel by concatenated 的 ASPP 输出特征图 F 2 \mathcal{F}_2 F2。
- 最后我们再将 ASPP 输出特征图 F 2 \mathcal{F}_2 F2 送入分割头(Segmentation Head),这个头一般会对特征图进行上采样和 softmax 计算,前者的目的是将特征图 F 3 \mathcal{F}_3 F3 的 [ H , W ] [H, W] [H,W] 恢复到输入图片 I m a g e \mathrm{Image} Image 的大小;后者的目的是得到每个像素所属的类别。
- 经过上述过程,我们就可以得到一个 shape 为 480 × 480 × n u m _ c l a s s e s 480 \times 480 \times \mathrm{num\_ classes} 480×480×num_classes 的最终特征图 F 3 \mathcal{F}_3 F3,这个最终特征图的宽度和高度与输入图片是一致的,但通道数变为 n u m _ c l a s s e s \mathrm{num\_ classes} num_classes。因此我们便可以知道图片中每个像素所属的类别,再经过一定的后处理就可以得到语义分割后的结果,即一张灰度图 F o u t \mathcal{F}_\mathrm{out} Fout(不同类别分别对应一个独特的像素值)。
因为 ASPP 一般会使用并行结构,并且最后会对不同分支的结果进行融合,因此 ASPP 输出特征图最后一个维度是 c h a n n e l b y c o n c a t e n a t e d \mathrm{channel \ by \ concatenated} channel by concatenated 🧐
通过上述对语义分割流程的描述,我们就知道语义分割的大致流程。接下来我们就可以学习不同 ASPP 的特点和不同了。
2. 各版本 ASPP 介绍
2.1 ASPP v2
参考博文:[语义分割] DeepLab v2(膨胀卷积、空洞卷积、多尺度信息融合、MSc、ASPP、空洞空间金字塔池化、Step学习率策略、Poly学习率策略)
在 DeepLab V2 首先提出 ASPP 概念,这个 ASPP 模块很像是 DeepLab V1 中 LargeFOV + MSc 的升级版(但额外加入了多尺度的特性),下面是 ASPP v2 的示意图。
ASPP v2 的结构非常清晰,就是在 Backbone 的输出特征图后并联四个分支,每个分支的第一层都是使用的膨胀卷积,但不同的分支使用的膨胀系数不同(dilate = [6, 12, 18, 24]
)(即每个分支的感受野不同,从而具有解决目标多尺度的问题)。因此每个分支的感受野是不一样的(膨胀系数越大,感受野越大),最终将 4 个分支的结果进行融合
⊕
\oplus
⊕ 就使得 DeepLab v2 具有了解决多尺度的能力。
在 DeepLab v1 中,LargeFOV 本质上就是使用了膨胀卷积替换全连接层;MSc 就是 Multi-Scale 连接(但都是普通卷积,没有膨胀卷积),而 ASPP 是多分支,并且每个分支都使用了膨胀卷积,所以说,ASPP ≈ \approx ≈ LargeFOV + MSc。
2.2 ASPP v3
参考博文:[语义分割] DeepLab v3(Cascaded model、ASPP model、两种ASPP对比、Multi-grid、训练细节)
我们再来看下 DeepLab V3 中的 ASPP,即 ASPP v3 结构,如下图所示。
ASPP v3 中的膨胀卷积是经典的汉堡包结构:
Conv → BN → Activation
ASPP v3 有 5 个并行分支,分别是:
① 一个
1
×
1
1\times 1
1×1 的卷积层(普通卷积)
② ~ ④ 三个
3
×
3
3\times 3
3×3 的膨胀卷积层(膨胀率
r
r
r 是不同的)
⑤ 一个全局平均池化层(后面还跟有一个
1
×
1
1\times 1
1×1 的卷积层,然后通过双线性插值的方法还原回输入的 W
和 H
)。
关于最后一个全局池化分支作者说是为了增加一个全局上下文信息(Global Contextual Information)。
之后通过 Concat
的方式将这 5 个分支的输出进行拼接 concat
(沿着 channel
方向),最后再通过一个
1
×
1
1\times 1
1×1 的卷积层(普通卷积)进一步融合信息。
2.3 ASPP v3+
参考博文:[语义分割] DeepLab v3+(DeepLab v3 Plus、Backbone、Xception、MobileNet v2、Encoder、Decoder、ASPP、多尺度融合、膨胀卷积)
从图中可以看到,ASPP v3+ 其实和很相似,但有两点不同:
- 膨胀卷积中的膨胀系数不同
- 膨胀卷积使用的是深度可分离卷积
2.4 LR-ASPP
LR-ASPP 在 Backbone 输出上分成了两个分支,如下图所示:
- 【第一个分支】上面的分支通过一个简单的
1
×
1
1 \times 1
1×1 卷积(
bias=False
)汉堡包结构,即Conv -> BN -> ReLU
,得到一个输出特征图 F 1 \mathcal{F}_1 F1 - 【第二个分支】第二分支通过一个 核大小为
49
×
49
49 \times 49
49×49,步长为
[
16
,
20
]
[16, 20]
[16,20] 的全局平均池化层(AvgPooling Layer),之后再通过一个
1
×
1
1 \times 1
1×1 的普通卷积(
bias=False
) + Sigmoid,得到一个输出特征图 F 2 \mathcal{F}_2 F2
注意❗️:
- 根据观察源码,
F
1
\mathcal{F}_1
F1 分支中的
ReLU
就是普通的ReLU
而非ReLU6
-
F
2
\mathcal{F}_2
F2 分支中的
Bilinear Upsample
其实是不需要的(正常来说,通过 Sigmoid 层后得到的就是长度为 128 的向量) -
F
2
\mathcal{F}_2
F2 分支中的
AdaptiveAvgPool2d -> 1×1 Conv -> Sigmoid
与 MobileNet v3 中提出的 Squeeze-and-Excitation(SE)注意力模块非常相似
- 【第一次融合】 F 1 ⊗ F 2 \mathcal{F}_1 \otimes \mathcal{F}_2 F1⊗F2 之后,经过双线性插值进行 2 倍上采样,之后再经过普通的 1 × 1 1 \times 1 1×1 卷积,得到输出特征图 F 3 \mathcal{F}_3 F3
- 【第三个分支】将 Backbone 中经过 8 倍下采样的特征图拿出来,经过 普通的 1 × 1 1 \times 1 1×1 卷积得到输出特征图 F 4 \mathcal{F}_4 F4
- 【第二次融合】 F 3 ⊕ F 4 = F 5 \mathcal{F}_3 \oplus \mathcal{F}_4 = \mathcal{F}_{5} F3⊕F4=F5,得到 LR-ASPP 的输出特征图。
3. ASPP 结构汇总
4. 不同 ASPP 准确率提升对比
Model | Backbone | Version | Before(%) | After(%) | Δ \Delta Δ | Dataset |
---|---|---|---|---|---|---|
DeepLab v2 | ResNet-101 | ASPP v2 | 74.87 | 76.35 | +1.48 | VOC 2012 |
DeepLab v3 | ResNet-101 | ASPP v3 | 77.21 | 78.51 | +1.3 | VOC 2012 |
DeepLab v3+ | Xception | ASPP v3+ | 79.17 | 79.93 | +0.76 | VOC 2012 |
MobileNetV3 LR-ASPP | MobileNetV3 Large | LR-ASPP | 71.91 | 72.37 | +0.46 | Cityscapes |
现在我们来具体分析每个模型的性能:
-
DeepLab v2:
- Backbone: ResNet-101
- Version: ASPP v2
- 在VOC 2012数据集上,训练之前准确率为74.87%,经过训练后提高到76.35%。经过训练后的性能提升了1.48个百分点。
-
DeepLab v3:
- Backbone: ResNet-101
- Version: ASPP v3
- 在VOC 2012数据集上,训练之前准确率为77.21%,经过训练后提高到78.51%。经过训练后的性能提升了1.3个百分点。
-
DeepLab v3+:
- Backbone: Xception
- Version: ASPP v3+
- 在VOC 2012数据集上,训练之前准确率为79.17%,经过训练后提高到79.93%。经过训练后的性能提升了0.76个百分点。
-
MobileNetV3 LR-ASPP:
- Backbone: MobileNetV3 Large
- Version: LR-ASPP
- 在Cityscapes数据集上,训练之前准确率为71.91%,经过训练后提高到72.37%。经过训练后的性能提升了0.46个百分点。