RefineDet

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Chunfengyanyulove/article/details/84943544

论文链接: https://arxiv.org/abs/1711.06897
作者代码链接 : https://github.com/sfzhang15/RefineDet

在目标检测中,有两个主流的分支,分别是以Faster R-CNN为代表的two stage方法以及以SSD为代表的one stage方法,两者各有优势,总结起来就是:two stage方法的精度更高,one stage方法的速度更快

是什么造成了这两种方法的不同呢?简而言之,就是对anchor的处理方法。

two stage方法提取anchor后,对anchor进行了微调,然后将处理过的anchor送入到分类与回归器中,而one stage 缺省了anchor处理这步,将提取的anchor直接送入到分类与回归器中,这可以有效的提高速度,但是带来了一定的问题:由于没有对提取的anchor进行处理(筛选),导致出现了anchor类别不均衡问题,负样本的数量肯定是多的,即使SSD采用了比如:对分类loss进行排序,然后控制正负样本比例1:3,依然会存在这个问题,这也就是为什么one stage方法精度达不到two stage方法那么高的原因。

相比较于one stage方法,two stage方法的优点如下:

  • 控制了样本不均衡问题。
  • 利用2个阶段的级联去进行box框坐标的回归。
  • 利用两个阶段的特征去进行目标的描述。(这里解释一下,是指首先利用RPN网络去判断是否是目标,然后利用后面的网络判断是什么目标以及位置在哪,他们是共享backbone的。)

既然one stage与two stage精度存在差距的原因已经找到,那么我们是否可以想办法解决这个问题呢?

当然可以,对于类别不均衡这个问题,很多网络也都给出了不同的方法,比如:RetinaNet提出使用focal loss去限制负样本的loss比例等

本文实现的RefineDet其实也是在解决这个问题,本文是如何解决的呢?

总结起来其实很简单,既然two stage可以解决这个问题,那么我将one stage与two stage方法融合在一起不就可以即取得高精度又实现高效率了。

下面我们一起看看RefineDet是如何实现的:

首先我们来看RefineDet的网络结构,如下:

上图是本文的关键,观察上图,我们一点点分析:首先,RefineDet由两个内部连接的模块组成,一个是ARM(anchor refinement module),(上面部分), 另一个是ODM(object detection module),(下面部分)ARM就类似于Faster R-CNN中的RPN网络,一方面用于修正anchor,去掉多余的负样本,减少搜索空间,另一方面,用于对anchor的位置以及尺寸进行修正,使得其更有利于坐标的回归,其实就是两方面的优化嘛,一个是分类,一个是回归。ODM就类似于SSD,只不过接受的是前面修改中过的anchor,并利用该anchor进行分类(multi-class)与回归。这样,就不再具有了two stage方法的局限性,如Faster R-CNN生成anchor后,再送入后面进行分类与回归比较耗时,同时又使得one stage方法如SSD的anchor进行了处理,使其同时具有one-stage以及two-stage的优点。另外作者设计了TCB结构,TCB一方面将ARM的feature映射到ODM,另一方面,是将高层的语义信息与低层的信息相融合(就类似于FPN),TCB的结构如下图Figure2所示,这里使用的是Deconv进行特征图的放大,然后利用element-wise sum的方式相加,求和后,连接一个卷积提高特征图的分辨力。

所以,RefineDet总结起来就是如下三点:

  • 利用两个阶段的回归,提高物体检测的精度
  • 过滤掉过多的negative anchor,使得正负样本能够平衡一些。
  • 使用transfer connection block(TCB)将ARM与ODM连接到一起

细节介绍

  • two-step cascaded regression

RefineDet 首先利用ARM网络第一次调整anchor的位置以及坐标,然后将ARM修正过的anchor传给ODM网络,使得ODM网络可以得到更好的初始化的anchor,进而得到更好的回归效果。这样说是不是太泛泛了,下面有更详细的
首先在ARM网络上,采用类似于SSD的方法,在对应的feature map上面生成对应的anchor。对于feature map上的每个cell,预测4个offset以及是前景还是背景(softmax分类),这样对于每个cell就可以生成对应的refined anchor(修正anchor),在得到refined anchor后,将refined anchor传给ODM网络,在ODM中再一次进行分类与回归得到最终目标的分类以及目标的位置。
另外,ARM与ODM的特征图具有相同的维度。每个anchor产生c+4个输出,分别对应c个类别以及4个坐标,这里跟SSD类似,不一样的是,SSD使用的是default box去预测结果,而refineDet使用的是ARM模块refined过后的anchor去预测结果。这使得refineDet具有更好的检测精度,特别是对小目标物体,(所以说,对小目标,FPN那一套还是很有用的)。

  • Negative Anchor Filtering

这个其实很简单,我们知道在one stage方法中,由于是每个cell固定产生anchor的,所以anchor的负样本的量实际上还是很大的,但是大部分其实是没有用的,所以就需要采用一些方法对没有用的anchor进行过滤,可以利用loss进行过滤,也可以利用分类分数进行过滤,在ARM中,是使用的分类的分数进行过滤的方法,就是在训练的过程中,如果ARM判断其negative的confidence(置信度)大于设定的阈值(默认是0.99),则我们在ODM中就自动忽略这个anchor,在inference阶段,如果refined anchor box的negative confidence的值大于阈值,同样也是被忽略的。

Training and Inference

  • 数据增强,这个当然是必不可少的,本文数据增强方法参照SSD数据增强方法。

  • backbone network:网络结构跟SSD基本保持一致。,作者使用了VGG16以及ResNet-101作为基础网络,当然其他网络也可以,这里只是比较常用。以VGG16为例,跟SSD一样,将fc6和fc7转换为卷积层conv_fc6以及conv_fc7,另外为了更好的利用高层信息,我们在vgg16网络的最后增加了2个额外的卷积层(conv6_1,conv6_2),对resnet101增加了一个另外的residual block(res6),并且对conv4_3以及conv5_3添加了L2 normalization层,并分别设置scale为10和8,并在反向传播中学习scale。

class L2Norm(nn.Module):
    def __init__(self,n_channels, scale):
        super(L2Norm,self).__init__()
        self.n_channels = n_channels
        self.gamma = scale or None
        self.eps = 1e-10
        self.weight = nn.Parameter(torch.Tensor(self.n_channels))
        self.reset_parameters()

    def reset_parameters(self):
        init.constant(self.weight,self.gamma)

    def forward(self, x):
        norm = x.pow(2).sum(dim=1, keepdim=True).sqrt()+self.eps
        #x /= norm
        x = torch.div(x,norm)
        out = self.weight.unsqueeze(0).unsqueeze(2).unsqueeze(3).expand_as(x) * x
        return out
  • Anchor Design and Matching:Anchor的设计跟SSD也是比较相似的,不同的是,这里只在4个feature layer上面提取Anchor,分别对应stride为(8,16,32,64)(注:SSD是在6个特征图上,以SSD300为例,分别对应特征图大小为38,19,10,5,3,1),并且不同的feature layer匹配不同大小及尺寸的anchor,scale是stride的4倍即对应的检测尺度为,以320为例子,对应的不同的layer检测的图像尺度为:[ 32, 64, 128, 256 ],aspect ratio 有3个(0.5,1,2),正样本同样是overlap最大以及IOU大于0.5,这都没啥特殊的,都是这样的。

  • Hard Negative Mining: 不管对于ARM还是ODM,依然使用类似于SSD的正负样本1:3的比例,手段跟SSD一样,利用分类loss从大到小排序,取前面的部分。

  • Loss Function, 如下:

loss function解释一下:其中 p i p_i 以及 x i x_i 是ARM模块中对anchor进行分类的置信度以及回归的坐标, c i c_i t i t_i 是ODM模块对refined anchor进行分类的置信度以及回归的坐标, N a r m N_{arm} 以及 N o d m N_{odm} 分别代表batch中正样本的数量 , L b L_b 是一个2类的交叉熵loss,判断是否是object, L m L_m 是softmax loss, 类别数为检测的类别, L r L_r 是smooth L1 loss, 类似于Faster R-CNN, l i l_i^* 表示分类的groud truth, g i g_i^* 代表的是坐标的ground truth,[ l i l_i^* >=1] 当条件满足的时候输出为1,[ l i l_i^* >=1]代表的是正样本,所以[ l i l_i^* >=1] L r L_r 代表的是只有正样本才会去计算坐标回归,负样本不计算。

  • Optimization: VGG-16新添加的两层: 采用xavier初始化参数, resnet101新添加的residual block: 采用均值为0,方差为0.01的高斯分布进行初始化。默认训练的 batchsize 是32 ,使用SGD方法进行fine-tune训练,momentum取0.9, weight decay为0.0005, learning rate取0.001,learning rate delay。

  • Inference: inference阶段,首先ARM首先利用分类得分阈值过滤掉一部分的负样本,然后计算这部分anchor的location,以及size,然后,将refined anchor传入ODM模块进行分类,每张图像取得分高的400个图像。最终,利用非极大值抑制,保证最终得到200个高分的检测结果作为最终的结果。

  • 速度方面:Titan X GPU 图像尺寸:320*320,40.2FPS, 图像尺寸:512*512, 24.1FPS。

实验部分

  • VOC的对比实验

下图显示的是在VOC上的测试结果,可见RefineDet320*320可以达到80%的精度,512*512可以达到81.8%的精度,最下面两组是采用multi-scale的测试策略【即将图片缩放到不同的尺度进行测试】,测试结果显示,512的精度可以达到83.8%。RefineDet也是第一个实时的精度超过80%的目标检测算法, SSD512有24564个anchor,而RefineDet512只有16320个anchor。多尺度也是一个比较有效的提高精度的方法

  • 溶解实验
  • 首先,是对负样本滤除效果的验证,作者设计实验,一个是使用所有refined anchor,另一个是正常的使用阈值(0.99)进行过滤,由table 3可以发现,负样本的滤除可以带来大约0.5%的精度提升。
  • 为验证2个阶段回归的重要性,作者使用不再refined的anchor进行实验,发现其精度有大约2%的下降(表格第2列以及第3列)
  • 验证TCB的效果,作者直接去掉了TCB连接,直接在ARM上进行分类以及回归,这其实就跟SSD一样了,发现其精度又有了大约1%的下降。分析原因,主要是采用TCB一方面可以从ARM中继承到特征差异,另一方面采用了类似于FPN的特征融合,使得精度得到提升。

  • COCO:

为了得到更好的效果,这里作者实验使用的basebone是resnet101,对比Table 7,其中带加号的是代表multi-scale test,可见,RefineDet的最好的效果可以达到了41.8%

如何提高PASCAL VOC的检测精度??

因为PASCAL VOC是COCO的子集,所以我们也可以使用COCO的预训练模型来提高VOC的精度,实验结果如下,通过COCO的预训练模型,RefineDet320可以达到84%的精度,如果是512可以达到85.2%的精度(2007 test),如果使用multi-scale test,精度还可以进一步提高,如下表所示,最高可以达到86%左右

分析RefineDet对不同类别目标的检测效果,如下图,其中第一排是不同类别的比例分布,横轴是检测的数量,那条红色的实线是IOU阈值0.5对应的召回率,虚线是IOU阈值0.1对应的召回率,其中不同颜色分别代表如下:白色代表判断对的,蓝色代表由于位置不对导致的错误,深红表示相近类别的混淆,紫色代表背景,绿色代表其他,

第二行代表判错的样本中不同类别分布的百分比。

最后来一张检测结果图:

以上是本人对RefineDet的理解,如有问题,还请指出~

猜你喜欢

转载自blog.csdn.net/Chunfengyanyulove/article/details/84943544