SSD: Single Shot MultiBox Detector 深度学习笔记之SSD物体检测模型

算法概述

本文提出的SSD算法是一种直接预测目标类别和bounding box的多目标检测算法。

与faster rcnn相比,该算法没有生成 proposal 的过程,这就极大提高了检测速度。针对不同大小的目标检测,传统的做法是先将图像转换成不同大小(图像金字塔),然后分别检测,最后将结果综合起来(NMS)。

而SSD算法则利用不同卷积层的 feature map 进行综合也能达到同样的效果。算法的主网络结构是VGG16,将最后两个全连接层改成卷积层,并随后增加了4个卷积层来构造网络结构。对其中5种不同的卷积层的输出(feature map)分别用两个不同的 3×3 的卷积核进行卷积,一个输出分类用的confidence,每个default box 生成21个类别confidence;一个输出回归用的 localization,每个 default box 生成4个坐标值(x, y, w, h)。

此外,这5个feature map还经过 PriorBox 层生成 prior box(生成的是坐标)。上述5个feature map中每一层的default box的数量是给定的(8732个)。最后将前面三个计算结果分别合并然后传给loss层。

Default box

文章的核心之一是作者同时采用lower和upper的feature map做检测。

如图Fig 1 所示,这里假定有8×8和4×4两种不同的feature map。第一个概念是feature map cell,feature map cell 是指feature map中每一个小格子,如图中分别有64和16个cell。另外有一个概念:default box,是指在feature map的每个小格(cell)上都有一系列固定大小的box,如下图有4个(下图中的虚线框,仔细看格子的中间有比格子还小的一个box)。

假设每个feature map cell有k个default box,那么对于每个default box都需要预测c个类别score和4个offset,那么如果一个feature map的大小是m×n,也就是有m*n个feature map cell,那么这个feature map就一共有(c+4)*k * m*n 个输出。这些输出个数的含义是:采用3×3的卷积核对该层的feature map卷积时卷积核的个数,包含两部分(实际code是分别用不同数量的3*3卷积核对该层feature map进行卷积):数量c*k*m*n是confidence输出,表示每个default box的confidence,也就是类别的概率;数量4*k*m*n是localization输出,表示每个default box回归后的坐标)。训练中还有一个东西:prior box,是指实际中选择的default box(每一个feature map cell 不是k个default box都取)。

也就是说default box是一种概念,prior box则是实际的选取。训练中一张完整的图片送进网络获得各个feature map,对于正样本训练来说,需要先将prior box与ground truth box做匹配,匹配成功说明这个prior box所包含的是个目标,但离完整目标的ground truth box还有段距离,训练的目的是保证default box的分类confidence的同时将prior box尽可能回归到ground truth box。

举个列子:假设一个训练样本中有2个ground truth box,所有的feature map中获取的prior box一共有8732个。那个可能分别有10、20个prior box能分别与这2个ground truth box匹配上。训练的损失包含定位损失和回归损失两部分。

作者的实验表明default box的shape数量越多,效果越好。

这里用到的 default box 和Faster RCNN中的 anchor 很像,在Faster RCNN中 anchor 只用在最后一个卷积层,但是在本文中,default box 是应用在多个不同层的feature map上。

那么default box的scale(大小)和aspect ratio(横纵比)要怎么定呢?假设我们用m个feature maps做预测,那么对于每个featuer map而言其default box的scale是按以下公式计算的:

Sk=Smin+Smax−Sminm−1(k−1),k∈[1,m]

这里smin是0.2,表示最底层的scale是0.2;smax是0.9,表示最高层的scale是0.9。

至于aspect ratio,用a_r表示为下式:注意这里一共有5种aspect ratio

a_r = \{1, 2, 3, 1/2, 1/3\}

因此每个default box的宽的计算公式为:

w_k^a=s_k\sqrt{a_r}

高的计算公式为:(很容易理解宽和高的乘积是scale的平方)

h_k^a=s_k/\sqrt{a_r}

另外当aspect ratio为1时,作者还增加一种scale的default box:

s_k^{'}=\sqrt{s_{k}s_{k+1}}

因此,对于每个feature map cell而言,一共有6种default box。

可以看出这种default box在不同的feature层有不同的scale,在同一个feature层又有不同的aspect ratio,因此基本上可以覆盖输入图像中的各种形状和大小的object!

(训练自己的样本的时候可以在FindMatch()之后检查是否能覆盖了所有的 ground truth box)

源代码中的 ssd_pascal.py 设计了上面几个参数值,caffe 源码 prior_box_layer.cppForward_cpu()实现。

最后会得到(38*38*4 + 19*19*6 + 10*10*6 + 5*5*6 + 3*3*4 + 1*1*4)= 8732个prior box。

Fig.2 SSD 框架

正负样本

prior boxgrount truth box 按照IOU(JaccardOverlap)进行匹配,匹配成功则这个prior box就是positive example(正样本),如果匹配不上,就是negative example(负样本),显然这样产生的负样本的数量要远远多于正样本。这里将前向loss进行排序,选择最高的num_sel个prior box序号集合 D。那么如果Match成功后的正样本序号集合P。那么最后正样本集为 P - D\cap{P},负样本集为 D - D\cap{P}。同时可以通过规范num_sel的数量(是正样本数量的三倍)来控制使得最后正、负样本的比例在 1:3 左右。

Fig.3 positive and negtive sample VS ground_truth box

1.正样本获得

我们已经在图上画出了prior box,同时也有了ground truth,那么下一步就是将prior box匹配到ground truth上,这是在 src/caffe/utlis/bbox_util.cppFindMatches 以及子函数MatchBBox函数里完成的。值得注意的是先是从groudtruth box出发给每个groudtruth box找到了最匹配的prior box放入候选正样本集,然后再从prior box出发为prior box集中寻找与groundtruth box满足IOU>0.5的一个IOU最大的prior box(如果有的话)放入候选正样本集,这样显然就增大了候选正样本集的数量。

2.负样本获得

在生成一系列的 prior boxes 之后,会产生很多个符合 ground truth box 的 positive boxes(候选正样本集),但同时,不符合 ground truth boxes 也很多,而且这个 negative boxes(候选负样本集),远多于 positive boxes。这会造成 negative boxes、positive boxes 之间的不均衡。训练时难以收敛。

因此,本文采取,先将每一个物体位置上对应 predictions(prior boxes)loss 进行排序。 对于候选正样本集:选择最高的几个prior box与正样本集匹配(box索引同时存在于这两个集合里则匹配成功),匹配不成功则删除这个正样本(因为这个正样本不在难例里已经很接近ground truth box了,不需要再训练了);对于候选负样本集:选择最高的几个prior box与候选负样本集匹配,匹配成功则作为负样本。

这就是一个难例挖掘的过程,举个例子,假设在这8732个prior box里,经过FindMatches后得到候选正样本P个,候选负样本那就有8732-P个。将prior box的prediction loss按照从大到小顺序排列后选择最高的M个prior box。如果这P个候选正样本里有a个box不在这M个prior box里,将这M个box从候选正样本集中踢出去。如果这8732-P个候选负样本集中包含的8732-P有M-a个在这M个prior box,则将这M-a个候选负样本作为负样本。SSD算法中通过这种方式来保证 positives、negatives 的比例。实际代码中有三种负样本挖掘方式:

如果选择HARD_EXAMPLE方式(源于论文Training Region-based Object Detectors with Online Hard Example Mining),则默认M = 64,由于无法控制正样本数量,这种方式就有点类似于分类、回归按比重不同交替训练了。

如果选择MAX_NEGATIVE方式,则M = P*neg\_pos\_ratio,这里当neg\_pos\_ratio = 3的时候,就是论文中的正负样本比例1:3了。

enum MultiBoxLossParameter_MiningType {
  MultiBoxLossParameter_MiningType_NONE = 0,
  MultiBoxLossParameter_MiningType_MAX_NEGATIVE = 1,
  MultiBoxLossParameter_MiningType_HARD_EXAMPLE = 2
};

3.Data augmentation

本文同时对训练数据做了 data augmentation,数据增广。

每一张训练图像,随机的进行如下几种选择:

  • 使用原始的图像
  • 随机采样多个 patch(CropImage),与物体之间最小的 jaccard overlap 为:0.1,0.3,0.5,0.7 与 0.9

采样的 patch 是原始图像大小比例是 [0.3,1.0],aspect ratio 在 0.5 或 2。

当 groundtruth box 的 中心(center)在采样的 patch 中且在采样的 patch中 groundtruth box面积大于0时,我们保留CropImage。

在这些采样步骤之后,每一个采样的 patch 被 resize 到固定的大小,并且以 0.5 的概率随机的 水平翻转(horizontally flipped,翻转不翻转看prototxt,默认不翻转)

这样一个样本被诸多batch_sampler采样器采样后会生成多个候选样本,然后从中随机选一个样本送人网络训练。

网络结构

SSD的结构在VGG16网络的基础上进行修改,训练时同样为conv1_1,conv1_2,conv2_1,conv2_2,conv3_1,conv3_2,conv3_3,conv4_1,conv4_2,conv4_3,conv5_1,conv5_2,conv5_3(512),fc6经过3*3*1024的卷积(原来VGG16中的fc6是全连接层,这里变成卷积层,下面的fc7层同理),fc7经过1*1*1024的卷积,conv6_1,conv6_2(对应上图的conv8_2),conv7_1,conv7_2,conv,8_1,conv8_2,conv9_1,conv9_2,loss。然后一方面:针对conv4_3(4),fc7(6),conv6_2(6),conv7_2(6),conv8_2(4),conv9_2(4)(括号里数字是每一层选取的default box种类)中的每一个再分别采用两个3*3大小的卷积核进行卷积,这两个卷积核是并列的(括号里的数字代表prior box的数量,可以参考Caffe代码,所以上图中SSD结构的倒数第二列的数字8732表示的是所有prior box的数量,是这么来的38*38*4+19*19*6+10*10*6+5*5*6+3*3*4+1*1*4=8732),这两个3*3的卷积核一个是用来做localization的(回归用,如果prior box是6个,那么就有6*4=24个这样的卷积核,卷积后map的大小和卷积前一样,因为pad=1,下同),另一个是用来做confidence的(分类用,如果prior box是6个,VOC的object类别有20个,那么就有6*(20+1)=126个这样的卷积核)。

如下图是conv6_2的localizaiton的3*3卷积核操作,卷积核个数是24(6*4=24,由于pad=1,所以卷积结果的map大小不变,下同):这里的permute层就是交换的作用,比如你卷积后的维度是32×24×19×19,那么经过交换层后就变成32×19×19×24,顺序变了而已。而flatten层的作用就是将32×19×19×24变成32*8664,32是batchsize的大小。另一方面结合conv4_3(4),fc7(6),conv6_2(6),conv7_2(6),conv8_2(4),conv9_2(4)中的每一个和数据层(ground truth boxes)经过priorBox层生成prior box。

经过上述两个操作后,对每一层feature的处理就结束了。对前面所列的5个卷积层输出都执行上述的操作后,就将得到的结果合并:采用Concat,类似googleNet的Inception操作,是通道合并而不是数值相加。

Fig.5 SSD 流程

损失函数方面:和Faster RCNN的基本一样,由分类和回归两部分组成,可以参考Faster RCNN,这里不细讲。总之,回归部分的loss是希望预测的box和prior box的差距尽可能跟ground truth和prior box的差距接近,这样预测的box就能尽量和ground truth一样。

上面得到的8732个目标框经过Jaccard Overlap筛选剩下几个了;其中不满足的框标记为负数,其余留下的标为正数框。紧随其后:

训练过程中的 prior boxes 和 ground truth boxes 的匹配,基本思路是:让每一个 prior box 回归并且到 ground truth box,这个过程的调控我们需要损失层的帮助,他会计算真实值和预测值之间的误差,从而指导学习的走向。

SSD 训练的目标函数(training objective)源自于 MultiBox 的目标函数,但是本文将其拓展,使其可以处理多个目标类别。具体过程是我们会让每一个 prior box 经过Jaccard系数计算和真实框的相似度,阈值只有大于 0.5 的才可以列为候选名单;假设选择出来的是N个匹配度高于百分之五十的框吧,我们令 i 表示第 i 个默认框,j 表示第 j 个真实框,p表示第p个类。那么x_{ij}^p表示 第 i 个 prior box 与 类别 p 的 第 j 个 ground truth box 相匹配的Jaccard系数,若不匹配的话,则x_{ij}^p=0。总的目标损失函数(objective loss function)就由 localization loss(loc) 与 confidence loss(conf) 的加权求和:

  • N 是与 ground truth box 相匹配的 prior boxes 个数
  • localization loss(loc) 是 Fast R-CNN 中 Smooth L1 Loss,用在 predict box(l) 与 ground truth box(g) 参数(即中心坐标位置,width、height)中,回归 bounding boxes 的中心位置,以及 width、height
  • confidence loss(conf) 是 Softmax Loss,输入为每一类的置信度 c
  • 权重项 α,可在protxt中设置 loc_weight,默认设置为 1

使用注意

1. 使用batch_sampler做data argument时要注意是否crop的样本只包含目标很小一部分。

2.检查对于你的样本来说回归和分类问题哪个更难,以此调整multibox_loss_param中loc_weight进行训练。

3.正负样本比例,HARD_EXAMPLE方式默认只取64个最高predictions loss来从中寻找负样本,检查你的样本集中正负样本比例是否合适。

本文分享自微信公众号 - AI研习社(okweiwu)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-08-31

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏蜉蝣禅修之道

由浅入深CNN中卷积层与转置卷积层的关系

导语:转置卷积层(Transpose Convolution Layer)又称反卷积层或分数卷积层,在最近提出的卷积神经网络中越来越常见了,特别是在对抗生成神经...

854110
来自专栏marsggbo

DeepLearning.ai学习笔记(一)神经网络和深度学习--Week3浅层神经网络

介绍 DeepLearning课程总共五大章节,该系列笔记将按照课程安排进行记录。 另外第一章的前两周的课程在之前的Andrew Ng机器学习课程笔记(博...

24490
来自专栏目标检测和深度学习

深度 | 语义分割网络DeepLab-v3的架构设计思想和TensorFlow实现

选自Medium 作者:Thalles Silva 机器之心编译 参与:Nurhachu Null、刘晓坤 深度卷积神经网络在各类计算机视觉应用中取得了显著的成...

75870
来自专栏人工智能LeadAI

卷积,特征图,转置卷积和空洞卷积的计算细节

最近在做姿态估计的项目,在定制和实现卷积网络的时候发现自己对里面的一些计算细节还不够了解,所以整理了该文章,内容如下:

26940
来自专栏计算机视觉战队

卷积神经网络就是这么简单就能学会

卷积神经网络和前几次介绍的神经网络非常相似:它们都是由神经元组成,神经元中有具有学习能力的权重和偏差。每个神经元都得到一些输入数据,进行内积运算后再进行激活函数...

14720
来自专栏开心的学习之路

神经网络体系搭建(三)——卷积神经网络

本篇是神经网络体系搭建的第三篇,解决体系搭建的卷积神经网络相关问题,详见神经网络体系搭建(序) 卷积神经网络(CNN) ? CNN是什么 卷积神经网络是一种空间...

42480
来自专栏量子位

一文了解各种卷积结构原理及优劣

王小新 编译自 Medium 量子位 出品 | 公众号 QbitAI 卷积神经网络作为深度学习的典型网络,在图像处理和计算机视觉等多个领域都取得了很好的效果。 ...

40960
来自专栏专知

使用SSD进行目标检测:目标检测第二篇

【导读】近日,CV-Tricks.com发布了一篇文章,使用SSD进行目标检测,SSD是当前最流行的目标检测算法之一。作者从检测的基本概念、滑动窗口检测、减少滑...

61550
来自专栏人工智能

BP神经网络

BP(Back Propagation)神经网络是1986年由以Rumelhart和McCelland为首的科学家小组提出的,是一种按误差逆传播算法训练的多层前...

32590
来自专栏张洁的专栏

线性回归的高斯假设

在线性回归问题中,我们定义了损失函数,但是为什么用最小二乘(而不是三次方等)作为损失函数? 我们来尝试解决一个完整的线性回归问题。

73000

扫码关注云+社区

领取腾讯云代金券