[语义分割] DeepLab v2(膨胀卷积、空洞卷积、多尺度信息融合、MSc、ASPP、空洞空间金字塔池化、Step学习率策略、Poly学习率策略)
膨胀卷积、空洞卷积、多尺度信息融合、MSc、ASPP、空洞空间金字塔池化、Step学习率策略、Poly学习率策略
- 论文地址:DeepLab: Semantic Image Segmentation with Deep Convolutional Nets, Atrous Convolution, and Fully Connected CRFs
- 源码地址:DeepLab: Semantic Image Segmentation with Deep Convolutional Nets, Atrous Convolution, and Fully Connected CRFs
- 复现代码:https://github.com/kazuto1011/deeplab-pytorch
这是一篇于 2016 年发布在 CVPR 上的文章。接着上一篇 DeepLab V1 网络简介,本文对 DeepLab V2 网络进行简单介绍。DeepLab V1 相比 DeepLab V2 就是换了个 Backbone(VGG → ResNet,简单换个 Backbone 就能涨大概 3 个点)然后引入了一个新的模块 ASPP(Atros Spatial Pyramid Pooling,空洞空间金字塔池化),其他的没太大区别。
DeepLab v2 概况
DeepLab v2 是一个语义分割模型,旨在对图像进行像素级别的分类,将每个像素分配到其对应的语义类别。它是 DeepLab 系列的第二个版本,在 2016 年由 Chen 等人提出,并取得了令人印象深刻的结果。
DeepLab v2 的核心思想是使用深度卷积神经网络(DCNN)来解决语义分割问题,并在此基础上引入了一些关键技术来提高性能。其主要的核心思想包括:
-
膨胀卷积(Atrous Convolution):传统的卷积操作具有固定的感受野大小,但在语义分割任务中,需要考虑不同尺度的上下文信息。为了实现这一点,DeepLab v2 采用了膨胀卷积。通过在卷积操作中引入可调节的膨胀系数(率) r r r,可以在不增加计算量的情况下扩大感受野,从而捕捉更广泛的上下文信息。
-
多尺度信息融合:为了进一步提高语义分割的性能,DeepLab v2 采用了多尺度信息融合(Multi-Scale,MSc)的策略。它通过在不同膨胀系数 r r r 下进行多尺度的膨胀卷积操作,并将这些不同尺度的特征图融合在一起,从而使模型能够同时利用局部和全局的上下文信息。
-
高分辨率分类器:在语义分割任务中,分辨率较低的特征图可能会导致细小目标的信息丢失。为了解决这个问题,DeepLab v2 在膨胀卷积后使用了一个全局平均池化层(AvgPooling),将特征图的尺寸降低到 1 × 1 1\times 1 1×1,然后通过一个额外的高分辨率分类器来对原始尺寸的特征图进行上采样,从而恢复细节信息。
-
条件随机场(CRF)后处理:在语义分割中,由于卷积神经网络的输出是逐像素的分类结果,可能存在一些不连续性和噪声。为了优化分割结果并增强空间连续性,DeepLab v2 使用了条件随机场(CRF)后处理步骤,以进一步优化像素标签。
总的来说,DeepLab v2 通过引入膨胀卷积、多尺度信息融合、高分辨率分类器和 CRF 后处理等技术,显著提高了语义分割任务的性能,成为当时语义分割领域的重要里程碑之一。
Abstract
在这项工作中,我们使用深度学习来解决语义图像分割任务,并做出了三个主要贡献,经实验证明具有实际价值。
- ①首先,我们强调卷积操作与上采样卷积层的结合,或者称为“膨胀卷积”,作为密集预测任务中的强大工具。膨胀卷积允许我们明确控制在深度卷积神经网络中计算特征响应的分辨率。它还使我们能够有效地扩大卷积层的感受野,以在不增加参数或计算量的情况下纳入更大的上下文信息。
- ②其次,我们提出了空洞空间金字塔池化(ASPP)来在多个尺度上鲁棒地分割对象。ASPP 使用多种采样率和有效视野对输入的卷积特征层进行探测,从而捕捉多个尺度上的对象以及图像上下文。
- ③第三,我们通过结合深度卷积神经网络(DCNNs)和概率图模型的方法来改善对象边界的定位。在 DCNNs 中常用的最大池化和降采样组合实现了不变性,但会影响定位的准确性。我们通过将最终 DCNN 层的响应与全连接的条件随机场(CRF)相结合来克服这一问题,定性和定量地证明了它能够改善定位性能。
我们提出的 “DeepLab” 系统在 PASCAL VOC-2012 语义图像分割任务上取得了新的最高水平,测试集上达到了 79.7% 的 mean IoU,并在其他三个数据集(PASCAL-Context,PASCAL-Person-Part 和 Cityscapes)上取得了进展。我们的所有代码都公开在网上可供使用。
概率图模型(Probabilistic Graphical Model,PGM)是一种用于表示和处理不确定性信息的概率模型。它是概率论和图论的结合,旨在描述变量之间的概率关系,并通过图形的方式展示这些关系。在概率图模型中,节点表示随机变量,边表示随机变量之间的条件依赖关系。
- PASCAL-Context:PASCAL-Context 是一个用于语义分割任务的数据集,是 PASCAL VOC 2010 数据集的扩展版本。它包含了对 20 个对象类别的像素级别标注,同时还提供了对每个像素的细粒度标注,将对象分割成更多的语义类别。这个数据集对于研究场景中细粒度语义理解非常有用,因为它允许分割出更多类别的对象部分,例如“车轮”、“玻璃”、“车门”等。PASCAL-Context 数据集是计算机视觉和语义分割研究中一个常用的基准数据集。
- PASCAL-Person-Part:PASCAL-Person-Part 是基于 PASCAL VOC 2010 数据集创建的数据集,专门用于人体部分语义分割。它包含了对人体图像进行的像素级别标注,将人体分割成头部、手臂、腿等细粒度部分。该数据集使得研究人员可以专注于解决人体部分分割的挑战,对于姿势估计、人体动作分析等任务都有很大的帮助。
- Cityscapes:Cityscapes 是一个用于城市场景理解的大规模数据集,主要用于语义分割和实例分割任务。它提供了大量来自德国和瑞士 50 个城市的高分辨率图像,包含各种复杂的城市环境,如街道、交通标志、建筑物、汽车等。Cityscapes 数据集提供了精细的像素级别标注,涵盖了 19 个语义类别,以及一些额外的信息,如实例级别分割标注和像素级别的语义标签。这个数据集在城市场景理解、自动驾驶等领域的研究中发挥着重要作用。
1. CNNs 应用在语义分割任务中存在的问题及解决方案
1.1 CNNs 在语义分割中存在的问题
和上篇文章一样,在文章的引言部分作者提出了 DCNNs 应用在语义分割任务中遇到的问题。
- 分辨率被降低(主要由于下采样
stride > 1
的卷积/池化层导致)—— v1 中已提出 - 目标的多尺度问题
- CNNs 的不变性(Invariance)会降低定位精度 —— v1 中已提出
虽然问题 2 是 v2 中新提出来的问题,但是在 v1 中已经有一个名为 MSc(Multi-Scale) 的trick。
1.2 解决方案
-
分辨率被降低:一般就是将最后的几个 Maxpooling 层的
stride
给设置成 1(如果是通过卷积下采样的,比如 ResNet,同样将stride
设置成 1 即可),然后在配合使用膨胀卷积。 -
目标多尺度:最容易想到的就是将图像缩放到多个尺度分别通过网络进行推理,最后将多个结果进行融合即可。这样做虽然有用但是计算量太大了。为了解决这个问题,DeepLab V2 中提出了 ASPP 模块(Atrous Spatial Pyramid Pooling,空洞空间金字塔池化),具体结构后面会讲。
-
CNNs 不变性导致定位精度降低:和 DeepLab V1 差不多,还是通过 CRFs 解决,不过这里用的是 fully connected pairwise CRF,相比 V1 里的 fully connected CRF 要更高效点。在 DeepLab V2 中 CRF 涨点就没有 DeepLab V1 猛了,在 DeepLab V1 中大概能提升 4 个点,在 DeepLab V2 中通过 Table4 可以看到大概只能提升 1 个多点了。
pairwise
- adv. 对偶(地);成对(双)(地);
- adj. 两个两个的;成对的;
2. DeepLab V2 的优势
和 DeepLab V1 中写的一样:
- 速度更快
- 准确率更高(当时的 state-of-the-art)
- 模型结构简单,还是 CNNs 和 CRFs 的联级
3. ASPP(Atrous Spatial Pyramid Pooling,空洞空间金字塔池化)
3.1 ASPP 结构
在 DeepLab V2 中最值得讲的就是 ASPP 模块了,其他的都算不上啥亮点😂。这个 ASPP 模块很像是 DeepLab V1 中 LargeFOV + MSc 的升级版(但额外加入了多尺度的特性)。下图是原论文中介绍 ASPP 的示意图,就是在 Backbone 输出的 Feature Map 上并联四个分支,每个分支的第一层都是使用的膨胀卷积,但不同的分支使用的膨胀系数不同(即每个分支的感受野不同,从而具有解决目标多尺度的问题)。
由于每个分支的膨胀系数不同,因此每个分支的感受野是不一样的(膨胀系数越大,感受野越大),最终将 4 个分支的结果进行融合就使得 DeepLab v2 具有了解决多尺度的能力。
在 DeepLab v1 中,LargeFOV 本质上就是使用了膨胀卷积替换全连接层;MSc 就是 Multi-Scale 连接(但都是普通卷积,没有膨胀卷积),而 ASPP 是多分支,并且每个分支都使用了膨胀卷积,所以说,ASPP ≈ \approx ≈ LargeFOV + MSc。
3.2 DeepLab-ASPP(以 VGG-16 为例)
下图是更加详细的 ASPP 结构(以 VGG-16 为例)。
图中虽然写着是 FC,但 DeepLab 中并没有 FC,所以都是普通卷积或膨胀卷积。
将 Pool5 输出的特征层并联 4 个分支,每个分支分别通过一个
3
×
3
3\times 3
3×3 的膨胀卷积层、
1
×
1
1\times 1
1×1 的卷积层、
1
×
1
1\times 1
1×1 的卷积层(卷积核的个数等于 num_classes
)。最后将四个分支的结果进行
⊕
\oplus
⊕ 融合即可。
如果是以 ResNet-101 做为 Backbone 的话,每个分支只有一个 3 × 3 3\times 3 3×3 的膨胀卷积层,卷积核的个数等于
num_classes
(根据源码分析得到)。
3.3 ASPP 不同配置
在论文中有给出两个 ASPP 的配置:
- ASPP-S(四个分支膨胀系数分别为
[2,4,8,12]
) - ASPP-L(四个分支膨胀系数分别为
[6,12,18,24]
)
下表是对比 LargeFOV、ASPP-S 以及 ASPP-L 的效果。这里的模型并没有使用 CRF 。
LargeFOV:单一分支,r = 12
ASPP-S:四个分支,r = {2, 4, 8, 12}
ASPP-L:四个分支,r = {6, 12, 18, 24}
从上表可以看到,ASPP-L > ASPP-S > LargeFOV。因此我们在使用 DeepLab v2 时一般使用 ASPP-L。
4. DeepLab V2 网络结构
这里以 ResNet-101 作为 Backbone 为例,下图是 霹雳吧啦WZ 根据官方源码绘制的网络结构(不考虑 MSc 多尺度融合)。
经过 8 倍上采样得到 224 × 224 × n u m c l a s s e s 224 \times 224 \times \mathrm{num \ classes} 224×224×num classes 的特征图并非模型最终输出结果,还要经过一个 Softmax 层后才是模型最终的输出结果。
需要注意的点❗️
- 在 ResNet 的 Layer3 中的 Bottleneck1 中原本是需要下采样的(
3
×
3
3\times 3
3×3 的卷积层
stride=2
),但在 DeepLab V2 中将stride
设置为 1,即不在进行下采样。而且 3 × 3 3\times 3 3×3 卷积层全部采用膨胀卷积膨胀系数为 2。 - 在 Layer4 中也是一样,取消了下采样,所有的 3 × 3 3\times 3 3×3 卷积层全部采用膨胀卷积膨胀系数为 4。
- 最后需要注意的是 ASPP 模块,在以 ResNet-101 做为 Backbone 时,每个分支只有一个
3
×
3
3\times 3
3×3 的膨胀卷积层(没有后面的两个
1
×
1
1 \times 1
1×1 卷积层了),且卷积核的个数都等于
num_classes
(=输出特征图通道数)。
5. Learning Rate Policy(学习率策略)
5.1 普通的 step 学习率变化策略
学习率策略是指在训练过程中调整学习率的方式。Step策略是一种常见的学习率策略之一。在 Step 策略中,学习率在训练的特定步骤(epoch 或者迭代次数)时会进行调整。Step 策略的学习率更新公式为:
学习率 = 初始学习率 × γ ( 当前步骤数 / / s t e p _ s i z e ) l r i = l r i n i t × γ s t e p i / / s t e p _ s i z e \begin{aligned} & 学习率 = 初始学习率 \times \gamma ^{ (当前步骤数 // \mathrm{step\_size})}\\ & \mathrm{lr}_i = \mathrm{lr_{init}} \times \gamma^{\mathrm{step}_i // \mathrm{step\_size}} \end{aligned} 学习率=初始学习率×γ(当前步骤数//step_size)lri=lrinit×γstepi//step_size
其中:
- 初始学习率 l r i n i t \mathrm{lr_{init}} lrinit 是训练开始时设置的学习率
-
γ
\gamma
γ 是一个介于 0 和 1 之间的超参数,用于控制学习率的下降速度
- γ \gamma γ 越大,学习率下降越慢
- γ \gamma γ 越小,学习率下降越快
- 当前步骤数 s t e p i \mathrm{step}_i stepi 是指训练进行到的当前步骤
-
s
t
e
p
_
s
i
z
e
\mathrm{step\_size}
step_size 是调整学习率的步长:
- s t e p _ s i z e \mathrm{step\_size} step_size 越大,学习率的调整频率越低,学习率下降速度越慢
- s t e p _ s i z e \mathrm{step\_size} step_size 越小,学习率的调整频率越高,学习率下降速度越快
注意❗️
- 当 当前步骤数 s t e p i \mathrm{step}_i stepi 是调整学习率的步长 s t e p _ s i z e \mathrm{step\_size} step_size 的倍数时,会进行学习率的调整
- / / // // 表示整除
import matplotlib.pyplot as plt
def step_learning_rate(initial_lr, gamma, step_size, total_steps):
learning_rates = [initial_lr * (gamma ** (step // step_size)) for step in range(total_steps)]
return learning_rates
# 设置初始学习率、gamma、step_size和总迭代次数
initial_lr = 0.1
gamma_lst = [0.01, 0.1, 0.25, 0.5, 0.8]
# step_size_lst = [5, 10, 20, 50]
step_size = 10
total_steps = 100
# 获取学习率变化曲线数据
for gamma in gamma_lst:
learning_rates = step_learning_rate(initial_lr, gamma, step_size, total_steps)
# 绘制学习率变化曲线
plt.plot(range(total_steps), learning_rates, label=f"$gamma={gamma}$")
plt.xlabel('Step')
plt.ylabel('Learning Rate')
plt.title('Step Learning Rate Schedule')
plt.grid(True)
plt.legend()
plt.savefig("step learning rate strategy", dpi=300)
5.2 DeepLab v2 的 poly 学习率变化策略
在 DeepLab V2 中训练时采用的学习率策略叫 poly
,相比普通的 step
策略(即每间隔一定步数就降低一次学习率)效果要更好。文中说最高提升了 3.63 个点,真是炼丹大师😂。poly
学习率变化策略公式如下:
l r i = 初始学习率 × ( 1 − 当前迭代次数 总迭代次数 ) 幂指数 = l r i n i t × ( 1 − i t e r i m a x _ i t e r ) p o w e r \begin{aligned} \mathrm{lr}_i & = 初始学习率 × (1 - \frac{当前迭代次数}{总迭代次数}) ^{幂指数}\\ & = \mathrm{lr_{init}} \times (1 - \frac{\mathrm{iter}_i}{\mathrm{max\_iter}})^{\mathrm{power}} \end{aligned} lri=初始学习率×(1−总迭代次数当前迭代次数)幂指数=lrinit×(1−max_iteriteri)power
其中:
- l r i \mathrm{lr}_i lri 表示第 i i i 次迭代的学习率(当前学习率)
- l r i n i t \mathrm{lr_{init}} lrinit 是初始学习率
- i t e r i \mathrm{iter}_i iteri 是当前迭代次数
- m a x _ i t e r \mathrm{max\_iter} max_iter 是总迭代次数
-
p
o
w
e
r
\mathrm{power}
power 是幂指数。幂指数是一个超参数,用于控制学习率下降的速度。通常情况下:
- 它可以设为 1,表示线性减小学习率
- 或者设为其他小于 1 的值,以实现更激进的学习率下降
- p o w e r \mathrm{power} power 越小,学习率下降越慢
- p o w e r \mathrm{power} power 越大,学习率下降越快
在 DeepLab v2 中,Poly 学习率策略的默认幂指数(power)值为 0.9。
import matplotlib.pyplot as plt
def poly_learning_rate(initial_lr, power, total_steps):
learning_rates = [initial_lr * (1 - step / total_steps) ** power for step in range(total_steps)]
return learning_rates
# 设置初始学习率、幂指数和总迭代次数
initial_lr = 0.1
power_lst = [1.0, 0.9, 0.5, 0.1]
total_steps = 100
# 获取学习率变化曲线数据
for power in power_lst:
learning_rates = poly_learning_rate(initial_lr, power, total_steps)
# 绘制学习率变化曲线
plt.plot(range(total_steps), learning_rates, label=f"$power={power}$")
plt.xlabel('Step')
plt.ylabel('Learning Rate')
plt.title('Poly Learning Rate Schedule')
plt.legend()
plt.grid(True)
plt.savefig("poly learning rate strategy", dpi=300)
5.3 Step v.s. Poly 学习率策略效果对比
从上表数据可以看到,Poly 学习率变化策略对 mean IoU 的提升较为明显!
6. 消融实验(Ablation)
下表是原论文中给出的一些消融实验对比:
我们评估了每个因素以及 LargeFOV 和 Atrous Spatial Pyramid Pooling (ASPP) 对验证集性能的影响。将 ResNet-101 用于替代 VGG-16 显著提高了 DeepLab 的性能(例如,我们最简单的基于 ResNet-101 的模型达到了 68.72%,而我们基于 DeepLab-LargeFOV VGG-16 的变体在 CRF 之前为 65.76%)。多尺度融合 [ 17 ] ^{[17]} [17]带来额外的 2.55% 的改进,而在 MS-COCO 上预训练模型又带来了额外的 2.01% 的提升。训练过程中的数据增强是有效的(大约提升了 1.6%)。采用 LargeFOV(在 ResNet 的顶部添加一个具有 3 × 3 3\times 3 3×3 的内核和
r = 12
的膨胀卷积层)是有益的(大约提升了 0.6%)。而通过 Atrous Spatial Pyramid Pooling (ASPP) 进一步提高了 0.8%。通过密集条件随机场(dense CRF)后处理我们的最佳模型,性能达到了 77.69%。
- MSC:表示多尺度输入,先将图像缩放到 0.5、0.7 和 1.0 三个尺度,然后分别送入网络预测得到 score maps,最后融合这三个 score maps(对每个位置取三个 score maps 的最大值,而非我们常见的 ⊕ \oplus ⊕) —— 提升较大!
- COCO:是否使用在 MS-COCO 上预训练的模型 —— 提升较大!
- Aug:代表数据增强,这里就是对输入的图片在 0.5 到 1.5 之间进行随机缩放 —— 一般提升!
- LargeFOV 是在 DeepLab V1 中讲到过的结构 —— 提升不如在 v1 时的表现!
- ASPP 前面讲过了 —— 一般提升!
- CRF 前面也提到过了 —— 一般提升!
知识来源
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)