本文为DeepLab系列论文阅读笔记,包括DeepLabV1、DeepLabV2、DeepLabV3、DeepLabV3+。
目录
一、DeepLabV1
网络结构
二、DeepLabV2
ASPP
学习率策略
三、DeepLabV3
DeepLabV3的变化
网络结构
四、DeepLabV3+
模型设计
深度可分离卷积
参考
论文:Semantic Image Segmentation with Deep Convolutional Nets and Fully Connected CRFs
DeepLabV1结合了DCNN(deep convolutional neural network)和概率图模型来完成语义分割任务。
DCNN在语义分割任务中有2个问题:
1、下采样导致信息丢失
2、CNN的空间不变性(图片的旋转平移不影响图片的分类结果,说明CNN对边缘信息不敏感,难以捕获细节信息)
文中提出的解决方案:
1、空洞卷积:为了获得较大的感受野,常用的方法就是通过池化或者带步长的卷积来降低特征图的分辨率,但是特征图的分辨率降低会导致信息丢失。为了防止信息丢失,需要一种不降低特征图分辨率获得大的感受野的方法,使用空洞卷积来增加感受野。
2、对于CNN的空间不变性导致的语义分割边缘分割不准确的问题,使用CRF(Conditional Random Field)对DCNN的分割结果进行修正。(DeepLabV3后弃用CRF,本文将不过多关注)
使用VGG16网络并进行修改,使其完成语义分割任务。把第四第五个maxpool步长变为1(输出的特征图分辨率1/8),stage 5的所有卷积层和第五层maxpool后的第一个卷积层使用空洞卷积。
卷积核大小:在滤波器中插入0是的增加滤波器长度,stage5的滤波器变为原来的2倍,第五层maxpool后的卷积层变为4倍。
网络的输出上采样8倍得到输出。
论文:DeepLab: Semantic Image Segmentation with Deep Convolutional Nets, Atrous Convolution, and Fully Connected CRFs
DeepLabV2主要有3个贡献:
1、强调了空洞卷积在密集预测任务中的作用,它可以在不增加参数的同时有效地增加感受野;
2、提出了ASPP(Atrous spatial pyramid pooling),多尺度特征提取,可以有效地提取多尺度的图像语义信息;
3、全连接CRF对图像分割结果的边缘修正。
在语义分割任务中存在3个挑战:
1、DCNN中为了增加感受野,使用了maxpool和downsampling,从而导致特征图分辨率下降,会丢失语义信息;
2、多尺度的目标分割,为了分割不同大小的目标,常用方法是将图片缩放到不同大小,得到不同尺度的score map后再融合,但是该方法计算成本高;
3、CNN的空间不变性,导致物体的边缘信息丢失,边缘分割效果差;
文中提出了对应的解决方案:
1、使用空洞卷积,增加感受野;
2、提出ASPP模块,使用不同大小的空洞卷积以获取不同大小的物体的语义信息;
3、使用CRF(Conditional Random Field)对DCNN的分割结果进行修正。
ASPP模块如图所示,卷积核采用不同的空洞大小,来增加感受野的同时,能够捕获不同大小的目标的语义信息。
deeplabv2使用了学习率多项式衰减策略,power=0.9
论文:Rethinking Atrous Convolution for Semantic Image Segmentation
在语义分割任务中存在2个挑战:
1、卷积神经网络模型常常使用连续的池化或者带步长的卷积来减少特征图的分辨率,从而得到高级的抽象特征表示,但是这样会损失图像的低级信息(例如边界)。通常的处理方法是减少下采样(maxpool和带步长的卷积),保留空间细节信息,同时使用空洞卷积来增加感受野;
2、多尺度的目标分割,现有的处理方法如下:
a:Image Pyramid,将输入图像resize成不同的大小,送入网络得到分割结果后对分割结果进行融合;
b:Encoder-Decoder,encoder提取多尺度的特征,decoder对不同尺度的特征融合,解码器解码时可以从不同分辨率的特征图中复原空间细节信息;
c:Context Module,在模型加入额外模块对长距离上下文进行编码(如空洞卷积);
d:Spatial pyramid pooling,通过不同步长的池化,可以得到不同感受野的特征图,因此捕捉到不同尺度的目标。
output_stride:输出分辨率和输入分辨率的比率,out_stride=16表示输出特征图是输入特征图的1/16。
1、Multi-grid
连续下采样对语义分割任务是有害的,为了不下采样同时增加感受野,使用空洞卷积来增加感受野,空洞卷积的策略是Multi-grid,以下图为例介绍该策略,下图中block5、block6、block7的模型结构和block4相同。
以resnet50为例,介绍multi-grid策略,首先下图给出resnet50 block4的结构(红框部分),红框中的中括号为BottleneckBlock(瓶颈块),block4包含3个瓶颈块,当multi_grid=(1,2,4)时,BottleneckBlock1的3X3卷积的dilation为rate*multi_grid[1],即dilation=2*1=2;对应的BottleneckBlock2的3X3卷积的dilation=2*2=4,BottleneckBlock3的3X3卷积的dilation=2*4=8。
2、在ASPP模块中加入BatchNormalization
3、引入全局池化添加全局上下文信息
为什么要引入全局池化呢?
在65x65的特征图上使用不同空洞率的3x3卷积,当卷积核和特征图一样大时,3x3卷积会退化成1x1的卷积,只有中间的权重有效,从而无法捕获图片上下文信息,所以引入了全局池化来捕获全局上下文信息。
模型的网络结构如下图所示,output_stride=16时,block4的rate=2,当output_stride=8时,block3的rate=2,block4的rate=4。ASPP模块加入了image pooling,该部分的组成为[averate pooling > conv1x1 > BN > relu > interpolate]。
下面给出torchvision的ASPP源代码:
class ASPPConv(nn.Sequential):
def __init__(self, in_channels: int, out_channels: int, dilation: int) -> None:
modules = [
nn.Conv2d(in_channels, out_channels, 3, padding=dilation, dilation=dilation, bias=False),
nn.BatchNorm2d(out_channels),
nn.ReLU(),
]
super().__init__(*modules)
class ASPPPooling(nn.Sequential):
def __init__(self, in_channels: int, out_channels: int) -> None:
super().__init__(
nn.AdaptiveAvgPool2d(1),
nn.Conv2d(in_channels, out_channels, 1, bias=False),
nn.BatchNorm2d(out_channels),
nn.ReLU(),
)
def forward(self, x: torch.Tensor) -> torch.Tensor:
size = x.shape[-2:]
for mod in self:
x = mod(x)
return F.interpolate(x, size=size, mode="bilinear", align_corners=False)
class ASPP(nn.Module):
def __init__(self, in_channels: int, atrous_rates: List[int], out_channels: int = 256) -> None:
super().__init__()
modules = []
modules.append(
nn.Sequential(nn.Conv2d(in_channels, out_channels, 1, bias=False), nn.BatchNorm2d(out_channels), nn.ReLU())
)
rates = tuple(atrous_rates)
for rate in rates:
modules.append(ASPPConv(in_channels, out_channels, rate))
modules.append(ASPPPooling(in_channels, out_channels))
self.convs = nn.ModuleList(modules)
self.project = nn.Sequential(
nn.Conv2d(len(self.convs) * out_channels, out_channels, 1, bias=False),
nn.BatchNorm2d(out_channels),
nn.ReLU(),
nn.Dropout(0.5),
)
def forward(self, x: torch.Tensor) -> torch.Tensor:
_res = []
for conv in self.convs:
_res.append(conv(x))
res = torch.cat(_res, dim=1)
return self.project(res)
论文:Encoder-Decoder with Atrous Separable Convolution for Semantic Image Segmentation
DeepLabV3+在DeepLabV3的基础上添加了一个简单有效的解码器模块来修正分割结果,对目标边界的修正效果更好。DeepLabV3+将深度可分离卷积应用到ASPP模块和解码器模块来提升运算速度。
如下图所示,a为DeepLabV3的模型结构,b为常用的编码解码器结构,将DeepLabV3作为编码器,并结合Encoder-Decoder结构,就是DeepLabV3+。
下图为DeepLabV3+的模型结构,Encoder为DeepLabV3。(图中的output_stride=16,如果output_stride=8,需要修改上采样比率)
对于普通的卷积,如果使用3x3的核,输入通道为in_channels,输出通道为out_channels,那么卷积核为[out_channels, in_channels, 3, 3],参数个数为3*3*in_channels*out_channels(忽略bias)。为了减少参数,可以把卷积分离为Depthwise conv 和 Pointwise conv。
Depthwise conv:假设输入为[N, in_channels, H, W],Depthwise使用C个3x3的卷积核分别对每层进行单独卷积,输出为[N, in_channels, H, W],参数为3x3xC
Pointwise conv:经过Depthwise conv得到[N, in_channels, H, W]的特征图,使用[out_channels, in_channels, 1, 1]的卷积核进行卷积,得到[N, out_channels, H, W]的输出,参数个数为:out_channels * in_channels。
那么深度可分离卷积核普通卷积的参数比为:
可以看出,参数量大大减少。
DeepLab V3
https: //github.com/tensorflow/models/tree/master/research/deeplab