Non-local Neural Networks 文章分析
Introduction
本文借鉴了传统图像处理中经典的Non-local mean方法,提出了一种称为Non-local block的结构用来捕获长距离序列中的依赖信息(“capturing long-range dependencies”)。作者通过实验证明这种结构设计对动态的视频分类和静态的目标检测、语义分割和关键点检测等任务中、都有较明显的提升。
在处理视觉任务的CNN网络中,使用卷积操作只能捕获局部信息,因此需要通过堆叠相当数量的卷积层,来增大CNN的感受野(Receptive field),从而获得语义性更强的信息。类似地,在NLP任务中,使用RNN、LSTM等结构也只能保留较短距离词的相关信息,对长句子的处理依然需要大量block的堆叠来完成。
作者提出的Non-local operation要完成的任务就是对特征图中所有位置的点进行加权求和来作为下一阶段特征图中的某一点的值。(“computes the response at a position as a weighted sum of the features at all positions.”)而在传统CNN中,下一层特征图中某一点是卷积核(假设3×3)与前一层特征图中3×3大小的像素点对位相乘再相加得到,这是两者最大的区别所在。因此,Non-local operation具有捕获长距离依赖关系的能力且不需要大量卷积层的堆叠。
上图是32帧视频中,等间距抽出来的4帧图像。注意:与所有帧的所有位置都存在连接。将与连接权重最高的几个点标注出来做连线可以看出:算法成功捕获到了球和小男孩在时间和空间上的依赖关系。
Implementation
数学公式描述
首先给出non-local operation的计算公式:
公式特别简单。是对应位置(空间位置or时间位置or时空位置)的输出,而是特征图上的所有可能位置。函数计算和之间的相关值。而计算输入信号在位置上的向量表示。是归一化因子。即原文中的“all positions”。
这种与所有位置连接的方式看起来很像CNN中的全连接层,但这non-local operation和fc是完全不一样的,最大区别在于:训练完成后的fc中的连接权重对于所有输入在相同位置都是相同的;而non-local operation中的连接权重,即对不同的输入在相同位置上是不同的。
公式结构是固定的,但是公式中的可以采用不同的实现方式,作者在文章中给出了以下几种实现:
对于: 是需要学习的权重,相当于对做embeding。的学习可以通过1×1卷积实现。
对于:
Method | ||
---|---|---|
Gaussian | C(x)= | |
Embedded Gaussian | C(x)= | |
Dot product | (N是的位置的数量) | |
Concatenation |
特别需要注意的几点:
- 上述几种实现方式都能提升视频分类任务精确度且相互间差距不大,说明这种Non-local操作的设计才是提升性能的最主要原因。
- 作者认为谷歌那篇著名的论文Attention is all you need中提出的self-attention机制其实就是Non-local operation以Embedded Gaussian机制实现版本的一种特例。在Gaussian 和Embedded Gaussian实现中,构成了softmax函数。(self_attention:
另外,为了方便在预训练好的模型中嵌入模块,作者使用了残差连接的方法,也就是说,Non-local block在位置的最终输出是:
网络结构描述
下图是的non-local block的Embedded Gaussian实现形式:
上面的结构图可以和公式一一对应起来。公式中的就是卷积核的参数,也就是上图蓝框里的部分。需要注意的是,公式给出的是一个点的计算过程,而在实际应用中是通过张量相乘同时计算所有点的值。
Experiments
实验部分不作详细描述了。文章的实验部分论证得特别充分,值得借鉴。作者在视频分类,目标检测和关键点检测等不同任务上的不同算法的不同阶段嵌入不同数量的Non-local block,都获得了可观的性能提升。
重点记录一下我一开始没有理解的部分:在Video Classification实验上,作者用了二维卷积(C2D)和三维卷积(I3D)分别搭建网络进行实验。在C2D部分,作者描述如下:“All convolutions in Table 1 are in essence 2D kernels that process the input frame-by-frame (implemented as 1×k×k kernels). ”并给出了下面参数表:
刚开始怎么看也没法把layer参数和output size对上,后来才明白了frame by frame的意思:将视频的每一帧作为独立的图片输入网络,layer列对应的是图片卷积时的参数,而output size列中第一个参数是帧,所以不与前面的channel数对应。只有在pool操作时才融合不同帧的信息,使帧维数降低(好像conv1时通过同时输入两张图片作为一张的方式降低了帧维数?)
注意不能把多通道二维卷积和三维卷积搞混:多通道二维卷积时,通道(channel)不应看作一个单独的维度,因为一个二维卷积核在通道上的“维数”和通道数是相同的,也就是说卷积核在通道方向上是不会“移动”的;而三维卷积是真正三维的:卷积核在帧维度上的大小小于输入数据在帧维度上的大小,也就是说,它在输入的长、宽、帧方向都是在“移动”的。