原始文档 https://www.yuque.com/lart/papers/onk4snpython
在本文中,咱们经过 基于自我约束机制捕获丰富的上下文依赖关系来解决场景分割任务。
与以前经过多尺度特征融合捕获上下文的工做不一样,咱们提出了一种双重注意网络(DANet)来自适应地集成局部特征及其全局依赖性。
具体来讲,咱们在传统的扩张FCN之上附加两种类型的注意力模块,它们分别对空间和通道维度中的语义相互依赖性进行建模。git
咱们将两个注意模块的输出相加以进一步改进特征表示,这有助于更精确的分割结果。github
场景分割是一个基本且具备挑战性的问题,其目标是将场景图像分割和解析到与语义类别相关联的不一样图像区域,包括填充物(例如天空,道路,草地)和离散物体(例如人,汽车,自行车)。 该任务的研究可应用于潜在的应用,例如自动驾驶,机器人传感和图像编辑。 为了有效地完成场景分割任务,咱们须要区分一些使人困惑的类别,并将不一样外观的对象分解。 例如,“田地”和“草地”的区域一般是难以区分的,而且一般难以区分的“汽车”可能具备不一样的尺度,遮挡和照明。 所以,有必要提升像素级识别特征表示的辨别能力。网络
最近,已经提出了基于彻底卷积网络(FCN)的最早进方法来解决上述问题。app
虽然上下文融合有助于捕获不一样比例的对象,但它没法利用全局视图中对象或东西之间的关系,这对于场景分割也是必不可少的。框架
另外一种类型的方法使用递归神经网络来利用长程依赖性,从而提升分割精度。提出了基于2DLSTM网络的方法来捕获标签上复杂的空间依赖性。工做[DAGRNN]使用有向无环图构建一个递归神经网络,以捕获局部特征上丰富的上下文依赖性。然而,这些方法使用递归神经网络隐含地捕捉全局关系,其有效性在很大程度上依赖于长期记忆的学习结果。dom
为了解决上述问题,在本文中,咱们提出了一种新的框架,称为双注意网络(DANet),用于天然场景图像分割,如图所示。它引入了一种自注意力机制来分别捕捉空间和通道尺寸中的视觉特征依赖性。学习
具体来讲,咱们在传统的_扩张FCN_之上添加了两个并行的注意模块。一个是位置注意力模块(position attention module),另外一个是通道注意模块(channel attention module)。测试
最后,这两个注意模块的输出被融合以进一步加强特征表示。编码
值得注意的是,在处理复杂多样的场景时,咱们的方法比之前的方法[Rethinking atrous convolution for semantic image segmentation, PSPNet]更有效,更灵活。走图中的街景。以图1为例。
咱们的主要贡献可概括以下:
除了第一步以外,捕获通道关系的过程相似于位置注意力模块,其中在通道维度中计算通道注意力矩阵。最后,咱们汇总了两个注意模块的输出特征,以得到更好的像素级预测特征表示。
对于场景理解, 判别特征表示是必不可少的,能够经过捕获远程上下文信息来得到。然而,许多做品代表传统FCN产生的局部特征表示可能致使objects和stuff的错误分类。
为了在局部特征表示之上建模丰富的上下文关系,咱们引入了一个位置注意力模块。位置注意力模块将更普遍的上下文信息编码到局部特征中,从而加强其表示能力。
如图:
这样一来, 每一个算出来的特征E的每一个位置都是来自全部位置的特征和原始特征的加权和. 所以能够得到一个全局的上下文信息, 而且能够根据空间注意力图来有选择的集成上下文信息. 类似的特征会互相得到增益, 所以能够提高类间对比度和语义一致性.
利用矩阵乘法来实现对于全局上下文信息的利用与融合, 实际上和全链接是同样的. 全链接确实能够更为全面的利用全部位置的信息, 可是会破坏空间结构, 这也是相互矛盾的, 因此, 不能彻底的利用全链接. 还得想办法保留更多的空间结构信息. 这里使用这个全链接的结果用在原始数据信息上, 互相利用, 互相促进.
高级特征的每一个通道映射能够被从新看做特定于类的响应,而且不一样的语义响应彼此相关联。经过利用通道映射之间的相互依赖关系,咱们能够强调相互依赖的特征映射,并改进特定语义的特征表示。所以,咱们创建了一个通道注意力模块, 以显式的建模通道之间的相互依赖性。
结构以下:
公式4显示 每一个通道的最终特征是全部通道和原始特征的特征的加权数据,其建模特征映射之间的远程语义依赖性。它 强调依赖于类的特征映射并有助于提升特征可辨性。
咱们在计算两个通道的关系以前,咱们不使用卷积层来嵌入特征,由于能够维持不一样通道映射之间的关系。此外,与最近经过全局池化或者编码层探索通道关系的工做[26]不一样,咱们利用全部相应位置的空间信息来建通道相关性。
为了充分利用远程上下文信息的优点, 咱们集成来自两个注意力模块的特征. 特别地, 咱们经过一个卷积层和元素级加法来聚合两个注意力模块的输出, 以实现特征融合.
在最后紧跟着一个用来生成最终预测图的卷积层. 咱们不采用级联操做, 由于它须要更多的 GPU 内存.
注意到咱们的注意力模块很简单, 能够直接插入现有的 FCN流程中。 它们不会增长太多的参数, 却又能有效地加强特征表示。
# https://github.com/junfu1115/DANet/blob/master/encoding/nn/attention.py ########################################################################### # Created by: CASIA IVA # Email: jliu@nlpr.ia.ac.cn # Copyright (c) 2018 ########################################################################### import numpy as np import torch import math from torch.nn import (Module, Sequential, Conv2d, ReLU, AdaptiveMaxPool2d, AdaptiveAvgPool2d, NLLLoss, BCELoss, CrossEntropyLoss, AvgPool2d, MaxPool2d, Parameter, Linear, Sigmoid, Softmax, Dropout, Embedding) from torch.nn import functional as F from torch.autograd import Variable class PAM_Module(Module): """ Position attention module""" # Ref from SAGAN def __init__(self, in_dim): super(PAM_Module, self).__init__() self.query_conv = Conv2d(in_channels=in_dim, out_channels=in_dim // 8, kernel_size=1) self.key_conv = Conv2d(in_channels=in_dim, out_channels=in_dim // 8, kernel_size=1) self.value_conv = Conv2d(in_channels=in_dim, out_channels=in_dim, kernel_size=1) self.gamma = Parameter(torch.zeros(1)) self.softmax = Softmax(dim=-1) def forward(self, x): """ inputs : x : input feature maps( N X C X H X W) returns : out : attention value + input feature attention: N X (HxW) X (HxW) """ m_batchsize, C, height, width = x.size() # B => N, C, HW proj_query = self.query_conv(x).view(m_batchsize, -1, width * height) # B' => N, HW, C proj_query = proj_query.permute(0, 2, 1) # C => N, C, HW proj_key = self.key_conv(x).view(m_batchsize, -1, width * height) # B'xC => N, HW, HW energy = torch.bmm(proj_query, proj_key) # S = softmax(B'xC) => N, HW, HW attention = self.softmax(energy) # D => N, C, HW proj_value = self.value_conv(x).view(m_batchsize, -1, width * height) # DxS' => N, C, HW out = torch.bmm(proj_value, attention.permute(0, 2, 1)) # N, C, H, W out = out.view(m_batchsize, C, height, width) out = self.gamma * out + x return out class CAM_Module(Module): """ Channel attention module""" def __init__(self): super(CAM_Module, self).__init__() self.gamma = Parameter(torch.zeros(1)) self.softmax = Softmax(dim=-1) def forward(self, x): """ inputs : x : input feature maps( N X C X H X W) returns : out : attention value + input feature attention: N X C X C """ m_batchsize, C, height, width = x.size() proj_query = x.view(m_batchsize, C, -1) proj_key = x.view(m_batchsize, C, -1).permute(0, 2, 1) # N, C, C, bmm 批次矩阵乘法 energy = torch.bmm(proj_query, proj_key) # 这里实现了softmax用最后一维的最大值减去了原始数据, 得到了一个不是太大的值 # 沿着最后一维的C选择最大值, keepdim保证输出和输入形状一致, 除了指定的dim维度大小为1 energy_new = torch.max(energy, -1, keepdim=True) energy_new = energy_new[0].expand_as(energy) # 复制的形式扩展到energy的尺寸 energy_new = energy_new - energy attention = self.softmax(energy_new) proj_value = x.view(m_batchsize, C, -1) out = torch.bmm(attention, proj_value) out = out.view(m_batchsize, C, height, width) out = self.gamma * out + x return out if __name__ == '__main__': module = CAM_Module() in_data = torch.randint(0, 255, (2, 3, 7, 7), dtype=torch.float32) print(module(in_data).size())
位置注意力模块的效果在图4中可视化, 一些细节和对象边界在使用位置注意力模块时更加清晰, 例如第一行中的 "杆子" 和第三行的 "人行道"。对局部特征的选择性融合加强了对细节的区分。
同时, 图5证实, 利用咱们的信道注意模块, 一些错误分类的类别如今被正确地分类, 如第一行和第三行中的 "公交车"。 通道映射之间的选择性集成有助于捕获上下文信息。 语义一致性获得了明显的改善。
Following [Rethinking atrous convolution for semantic image segmentation], we adopt the same strategies to improve peformance further.