Deformable Convolutional Networks 可变形卷积网络解析

Deformable Convolutional Networks

1. 什么是可变形卷积?

Deformable Convolutional Networks 中提出了一种可以变形的卷积核和池化核,也就是不使用原来的正方形卷积核,而且一个多边形。这样可以让卷积核更多地聚集在目标的轮廓上。

下面对比两种图片:

卷积核聚集在人的身上:
在这里插入图片描述
卷积核聚集在羊的身上:
在这里插入图片描述
所以论文中的核心思想就是:将固定形状的卷积过程改造成了能适应物体形状的可变的卷积过程,从而使结构适应物体形变的能力更强

2. 可形变卷积解决了什么问题?

传统的CNN只能靠一些简单的方法(比如max pooling)来适应物体的形变,如果形变的太厉害就无能为力了。为了改变这种情况专家们想了很多方法,最常见的有两种:

  1. 使用大量的数据进行训练。 比如用ImageNet数据集,再在其基础上做翻转等变化来扩展数据集,通俗地说就是通过穷举的方法使模型能够适应各种形状的物体,这种方法收敛较慢而且要设计复杂的网络结构才能达到理想的结果,但是,如果用训练中没有遇到过的新形状物体(但同属于一类)来做测试,由于新形状没有训练过,会造成测试不准确,而且靠数据集来适应形变的训练过程太耗时,网络结构也必须设计的很复杂
  2. 设计一些特殊的算法来适应形变。 比如SIFT,目标检测时用滑动窗口法来适应目标在不同位置上的分类也属于这类;但是,如果物体的形状极其复杂,要设计出能适应这种复杂结构的算法就更困难了。

传统的方法都不行,那要怎么办呢?

思路很清晰就是:我预定为正方形的感知野,但是感受野上的每一个点加一个偏移量,偏移的大小是通过学习得来的,偏移后感受野不再是个正方形,而是和物体的实际形状相匹配。这么做的好处就是无论物体怎么形变,卷积的区域始终覆盖在物体形状的周围。

下面用论文中的一个图来演示一下变化过程:
在这里插入图片描述

3. 可变形卷积的具体实现细节

在说明具体实现细节之前我现在这样说明一下双线性插值的概念

3.1 双线性插值

想要理解双线性查找,那我们想来说一下什么是线性插值。

线性插值的概念非常简单粗暴,就是两个点A,B,要在AB中间插入一个点C(点C坐标在AB连线上),就直接让C的值落在AB的值的连线上就可以了。

如A点坐标(0,0),值为3,B点坐标(0,2),值为5,那要对坐标为(0,1)的点C进行插值,就让C落在AB线上,值为4就可以了。当然前提是C在AB的连线上,如果C不在AB的连线上要怎么办呢,很简单分别沿x轴和y轴进行线性插值,然后给他加起来就ok啦,这个过程就叫做双线性插值

举个栗子:

如图,已知Q12,Q22,Q11,Q21,但是要插值的点为P点,这就要用双线性插值了,首先在x轴方向上,对R1和R2两个点进行插值,这个很简单,然后根据R1和R2对P点进行插值。
在这里插入图片描述
有兴趣的可以去维基百科看看推导的公式

说了那么多这个公式究竟是用来干什么的呢?在cv中主要是用来改变图像的大小,但是在这里并不是这个用法。你需要知道双线性插值是更加坐标系中已知量的值去得到一个未知坐标的值。下面的公式就会对其进行一个运用

3.2 可变形卷积 Deformable Convolution

传统的卷积结构可以定义成如下公式:

y ( p 0 ) = p n R w ( p n ) x ( p 0 + p n + Δ p n ) \mathbf{y}\left(\mathbf{p}_{0}\right)=\sum_{\mathbf{p}_{n} \in \mathcal{R}} \mathbf{w}\left(\mathbf{p}_{n}\right) \cdot \mathbf{x}\left(\mathbf{p}_{0}+\mathbf{p}_{n}+\Delta \mathbf{p}_{n}\right)
pn是卷积输出每一个点相对感受野上的每一个点的偏移量,取整数。

采用全新的可变形卷积后要在公式1基础上给每个点再增加一个偏移量Δpn,这个新的偏移量是由另一个卷积得出,所以一般是小数

y ( p 0 ) = p n R w ( p n ) x ( p 0 + p n + Δ p n ) \mathbf{y}\left(\mathbf{p}_{0}\right)=\sum_{\mathbf{p}_{n} \in \mathcal{R}} \mathbf{w}\left(\mathbf{p}_{n}\right) \cdot \mathbf{x}\left(\mathbf{p}_{0}+\mathbf{p}_{n}+\Delta \mathbf{p}_{n}\right)

x(p0+pn+Δpn)的取值位置非整数,并不对应feature map上实际存在的点,所以必须用插值来得到,这里我们就用双线性插值的方法来获取。然后我们可以得到这个公式
x ( p ) = q G ( q , p ) x ( q ) = q g ( q x , p x ) g ( q y , p y ) x ( q ) = q max ( 0 , 1 q x p x ) max ( 0 , 1 q y p y ) x ( q ) \begin{array}{l} x(\mathrm{p})=\sum_{q} G(\mathrm{q}, \mathrm{p}) \cdot x(\mathrm{q}) \\ =\sum_{q} \mathrm{g}\left(\mathrm{q}_{\mathrm{x}}, \mathrm{p}_{\mathrm{x}}\right) \cdot g\left(\mathrm{q}_{\mathrm{y}}, \mathrm{p}_{\mathrm{y}}\right) \cdot x(\mathrm{q}) \\ =\sum_{q} \max \left(0,1-\left|\mathrm{q}_{\mathrm{x}}-\mathrm{p}_{\mathrm{x}}\right|\right) \cdot \max \left(0,1-\left|\mathrm{q}_{\mathrm{y}}-\mathrm{p}_{\mathrm{y}}\right|\right) \cdot x(\mathrm{q}) \end{array}
x(q)表示feature map上所有整数位置上的点的取值

这里双线性插值的公式我就不在多做说明了。原理我在上面已经说过了。通过这样的可变形卷积层我们就完成了可变形卷积啦

下面放上论文中的可变形卷积的网络结构:
在这里插入图片描述
其中上方的卷积用于输出偏移量,该输出的长宽和输入特征图的长宽一致,维度则是输入的2倍(因为同时输出了x方向和y方向的偏移量,要用2个维度分开存储)。

3.3 可变形的ROI Pooling

ROI Pooling 的改进和卷积核的改进方式基本相同都是再增加一个偏移量

改进前:

y ( i , j ) = p  bin  ( i , j ) x ( p 0 + p ) / n i j \mathbf{y}(i, j)=\sum_{\mathbf{p} \in \text { bin }(i, j)} \mathbf{x}\left(\mathbf{p}_{0}+\mathbf{p}\right) / n_{i j}
改进后:

y ( i , j ) = p bin ( i , j ) x ( p 0 + p + Δ p i j ) / n i j \mathbf{y}(i, j)=\sum_{\mathbf{p} \in \operatorname{bin}(i, j)} \mathbf{x}\left(\mathbf{p}_{0}+\mathbf{p}+\Delta \mathbf{p}_{i j}\right) / n_{i j}

其中 Δ p i j \Delta p_{i j} 是每个bin的偏移量,要注意这个偏移量是针对整个bin的,也就是说一个bin中的每一个点该值都相同。

下面放上网络结构:
在这里插入图片描述
可以看到,需要做ROI Pooling处理的区域首先完成没有偏移下的pooling过程,输出kkchannel个数据,再用一个全连接层输出kk2*channel个点表示在x和y方向上的偏移 p n p^n ,再对它按如下公式进行处理处理得到真正的偏移量pn。公式中 γ \gamma 是个增益,作者建议取0.1,与(w,h)进行点乘是为了让偏移量的调整幅度能适配ROI的尺寸。pn也是个小数,需要通过双线性插值来得到真正的值,插值的方法和可变卷积相同,不再重复描述。

Δ p i j = γ Δ p ^ i j ( w , h ) \Delta \mathbf{p}_{i j}=\gamma \cdot \Delta \widehat{\mathbf{p}}_{i j} \circ(w, h)

原创文章 113 获赞 80 访问量 3万+

猜你喜欢

转载自blog.csdn.net/python_LC_nohtyp/article/details/106115366