笔记:DetNet: A Backbone network for Object Detection论文阅读
DetNet(2018)
一。摘要
现有骨干网络都是为分类任务设计,本文为目标检测专门设计了一个骨干网络DetNet
原因:1.FPN,RetinaNet等目标检测器通常比目标检测任务包含更多阶段,从而处理多尺度目标
2.目标检测任务不仅要对目标进行分类,还要进行定位,大的下采样因子带来大的感受野,利于目标分类,但不利于定位
在更深层中维持高空间分辨率的同时,DetNet 还包含与传统图像分类骨干网络不同的额外阶段。DetNet在保持高分辨率特征图和大感受野的同时,高效地执行目标检测任务,并可以自然地扩展到实例分割任务上。
代码链接:https://github.com/guoruoqian/DetNet_pytorch
二。介绍
DetNet 针对不同尺度目标像 FPN 一样使用了更多的 stage。它优于 ImageNet 预训练模型的地方在于成功保留了特征的空间分辨率,但同时也会增加神经网络的计算和内存成本。为保证 DetNet 的效率,本文引入了低复杂度的 dilated bottleneck。由此,DetNet 做到了较高分辨率和较大感受野的兼得。
传统骨干网络问题:1.主干网络和检测网络的阶段数不同
2.大目标定位不准确 :过大的下采样导致大物体看不清边界地区
3.小目标很难发现:同样过大的下采样也可能会丢失小物体的信息。
FPN下的骨干网络:
DetNet优势:1)stage 的数量与 FPN 相同,因此额外的 stage 比如 P6 可在 ImageNet 中完成预训练;
2)受益于最后 stage 中的高分辨率特征图,DetNet 在定位大物体边界框和发现小物体方面更为强大。
三。DetNet
DetNet使用 ResNet-50 作为基线模型,其作为骨干网络广泛用于大量目标检测器中。为了公平地与 ResNet-50 进行对比,研究者使 DetNet 的阶段 1、2、3、4 与原始 ResNet-50 的阶段保持一致。
主要有以下挑战:1.保持深度神经网络的空间分辨率需要耗费大量时间和内存;
2.降低下采样因子等于减少有效的接受野,这对很多视觉任务都是有害的,如图像分类和语义分割任务。
针对以上挑战,对后阶段进行以下改进:
(1)在FPN结构中应用的骨干网络中引入了额外的阶段,比如P6阶段。同时,即使在阶段4之后16x的空间分辨率依旧固定不变。
(2)空间尺度在阶段4之后是不变的,他们在阶段4后引入了新的阶段,每个阶段开始是一个带1x1卷积投射的Dilated botteNeck( B),他们发现在 B中的结构在类似FPN这种多阶段的检测器中有重要作用。
(3)他们把带扩张卷积的瓶颈结构作为基础网络模块,以此有效扩大感受野。又由于扩张卷积仍然很耗时,于是把阶段5和阶段6的通道数设置成和阶段4一样(256瓶颈模块输入通道)这和每到下一阶段就会扩大一倍通道数的传统骨干设计不一样。
以下为Dilated botteNeckB代码
class BottleneckB(nn.Module):
expansion = 4
def __init__(self, inplanes, planes, stride=1, downsample=None):
super(BottleneckB, self).__init__()
assert inplanes == (planes * 4), 'inplanes != planes * 4'
assert stride == 1, 'stride != 1'
assert downsample is None, 'downsample is not None'
self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=False) # inplanes = 1024, planes = 256
self.bn1 = nn.BatchNorm2d(planes)
self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, dilation=2,
padding=2, bias=False) # stride = 1, dilation = 2
self.bn2 = nn.BatchNorm2d(planes)
self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=False)
self.bn3 = nn.BatchNorm2d(planes * 4)
self.relu = nn.ReLU(inplace=True)
self.downsample = downsample
self.stride = stride
self.extra_conv = nn.Sequential(
nn.Conv2d(inplanes, planes * 4, kernel_size=1, bias=False),
nn.BatchNorm2d(planes * 4)
)
def forward(self, x):
out = self.conv1(x)
out = self.bn1(out)
out = self.relu(out)
out = self.conv2(out)
out = self.bn2(out)
out = self.relu(out)
out = self.conv3(out)
out = self.bn3(out)
residual = self.extra_conv(x)
if self.downsample is not None: # downsample always is None, because stride=1 and inplanes=expansion * planes
residual = self.downsample(x)
out += residual
out = self.relu(out)
return out
DetNet网络
class DetNet(nn.Module):
def __init__(self, block, layers, num_classes=1000):
self.inplanes = 64
super(DetNet, self).__init__()
self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3,
bias=False)
self.bn1 = nn.BatchNorm2d(64)
self.relu = nn.ReLU(inplace=True)
self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
self.layer1 = self._make_layer(block, 64, layers[0])
self.layer2 = self._make_layer(block, 128, layers[1], stride=2)
self.layer3 = self._make_layer(block, 256, layers[2], stride=2)
self.layer4 = self._make_new_layer(256, layers[3])
self.layer5 = self._make_new_layer(256, layers[4])
self.avgpool = nn.AdaptiveAvgPool2d(1)
self.fc = nn.Linear(1024, num_classes)
DetNet-59
model = DetNet(Bottleneck, [3, 4, 6, 3, 3])
四。实验
上一篇: Python简单实现控制电脑的方法
下一篇: 边缘检测 - Sobel算子