深度学习之图像分割—— deeplabv3基本思想和网络结构以及论文补充

论文链接:Rethinking Atrous Convolution for Semantic Image Segmentation

deeplabv3的引入

接着上篇DeepLab V2,本博文简单介绍下DeepLab V3(建议先去看下之前讲的DeepLab V1DeepLab V2)。这是一篇2017年发表在CVPR上的文章。
DeepLab V3相比DeepLab V2有三点变化:
1)引入了Multi-grid(多重网格)在Pytorch官方实现的DeepLab V3中,并没有使用Multi-Grid
2)改进了ASPP结构
3)把CRFs后处理给移除掉了。
在这里插入图片描述

一、DeepLabV3两种模型结构(重点区分)

文中有给出两个模型,这两个模型分别是cascaded modelASPP model,在cascaded model中是没有使用ASPP模块的,在ASPP model中是没有使用cascaded blocks模块的。注意,虽然文中提出了两种结构,但作者说ASPP model比cascaded model略好点。包括在Github上开源的一些代码,大部分也是用的ASPP model。

1.cascaded model

在这篇论文中,大部分实验基本都是围绕cascaded model来做的。如下图所示,论文中提出的cascaded model指的是图(b)。其中Block1,Block2,Block3,Block4是原始ResNet网络中的层结构,但在Block4中将第一个残差结构里的3x3卷积层以及捷径分支上的1x1卷积层步距stride由2改成了1(即不再进行下采样),并且所有残差结构里3x3的普通卷积层都换成了膨胀卷积层。Block5,Block6和Block7是额外新增的层结构,他们的结构和Block4是一模一样的,即由三个残差结构构成。
在这里插入图片描述
注意1:原论文中说在训练cascaded model时output_stride=16(即特征层相对输入图片的下采样率),但验证时使用的output_stride=8(这里论文里虽然没有细讲,但我猜应该是把Block3中的下采样取消了)。因为output_stride=16时最终得到的特征层H和W会更小,这意味着可以设置更大的batch_size并且能够加快训练速度。但特征层H和W变小会导致特征层丢失细节信息(文中说变的更“粗糙”),所以在验证时采用的output_stride=8。其实只要你GPU显存足够大,算力足够强也可以直接把output_stride设置成8。现在官方实现的代码中直接使用的就是8
原因:训练时会给我们的特征图下采样16倍,但是在验证的时候,下采样8倍。原因:下采样16倍,batch-size可以设置的更大一些,可以加速我们的训练。这个原因出现是因为当年的显存不够用,现有的设备已经不需要这么操作了,现在无论是训练还是验证都可以直接设置为8倍。

注意2:图中标注的rate并不是膨胀卷积真正采用的膨胀系数。 真正采用的膨胀系数应该是图中的rate乘上Multi-Grid参数,比如Block4中rate=2,Multi-Grid=(1, 2, 4)那么真正采用的膨胀系数是2 x (1, 2, 4)=(2, 4, 8)。关于Multi-Grid参数后面会提到。

2.ASPP model

虽然论文大篇幅的内容都在讲cascaded model以及对应的实验,但实际使用的最多的还是ASPP model,ASPP model结构如下图所示:
在这里插入图片描述注意:和cascaded model一样,原论文中说在训练时output_stride=16(即特征层相对输入图片的下采样率),但验证时使用的output_stride=8。但在Pytorch官方实现的DeepLabV3源码中就直接把output_stride设置成8进行训练的。

二、模块细节

1.ASPP

接下来分析下DeepLab V3中ASPP结构。首先回顾下上篇博文中讲的DeepLab V2中的ASPP结构,DeepLab V2中的ASPP结构其实就是通过四个并行的膨胀卷积层,每个分支上的膨胀卷积层所采用的膨胀系数不同(注意,这里的膨胀卷积层后没有跟BatchNorm并且使用了偏执Bias)。接着通过add相加的方式融合四个分支上的输出。
在这里插入图片描述
我们再来看下DeepLab V3中的ASPP结构。这里的ASPP结构有5个并行分支,分别是一个1x1的卷积层,三个3x3的膨胀卷积层,以及一个全局平均池化层(后面还跟有一个1x1的卷积层,然后通过双线性插值的方法还原回输入的W和H)。关于最后一个全局池化分支作者说是为了增加一个全局上下文信息global context information。然后通过Concat的方式将这5个分支的输出进行拼接(沿着channels方向),最后在通过一个1x1的卷积层进一步融合信息。
如果把下采样率设置为8时,我们的膨胀系数要进行翻倍处理。

2.Multi-grid

在之前的DeepLab模型中虽然一直在使用膨胀卷积,但设置的膨胀系数都比较随意。在DeepLab V3中作者有去做一些相关实验看如何设置更合理。下表是以cascaded model(ResNet101作为Backbone为例)为实验对象,研究采用不同数量的cascaded blocks模型以及cascaded blocks采用不同的Multi-Grid参数的效果。注意,刚刚在讲cascaded model时有提到,blocks中真正采用的膨胀系数应该是图中的rate乘上这里的Multi-Grid参数。通过实验发现,当采用三个额外的Block时(即额外添加Block5,Block6和Block7)将Multi-Grid设置成(1, 2, 1)效果最好。另外如果不添加任何额外Block(即没有Block5,Block6和Block7)将Multi-Grid设置成(1, 2, 4)效果最好,因为在ASPP model中是没有额外添加Block层的,后面讲ASPP model的消融实验时采用的就是Multi-Grid等于(1, 2, 4)的情况。
在这里插入图片描述

三、消融实验

1.cascaded model消融实验

下表是有关cascaded model的消融实验,其中:

MG代表Multi-Grid,刚刚在上面也有说在cascaded model中采用MG(1, 2, 1)是最好的。
OS代表output_stride,刚刚在上面也有提到过验证时将output_stride设置成8效果会更好
MS代表多尺度,和DeepLabV2中类似。不过在DeepLab V3中采用的尺度更多scales = {0.5, 0.75, 1.0, 1.25, 1.5, 1.75}。
Flip代表增加一个水平翻转后的图像输入。
在这里插入图片描述

2.ASPP model消融实验

下表是有关ASPP model的消融实验,其中:

MG代表Multi-Grid,刚刚在上面也有说在ASPP model中采用MG(1, 2, 4)是最好的。
ASPP前面讲过。
Image Pooling代表在ASPP中加入全局平均池化层分支。
OS代表output_stride,刚刚在上面也有提到过验证时将output_stride设置成8效果会更好
MS代表多尺度,和DeepLabV2中类似。不过在DeepLab V3中采用的尺度更多scales = {0.5, 0.75, 1.0, 1.25, 1.5, 1.75}。
Flip代表增加一个水平翻转后的图像输入。
COCO代表在COCO数据集上进行预训练。
在这里插入图片描述

四、训练细节

下表是原论文中给出的关于DeepLab V3在Pascal VOC2012测试数据集上的meanIOU。
在这里插入图片描述
通过对比发现,其实DeepLab V3和V2比起来提升了大约6个点。但这里的DeepLab V3貌似并没有明确指出具体是cascaded model还是ASPP model,个人觉得大概率是指的ASPP model。然后仔细想想这6个点到底是怎么提升的,如果仅通过引入Multi-Grid,改进ASPP模块以及在MSC中使用更多的尺度应该不会提升这么多个点。所以我能想到的就是在训练过程中的某些改动导致meanIOU提升了。有兴趣可以看下论文中A. Effect of hyper-parameters部分,其中作者有说:

1.在训练过程中增大了训练输入图片的尺寸(论文中有个观点大家需要注意下,即采用大的膨胀系数时,输入的图像尺寸不能太小,否则3x3的膨胀卷积可能退化成1x1的普通卷积。
2.计算损失时,是将预测的结果通过上采样还原回原尺度后(即网络最后的双线性插值上采样8倍)在和真实标签图像计算损失。而之前在V1和V2中是将真实标签图像下采用8倍然后和没有进行上采样的预测结果计算损失(当时这么做的目的是为了加快训练)。根据Table 8中的实验可以提升一个多点。
3.训练后,冻结bn层的参数然后在fine-turn下网络,根据Table 8中的实验可以提升一个多点。

五、Pytorch官方实现DeepLab V3模型结构

下图是我根据Pytorch官方实现的DeepLab V3源码绘制的网络结构(与原论文有些许差异):

1.在Pytorch官方实现的DeepLab V3中,并没有使用Multi-Grid,有兴趣的同学可以自己动手加上试试。
2.在Pytorch官方实现的DeepLab V3中多了一个FCNHead辅助训练分支,可以选择不使用。
3.在Pytorch官方实现的DeepLab V3中无论是训练还是验证output_stride都使用的8。
4.ASPP中三个膨胀卷积分支的膨胀系数是12,24,36,因为论文中说当output_stride=8时膨胀系数要翻倍。
在这里插入图片描述

六、论文细节

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
DeepLabv3+是Google于2018年提出的图像语义分割算法,它是基于DeepLabv3的改进版,主要针对于语义分割中存在的细节和边缘信息不够准确的问题进行了改进。相比于DeepLabv3DeepLabv3+在特征融合和上采样方面进行了优化,使得分割结果更加精确。 DeepLabv3+的网络结构主要由三个部分组成:骨干网络、ASPP(Atrous Spatial Pyramid Pooling)模块和Decoder模块。 骨干网络使用的是Xception模型,它是一种深度可分离卷积的扩展版本,能够更好地提取图像特征。ASPP模块通过使用不同的采样率对特征图进行空间金字塔池化,能够有效地捕捉不同尺度的特征。Decoder模块主要通过上采样和跨层连接来恢复分辨率和细节信息。 以下是使用Python和Tensorflow2.0实现的DeepLabv3+图像分割代码: ```python import tensorflow as tf from tensorflow.keras import layers # 定义ASPP模块 def ASPP(inputs, output_stride): # 定义空洞卷积的采样率 rates = [1, 6, 12, 18] # 使用不同的采样率对特征图进行空间金字塔池化 branches = [] for rate in rates: branch = layers.Conv2D(256, 3, padding='same', dilation_rate=rate, activation='relu')(inputs) branches.append(branch) # 使用全局池化对特征图进行降维 x = layers.GlobalAveragePooling2D()(inputs) x = layers.Reshape((1, 1, 2048))(x) x = layers.Conv2D(256, 1, padding='same', activation='relu')(x) x = layers.UpSampling2D(size=(output_stride // 4, output_stride // 4), interpolation='bilinear')(x) # 将ASPP分支和全局池化的结果进行拼接 x = layers.concatenate([x] + branches, axis=3) x = layers.Conv2D(256, 1, padding='same', activation='relu')(x) x = layers.Dropout(0.5)(x) return x # 定义Decoder模块 def Decoder(inputs, skip_connection): # 使用跨层连接将浅层特征图与深层特征图进行融合 x = layers.Conv2D(48, 1, padding='same', activation='relu')(inputs) x = layers.UpSampling2D(size=(4, 4), interpolation='bilinear')(x) x = layers.concatenate([x, skip_connection], axis=3) x = layers.Conv2D(256, 3, padding='same', activation='relu')(x) x = layers.Dropout(0.5)(x) x = layers.Conv2D(256, 3, padding='same', activation='relu')(x) x = layers.Dropout(0.1)(x) return x # 定义DeepLabv3+模型 def DeepLabv3Plus(input_shape, num_classes, output_stride): # 定义输入层 inputs = layers.Input(shape=input_shape) # 定义骨干网络 x = layers.Conv2D(32, 3, strides=2, padding='same', activation='relu')(inputs) x = layers.Conv2D(64, 3, padding='same', activation='relu')(x) x = layers.Conv2D(64, 3, strides=2, padding='same', activation='relu')(x) x = layers.Conv2D(128, 3, padding='same', activation='relu')(x) x = layers.Conv2D(128, 3, strides=2, padding='same', activation='relu')(x) x = layers.Conv2D(256, 3, padding='same', activation='relu')(x) x = layers.Conv2D(256, 3, padding='same', activation='relu')(x) skip_connection = x # 定义ASPP模块 x = ASPP(x, output_stride) # 定义Decoder模块 x = Decoder(x, skip_connection) # 使用双线性插值对特征图进行上采样 x = layers.UpSampling2D(size=(output_stride // 4, output_stride // 4), interpolation='bilinear')(x) # 输出层 x = layers.Conv2D(num_classes, 1, padding='same')(x) outputs = layers.Activation('softmax')(x) # 定义模型 model = tf.keras.Model(inputs=inputs, outputs=outputs) return model # 定义输入参数 input_shape = (512, 512, 3) num_classes = 21 output_stride = 16 # 构建DeepLabv3+模型 model = DeepLabv3Plus(input_shape, num_classes, output_stride) # 输出模型的结构信息 model.summary() ``` 在上述代码中,我们首先定义了ASPP模块和Decoder模块,然后通过这两个模块构建了DeepLabv3+模型。最后使用输入参数调用DeepLabv3Plus函数,即可得到完整的DeepLabv3+模型。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jul7_LYY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值