Deformable Convolution Networks
论文地址:https://arxiv.org/pdf/1703.06211
官方源码:https://github.com/msracver/Deformable-ConvNets/tree/master
Deformable Convolution
文章提出了可变形卷积和可变形ROI采样。原理是一样的,这里先讲解一下可变形卷积,传统的卷积如上图a所示吗,采样点是固定的9个位置,bcd是对应的可变形卷积,b是比较常见的状态,9个采样点位置随机。cd是可变形卷积比较特殊的情形。
这么做有什么好处呢?如上图所示,左边是普通卷积,卷积位置固定,模型关注的位置被限定成一个方形。右边是可变形卷积,由于偏移量是一个可学习参数,模型关注的形状可以是任意外形。
可变形卷积是怎么做的呢?从下图可以看到,只要计算出一个offsets偏移即可。
如果不考虑batch和channel的维度,假设有一个
H
×
W
H \times W
H×W的feature map,对于任意一个采样点的偏移,都需要x方向和y方向的偏移,仅仅这样还不够。由于卷积核是
k
×
k
k \times k
k×k大小的,卷积核上的每个采样点都要有偏移。所以每个点必须要有
2
×
k
×
k
2 \times k \times k
2×k×k个offsets。所以生成的offsets的尺寸为
H
×
W
×
2
k
2
H \times W \times 2k^2
H×W×2k2
在mmcv中使用可变形卷积,先利用常规的conv计算出offsets变量:
import torch
import torch.nn as nn
from mmcv.ops import DeformConv2d
class DeformableConvNet(nn.Module):
def __init__(self, in_channels, out_channels, kernel_size=3):
super(DeformableConvNet, self).__init__()
self.offsets = nn.Conv2d(in_channels, 2 * kernel_size * kernel_size, kernel_size=kernel_size, padding=1)
self.deform_conv = DeformConv2d(in_channels, out_channels, kernel_size=kernel_size, padding=1)
def forward(self, x):
offsets = self.offsets(x) # 生成偏移量
x = self.deform_conv(x, offsets) # 可变形卷积操作
return x
# 示例
input = torch.randn(1, 3, 64, 64)
model = DeformableConvNet(in_channels=3, out_channels=64, kernel_size=3)
output = model(input)
Deformable RoI Pooling
应用到ROI Pooling也是一样的,而且ROI Pooling相较于普通的Pooling,不需要进行移动和多次采样。所以直接是用一个全连接层,输出的offsets特征通道数是
2
×
h
×
w
2 \times h \times w
2×h×w,其中
h
h
h和
w
w
w是输出ROI的特征图的大小,2表示x,y方向的偏移。具体来说,输出的offsets tensor形状为
(
N
,
2
×
h
×
w
,
H
,
W
)
(N,2 \times h \times w, H,W)
(N,2×h×w,H,W),其中
N
N
N是batch的大小。
文章最后给出了验证集中的样例对比。左边第一张图是普通卷积,由于采样点位置很固定,那么模型实际上的关注点都是很分散的,模型无法聚焦到主体位置上。如果把普通卷积换成可变形卷积,效果就是右边两张图。由于可变形卷积的偏移量是可学习的,经过训练后,模型的关注点都会集中到主要物体上。