原文阅读地址
三遍阅读法
这篇文章主要讨论了上下文先验在场景分割的应用,发表于CVPR2020。
a) 受到嵌入在Context Prior Layer中的Affinity Loss监督,构建的Context Prior能够捕捉类内(intra-class)和类间(inter-class)的上下文相关性;< 我的理解:类内就是同一类的意思,类间就是不同类的意思>
b) 为了验证提出的Context,构建了一个网络Context Prior Network(CPNet),其包含了一个Backbone和一个Context Prior Layer;
c) 在一些基准上成为了SOTA(ADE20K,Pascal-Context,Cityscapes)
这些探索上下文依赖的分割方法可以分为两类:基于金字塔的聚合方法(Pyramid-based aggregation method)和基于注意力的聚合方法(Attention-based aggregation method) 第一种方法用到金字塔模块或者全局池化层来聚合局部和全局上下文信息,虽然捕获了同类的上下文信息,但是却忽略了不同类的依赖关系,如上图b所示,当这个场景中存在一些复杂类别,这个方法导致上下文变得不可靠。第二种方法,有用来学习channel-attention,spatial attention或者point-wise attention来有选择聚合多样的上下文信息,但由于缺乏显式正则化手段,这些attention机制的关系描述不够清楚,可能会选择一些完全不需要的上下文关系,如上图e。这两种方法都在没有明确区分的情况下,融合了上下文信息,这将会导致不同上下文关系的混乱。
所以,作者在这篇文章中对类别中的上下文关系进行建模作为先验知识,从而获得更精准的结果。主要有这几个关键点:Context Prior, Context Prior Layer, Affinity Loss,Aggregation Module, Context Prior Network(CPNet)。
为了去解决这些问题,在这篇文章中,先提出一个Context Prior去对相同类(intra-context)的像素与不同类(inter-context)的像素之间的关系进行建模。基于Context Prior,提出了Context Prior Network,它包含了受Affinity Loss监督的Context Prior Layer。
为了去明确规范这个网络去学习类别之间的关系,我们引入了Affinity Loss。对于图像上的每一个像素,Affinity Loss将会迫使网络去考虑在同一类别的像素和不同类别的像素。
只要给定输入的groundtruth,我们就可以知道每一个像素的‘Context Prior’(哪些属于同一类,哪些属于不同类),可以学习Context Prior去引导整个网络。首先根据ground truth建立Ideal Affinity Map作为监督:给定输入图像 I 和其对应的groundtruth L,将 I 送入网络中可以得到一个大小为HxW的特征图X。像上图一样,我们先将L下采样到与X大小相同,得到一个更小的groundtruth L~ 。我们使用了one-hot编码去对L~ 中的类别标签进行编码,得到一个大小为HxWxC的矩阵L^^,C为类别数。紧接着,将L~^ Reshape成NxC大小,N=HxW。最后,我们进行一个矩阵乘法:A = L~ L~T ,这个A就是我们期望的Ideal Affinity Map,大小为NxN。 我们使用Ideal Affinity Map去监督Context Prior Map的生成。
对于prior map中的每一个像素,其实是一个二分类问题。通常解决二分类问题用到的是二元交叉熵损失:
其中,{pn ∈ P,n ∈ [1, N2]},P为预测得到的Prior MAP,{an ∈ A,n ∈ [1, N2]},A为期望得到的Ideal Affinity MAP。
但它只考虑了在Prior Map中的单个像素,忽略了与其他像素的语义联系,我们可以看到在P(A)中的每一行其实都对应着feature map X中的每个像素,可以它们表示为同类像素或者不同类像素(有点邻接矩阵的意思),这个关系是有助于推理语义相关性和场景结构的。因此,我们考虑把同类像素和不同类像素作为两个部分来对关系分别编码:
其中,(2)(3)(4)分别表示P中第j行的同类准确率(precision),同类召回率(recall),特异度(specificity)。
最后,完整的Affinity Loss定义如下:
其中,λu 和 λg 用于平衡一元损失(unary loss)和全局损失(global loss),根据经验,通常都是直接设为1。
如上图,Context Prior Layer得到一个输入特征X,形状为HxWxC0。我们使用聚合模块(aggregation module)将X变为X~,形状为HxWxC1。得到 X~ 之后,进行1x1卷积+ BN + Sigmoid,形状变为HxWxN(N=HxW)去学习一个先验图 P。 在Affinity Loss的明确监督下,Context Prior Map P可以对类内(intra-class)像素和类间像素(inter-class)之间的关系进行编码。
最后,我们将原始特征和两种上下文Concat去输出最终的预测F = Concat(X, Y, Y_),有了这两种上下文,就可以推测每个像素的语义相关性和场景结构。
Context Prior Map需要一些局部空间信息去推理语义相关性,一般来说要聚合更多的空间信息就要使用更大的卷积核,但是计算代价是很大的。因此,作者用全分离卷积(fully separable convolution)设计了一个有效的Aggregation Module去聚合空间信息。
我们将一个普通卷积分解成两个在空间上不对称的卷积,比如一个kxk的卷积,我们这样来替代:先使用一个kx1卷积,接着再使用一个1xk卷积,我们称为空间可分离卷积(spatial separable convolution),并且每个空间卷积都采用深度都采用深度卷积(depth-wise convolution),这导致计算量大大减少。由于考虑了空间和深度两个维度,作者把这种方式称为Fully Separable Convolution。
Context Prior Network(CPNet)是一个全卷积网络,由Backbone和一个Context Prior Layer组成。Backbone是一个用了空洞卷积(dilation strategy)的现成网络。同时,在backbone网络的阶段4(stage 4)还使用了辅助损失(auxiliary loss),也是一个交叉熵损失。最终的损失函数为:
其中Ls, La, Lp 分别代表主要分割损失(main segmentation loss),辅助损失(auxiliary loss)以及Affinity Loss,λs, λa, λp 是用来平衡loss的权重。经验性地设置为:λs=1, λa=1, λp=0.4。
poly
训练策略。
Table 1 为消融实验。
为了证明Context Prior的有效性以及泛化能力,做了Table2 和Table3中的实验。
在CPNet网络中Prior Map的可视化,证明Context Prior Layer中的Prior Map可以学习到明确的结构信息。
这个文章想法很不错,特别是在Context Prior的设计与监督方式上的构思都比较完善。
以往人们在设计分割模型时,很多时候想着是尽可能地捕获更多、更丰富的特征信息(例如金字塔池化),这个固然能提高模型的准确率,但是往往忽略了这样组合起来的特征可能是混乱的、不考虑类别之间的上下文依赖关系的。而这篇文章,以这个角度为切入点,所以能在兵荒马乱的CVPR2020投稿中脱颖而出。
再次回顾这篇文章的亮点之处,除了Context Prior,还有Aggregation Module。从Aggregation Module可以看到,目前除了3x3的卷积之外,如果需要增大感受野,不再是扩大卷积核大小和增加卷积层数这种耗费计算资源的操作了,而是使用spatial separable convolution,并且还使用了depth-wise convolution。所以,我们在设计网络时,要尽可能地考虑计算成本。
非要说些不足的话,以我的愚见,就是Prior Map的利用还是不够,尽管作者尽可能想多利用一些Prior Map的信息,从而用到了(1-P)来得到一个reversed map,但是后面只是与原本的特征简单Concat,总是有种很奇怪的感觉。不过深度学习领域目前还是实验主导性,只要你的model提升了几个点,哪怕你的模型可解释性很差,但是只要你自圆其说,就问题不大。
https://github.com/ycszen/ContextPrior
以上为个人的浅见,水平有限,如有不对,望大佬们指点。
未经本人同意,请勿转载,谢谢。