——NeoZng [neozng1@hnu.edu.cn]
如果觉得笔者写得还不错,给个关注点个赞吧!
全网最强的CV注意力机制总结
注意力机制最早被使用在机器翻译(或自然语言处理)上中的Encoder-Decoder模型上,让网络在处理不同部分语句时能够聚焦到特定的已经编码的语义向量或输入上。
若想要理解上述注意力机制的来源,请学习和NLP和RNN相关的知识:吴恩达深度学习-序列模型,这是因为在计算机视觉中的注意力和机器翻译可以从不同角度理解。尤其是自注意力机制,强烈推荐李宏毅老师的讲解:李宏毅机器学习课程-self attention
在阅读空间域的QKV模型时,务必先掌握自注意力模型。
而在计算机视觉中,我们不大需要用Query/Key/Value的模型来解释,笔者更倾向于使用特征分解这个词,从特征空间的角度解析cv中的注意力机制。用于计算机视觉的注意力机制一般分为三种:通道域、空间域和混合域。其原理是赋予空间中不同通道或区域以不同的权重,而不是像以往一样进行卷积/池化操作时将空间中的一个位置(空间中的一个位置,对应所有CxWxH中长度为C的狭长的一列)或所有通道视为拥有一样的权重,从而使得网络专注与更重要的信息的提取。
这里会有一个误区,很多同学会认为,网络在训练的时候,只要往正确的方向迭代,不就自然会赋予卷积核中的参数以不同的值,这样难道不会在通道域或空间域产生不同的权重吗?为什么还需要注意力机制?
这里需要特别注意,卷积核上的不同权重参数是定域的,即其只能在其感受野内形成”小注意力“,虽然随着深度的加深感受野逐渐变大,但是其对于浅层和中层的参数更新也是间接的、微弱的。而注意力机制则会关注所有通道/整个WxH的空间的信息,从而选择最重要的部分。因此,也有”卷积是一种特殊的注意力模块“的说法,这么看来也不无道理。
视觉注意力一般分为三种,即通道域、空间域和混合域(前两者都使用)。在分割中还有使用类别注意力(分类特征对于图像分割额外重要),视频分析中也有使用时间注意力来建模目标在时间序列中的关系。
-
通道域 通道域注意力的代表作是SENet,其实现思想和过程都非常简单,仅仅加入了一个即插即用的SE模块分支用于建模不同channel之间的相关性就大幅度地提升了模型性能(最后一届ImageNet图像识别的冠军,超过去年冠军25%)。 ?SENet的结构 ?
若没有学习过积分变换或信号与系统,可以跳过下面这一段。
从本节开始谈到的特征空间分解的角度来看通道域的注意力机制,我们可以类比积分变换的思想:多通道卷积相当于把多个二维卷积核堆叠在一起,将他们拆分来看,每一个二维卷积核其实代表了一种特征空间或像素空间的基,可以对应傅里叶变换中不同频率的正弦分量(如下图),只不过这些分量的选取不是固定的,同时大概率不是正交的,也几乎不可能是完备的(学过信号与系统的同学可以思考一下这个问题)。那么对于检测一个物体来说,这些在不同特征分量上的投影(就是前级feature map经卷积操作产生的不同通道),其重要性也肯定不同。举例来说,如果我们要识别小猫,那么它身上的花纹肯定是一种重要的特征,对应傅里叶变换则应该是一种/多种频率较高的分量(花纹周期性出现),而低频分量就不是我们所关心的。同样对应通道域注意力,虽然我们不知道网络到底学习到了哪些特征(卷积核最终会代表哪一种特征分量),但是不同分量的重要性肯定不是等同的。如SENet这种通道域的注意力,就是让不同通道有不同权重,从而聚焦到那些对于识别特定物体更关键的通道上。 ?傅里叶变换将图像变为不同权重的不同分量叠加 ? 其实在SENet之前,就有paper认为图像中不同频率分量对检测的重要性不同,因此直接对原图进行傅里叶变换,然后将每个分量分别投入不同的网络,最后再用add或multi的方式聚合特征进行检测。其检测效果也还不错,说不定SENet就是借鉴了这类传统方法。
其实已经在可解释性方面的工作尝试发现频域和CNN网络之间的关系,传统图像处理仍然在发挥其优势,想进一步了解相关工作的同学可以参考这篇文章:频域(DCT,小波变换)与CNN结合,这需要一些信号处理的数学知识。
-
由于SENet仅仅利用简单的global average pooling和两层perceptron建模了不同通道的重要性,对于容量大的网络肯定是不够的。因此,后续作者又对其进行了改进得到SKNet(Selective Kernel,如下图),字如其名,这是一种能够自己选择合适大小的卷积核的网络。作者通过实验发现卷积核的结构和待检测物体的尺度有一定的关联,因此希望利用SK module让网络建模这种关联。 有人会说啊,google的Inception不是已经做到了让网络自适应选择卷积核了嘛,我们要注意的是虽然Inception同时并行使用了1x1,3x3和5x5的卷积,但是在concatenate之后,这些通道之间的重要性是等同的,而且卷积核的参数在训练结束后也是静态的。 ?sknet结构 ? 上图中U~和U^分别是经过不同大小卷积核卷积后得到的feature maps,直接按元素相加得到U,随后进行global average pooling和fc(还是SENet的味道),再投入softmax得到注意力得分a、b分别和U~,U^对应通道相乘,选出在对应尺寸卷积核下最重要的通道,最后将上述结果进行按元素相加得到输出V。 -
空间域 空间域的注意力相对比较直观,人类的视觉系统就有这种聚焦与视野内某个区域的特点,帮助我们快速捕捉最重要的信息。在下图里,我们肯定不会去观察海报的白色部分,因为那里没有任何有意义的信息。 ?阅读海报时人类感知系统的注意力分布 ?
-
经过这么长时间的熏陶,相信你应该已经想到如何构建一个空间注意力模块了:先利用池化或卷积从前层的feature maps中提取一个用于生成注意力分数的相关向量,紧接着将此它投入一个轻量化的fc层或conv层,得到注意力分数后和原feature maps相乘即可。不过需要注意的是,空间注意力需要为大小为WxH中的每个点都分配一个权重,因此生成的是一个注意力分数的矩阵。 很好!我们已经有了建空间中不同点间相关性的方法,这其实也是CBAM(Convolutional block attention module)的做法。CBAM是SENet的改进,在原有的通道注意力基础上增加了空间注意力模块,它其实是一种混合域的做法,只不过我们在这里介绍它的SAM模块以引入空间域。 ?绿色的是通道注意力模块,实现和SENet基本相同 ? ? SAM结构,同时使用最大池化和平均池化提取用于注意力的feature map ?
? 自注意力的Spatial Attention的结构,其中N=WxH ? ?DA-Net的结构,通过并行的SA和CA模块建模相关性 ?
-
但是它们都存在一个比较大的问题:巨大的时间开销。源自计算像素之间相关性的矩阵乘法(Q*K)时间复杂度至少是O(W^2*H^2),这对于实时性是不可接受的。于是就出现了ANN、CCNet和GCnet。 ANN(Asymmetric Non-local Neural Network)的思想很简单,一个局部区域内的像素或提取出来的特征和另外一个区域的相关性,应该是比较相近的,除了非常精细的边缘,总不可能每隔一个像素相关性就发生巨大的变化吧?并且检测比分割对于边缘的要求更低。因此它对Key和value矩阵进行了下采样的操作,实际上采用的就是局部线性化的思想:在feature map上选取稀疏的采样点(锚点),利用这些点替代周围的像素。 ? ANN的思想:Key和Value分别通过采样缩小尺寸,使得时间复杂度获得较为可观的减小 ? 线性化的具体的操作就是利用SPP生成θP和γP(最大池化和平均池化均可,或两者都使用让网络自己学习合适的权重),SPP产生的不同层次特征还有助于多尺度分割和检测。根据上图的结构,作者提出了AFNB和APNB两个模块。APNB共享了Key和Value的参数(类似检测头的参数共享),尽可能在不降低建模能力的情况下减少参数量。而AFNB则是继承了APNB的思想,我们从上图中可以看出θP和γP只要分别保证一个维度为C,S的大小是可以根据锚点的数量而变化的,只需要保持对齐即可(取点多则S大,反之少)。既然这样,用于生成QKV的输入也不一定要从同一层feature map中产生,即下图中AFNB模块中的Xh和Xl分别来自不同backbone中的不同层,只需要让生成的θP和γP拥有和Query匹配的维度即可。作者通过实验验证这种做法可以更好地融合不同尺度的特征,因此让backbone的后两个stage分别作为AFNB的输入。 ?ANN的架构 ? 从另一个角度理解,也可以将APNB视作Xh和Xl都来自同一个stage的并共享了Key和Value参数的例子。
-
虽然ANN已经在极大地降低了相关矩阵和注意力分布计算的开销,但是毕竟还是多项式级别的复杂度,有没有什么办法可以进一步减小注意力模块的规模?GCNet(global context)的作者通过实验发现,在backbone的后几个stage,将其feature map上任意一个位置的像素作为query,生成的注意力分布图非常相似,也就是说这种non-local的注意力模块学习到了位置无关的注意力分布。下图是对注意力的可视化结果,蓝->黄->红表示“聚焦程度”。 ?作者从coco上随机选取了6张图片,发现Non-Local模块对于不同的query point生成了几乎相同的注意力分布 ? 这里需要特别注意的是,某点注意力分数越高表示该点和query的相关程度越高。这也就是说,图像上的任意不同点,对于另外一点计算相关性,他们得到的结果是大体相同的(听起来似乎有些匪夷所思!不过注意这是在backbone的后几个stage,由于卷积的感受野越来越大,feature map上不同点之间的关联也应该随着网络深度的加深而变大)。作者在原文还计算了经过注意力权重加和后的特征向量之间的各种度量距离,发现他们的差距都很小。 那么结果很明显了,原来要计算WxH个注意力分布,现在我们从输入上随机选一个query point(或者说不需要query了)来计算它和其他像素的相关性,然后把这个注意力分布应用到其他所有位置即可: ?(b)为简化版本,直接丢弃了Wq矩阵,从计算上来看相当于不关心到底选取了哪一个位置作为query ? 这时候输出可以写为: 其中zi为第i个位置的输出,Np=HxW,xi为第i个位置的值,xj为其他位置的值,Σ后的是softmax操作,为了让总得分和为1。如果把Wv提取到求和前面(利用交换律),复杂度可以继续降低: (b)为简化版本,(d)又加入了通道注意力 ? 对边之前的版本,Wv的1x1卷积复杂度从原来的O(C^2HW)变成了现在的O(C^2)。作者又在上图中(b)的基础上加入通道注意力(使用降维的1x1卷积 [ bottle neck,熟悉inception的同学应该知道这个操作,用于降低参数量 ] 并使用layer normal,ization进一步简化原本的SE模块),得到了最终的GC block,如上图(d)所示。因此GCnet也属于混合域的注意力模型。 关于位置无关的注意力分布和模型简化、加入通道注意力与ablation还有更多的细节,若感兴趣可以参阅原文:GCnet -
最后一个有趣的很有创意的空间注意力网络是CCnet(Criss-Cross Attention [criss : 纵横交错的] )。CCnet聚焦于相关矩阵计算时的高复杂度,提出的模块结构如下: ?一个交叉注意力block需要使用两次基本的交叉注意力module ? criss-cross module在计算不同位置相关性的时候只考虑和当前query处于同一行和同一列的像素,单次计算的复杂度变为(H+W)*HW,紧接着还是和V矩阵进行element-wise multiply得到输出。随后再一次进入另一个cc module得到最终结果。 ? criss-cross module的结构,总体和non-local自注意力相同 ? 聪明的你应该已经想到,使用两次计算就可以间接接触到全局的信息了!第一次相关性计算会将当前像素的信息传递到同行同列的所有位置,第二次计算时之前接受到信息的每个像素又会将再次将信息传递到自己的同行同列。更为形象的例子就是,象棋中的“车”在经过两次移动可以到达棋盘上的任意位置(在没有遮挡的情况下)。 ?不在同一行的两个像素经过两次注意力计算产生关联 ?
如果觉得笔者写得还不错,给个关注点个赞,订阅一下专栏吧!
下期将会更新Anchor Free模型概览!
|