这是ICCV2019的用于语义分割的论文,可以说和CVPR2019的DANet遥相呼应。关于DANet可以见我的另一篇博客
官方源码
idea
和DANet一样,CCNet也是想建模像素之间的long range dependencies,来做更加丰富的contextual information,来补充特征图,以此来提升语义分割的性能。但是和DANet不一样,CCNet仅考虑空间分辨上的建模,不考虑建模通道之间的联系。作者提出的模块,criss-cross attention module,针对空间维度上的建模,对于空间位置的一个点u,仅考虑建模和u在同一行或者同一列的其他位置的像素之间的联系。相比DANet,能减少很多计算量,但是不足的是,对一个点的特征向量,尽管有同一行或者同一列的其他像素信息作为补充,对于语义分割任务,contextual information仍然是稀疏的(sparse),因为语义分割更在意一个像素和它周围的一些像素的关系。针对这个问题,作者提出了recurrent criss-cross attention module,来建模一个像素和全局所有像素的关系。方式是通过重复criss-cross attention module来实现的。这些module也是参数shared的。
main contribution
- 同样是建模空间维度的pixel-wise contextual information,CCNet的计算量相较于self attention,可小太多了。一个CC module,要处理的是一个像素点和同一行、同一列一共(H+W-1)这么多的像素,那么应用在所有像素上,计算量就是O(HW(H+W-1))。回顾DANet的空间注意力分支(position attention module),每一个像素就要和(HW)个像素建模之间的联系,应用在所有相素,计算量就是O(HW*(H*W))。
- 通过递归的方式用CC module,可以对一个像素捕捉到全局的contextual information,提到了语义分割任务的效果。
个人看法,简单且有效的,就是极其优秀的方法,CCNet就属于这一类方法。
Method
OverView
整个网络的管道如上图所示
- 首先一个原图送进backbone,这个backbone是修改过的,把最后两个stage的stride改为1,同时应用空洞卷积来增大感受野。得到的特征图是原图的1/8.
- 然后经过1*1的卷积降维。得到H。
- H经过一个criss-cross attention module 得到H′H'H′,这个时候,H’中的每个位置都捕捉到了和u在同一行或者同一列的context information
- H’经过一个相同结构、相同参数的cc module,得到了H’’。在H‘’中的每个位置,捕捉的是全局性的contextual information
- 最后经过一个分割层输出最后的预测结果。
criss-cross attention module
关于模块结构的介绍,重点应该在Affinity和Aggregation这里。H的维度是RC×H×WR^{C\times H\times W}RC×H×W
- Q和K,都是RC′×H×WR^{C' \times H\times W}RC′×H×W,C′<CC' < CC′<C
- V 是RC×H×WR^{C\times H\times W}RC×H×W
Affinity操作
在Q上的一点u,记作Qu∈Rc′Q_u \in R^{c'}Qu?∈Rc′,绿色的位置和青色的位置,都是和u在同一行或者同一列的单元。
在K中的相同位置上,把和u在同一行或同一列的所以单元加入到集合Ωu\Omega_uΩu?,那么集合Ωu\Omega_uΩu?中有H+W-1个长度为C’的向量。
Affinity定义如下:
di,u=QuΩi,uTd_{i,u} = Q_u \Omega_{i,u}^Tdi,u?=Qu?Ωi,uT?
就是向量的点积运算,得到标量。i从1到H+W-1变化。则对于一个位置u,能得到H+W-1个值。则所有的一共HW个位置。就有(HW*(H+W-1))个值,形成D,将D按照channel维度进行softmax,就得到了A(attention map)。
Aggregation 操作
从V中的位置u,取出Vu∈RcV_u \in R^cVu?∈Rc,同时得到集合Φu\Phi_uΦu?,这个集合是包含了在V中的位置u,和u同一行或者同一列的其他单元的特征。也就是说,Φu\Phi_uΦu?中有(H+W-1)个长度为C的向量。
Hu′=∑i∈∣Φu∣Ai,uΦi,u+HuH'_u = \sum_{i \in |\Phi_u|} A_{i,u} \Phi_{i,u} + H_uHu′?=i∈∣Φu?∣∑?Ai,u?Φi,u?+Hu?
Ai,uA_{i,u}Ai,u?是标量,是A中的位置u对应的特征向量中,第i个值。
Φi,u\Phi_{i,u}Φi,u?是集合Φu\Phi_uΦu?中第i和特征向量。
这个操作可以用下图简单表示:
最后一项,对应了结构图中的最上面的线,即skip connection。
recurrent criss-cross attention
看看这个recurrent 被使用的用意
作者认为,仅考虑同一行和同一列像素关系的建模,对于语义分割仍然是sparse的。于是作者提出了用递归的方式,使用CC module,且Module之间是参数共享的。使用两个CC module,就能针对一个像素点,建模它和全部像素点的联系。
方式就是:
- H经过一个CC module 得到 H’
- H’ 经过一个CC module 得到H’’
- H’'就包含了全局的contextual information,是dense的。
那为啥,递归使用两个CC module,就可以达成这样的效果呢?
假如在平面坐标系中,蓝色点要带着自己的信息去绿色点那里,且规定走的路线只能直行,即只能上下左右走。蓝色点到达目的地,最少需要几步?
答案是两步。CCNet也是利用了这个思想。
H’'虽然不能直接获得H中的全部像素点信息,但却通过间接的方式获取了。比如说,上图左下角绿色的块想获得蓝色块的信息,在第一个CC module中,蓝色块的信息被add到左上方和右下方的块中了,在第2个CC module中,左上方的块和右下方的块被add到绿色块中了。哈哈哈
觉得博主解读好的,请留个言嘛。 实验数据就不多介绍了。