其他SSD文章:https://blog.csdn.net/u010167269/article/details/52563573
https://blog.csdn.net/u014380165/article/details/72824889
https://blog.csdn.net/qianqing13579/article/details/82106664
SSD github : https://github.com/weiliu89/caffe/tree/ssd
SSD paper : https://arxiv.org/abs/1512.02325
SSD PPT:http://www.cs.unc.edu/~wliu/papers/ssd_eccv2016_slide.pdf
以下文章是本文的补充:
目标检测|SSD原理与实现:https://zhuanlan.zhihu.com/p/33544892
论文阅读:SSD: Single Shot MultiBox Detector : https://blog.csdn.net/u010167269/article/details/52563573
一、SSD网络总体架构
![](https://i-blog.csdnimg.cn/blog_migrate/06dd93f521821e462c1b19760236610e.png)
![](https://i-blog.csdnimg.cn/blog_migrate/3246a46453489e548656cb427af36b3f.png)
SSD采用VGG16作为基础模型,并且做了以下修改,如图1所示
- 分别将VGG16的全连接层FC6和FC7转换成 3x3 的卷积层 Conv6和 1x1 的卷积层Conv7
- 去掉所有的Dropout层和FC8层
- 同时将池化层pool5由原来的 stride=2 的 2x2 变成stride=1的 3x3 (猜想是不想reduce特征图大小)
- 添加了Atrous算法(hole算法),目的获得更加密集的得分映射
- 然后在VGG16的基础上新增了卷积层来获得更多的特征图以用于检测
二、算法细节
1、多尺度特征映射
![](https://i-blog.csdnimg.cn/blog_migrate/46ba71309b879c62a1f9449cf001d907.png)
如图3所示,左边的方法针对输入的图片获取不同尺度的特征映射,但是在预测阶段仅仅使用了最后一层的特征映射;而SSD(右图)不仅获得不同尺度的特征映射,同时在不同的特征映射上面进行预测,它在增加运算量的同时可能会提高检测的精度,因为它具有更多的可能性。
![](https://i-blog.csdnimg.cn/blog_migrate/c76707694b0b01211fc57379a0194b08.jpeg)
如图4所示,对于BB(bounding boxes)的生成,Faster-rcnn和SSD有不同的策略,但是都是为了同一个目的,产生不同尺度,不同形状的BB,用来检测物体。对于Faster-rcnn而言,其在特定层的Feature map上面的每一点生成9个预定义好的BB,然后进行回归和分类操作来进行初步检测,然后进行ROI Pooling和检测获得相应的BB;而SSD则在不同的特征层的feature map上的每个点同时获取6个(有的层是4个)不同的BB,然后将这些BB结合起来,最后经过NMS处理获得最后的BB。
原因剖析:
![](https://i-blog.csdnimg.cn/blog_migrate/66d7ade67ee0ece3a294865bb5bed931.jpeg)
如上图所示,输入一幅汽车的图片,我们将其输入到一个卷积神经网络中,在这期间,经历了多个卷积层和池化层,我们可以看到在不同的卷积层会输出不同大小的feature map(这是由于pooling层的存在,它会将图片的尺寸变小),而且不同的feature map中含有不同的特征,而不同的特征可能对我们的检测有不同的作用。总的来说,浅层卷积层对边缘更加感兴趣,可以获得一些细节信息(位置信息),而深层网络对由浅层特征构成的复杂特征更感兴趣,可以获得一些语义信息,对于检测任务而言,一幅图像中的目标有复杂的有简单的,对于简单的patch我们利用浅层网络的特征就可以将其检测出来,对于复杂的patch我们利用深层网络的特征就可以将其检测出来,因此,如果我们同时在不同的feature map上面进行目标检测,理论上面应该会获得更好的检测效果。
2、Default box 和 Prior box(先验框)
图片被送进网络之后先生成一系列 feature map,传统框架会在 feature map(或者原图)上进行 region proposal 提取出可能有物体的部分然后进行分类,这一步可能非常费时,所以 SSD 就放弃了 region proposal,而选择直接生成一系列 defaul box(筛选出prior boxes投入训练),然后以prior box 为初始bbox,将bboxes回归到正确的GT位置上去,预测出的定位信息实际上是回归后的bboxes和回归前的(prior box)的相对坐标。整个过程通过网络的一次前向传播就可以完成。
Defalut box:
![](https://i-blog.csdnimg.cn/blog_migrate/320895e9815692bff9a1394a76e1a967.jpeg)
Default box是指在feature map的每个单元格(cell)上都有一系列固定大小的box。SSD 训练图像中的 groundtruth 需要赋予到那些固定输出的 boxes 上,看下节Prior box概念。如上图所示,每个单元格使用了4个不同的Defalut box(虚线框,仔细看格子的中间有比格子还小的一个box),图片a中猫和狗分别采用最适合它们形状的Defalut box来进行训练。假设每个feature map cell有k个default box,那么对于每个default box都需要预测C(包括背景)个类别score和4个offset,因此如果一个feature map的大小是m*n,那么这个feature map就一共有K*m*n个default box,每个default box需要预测4个坐标相关的值和C(包括背景)个类别概率,则在m*n的特征图上面将会产生(C+4)* K * m * n个输出。这些输出个数的含义是:采用3×3的卷积核对该层的feature map卷积时卷积核的个数,包含两部分,实际code是分别用不同数量的3*3卷积核对该层feature map进行卷积:比如数量为C*K的卷积核对应confidence输出,表示每个default box的confidence,也就是类别的概率;数量为4*K的卷积核对应localization输出,表示每个default box回归后的坐标)。作者的实验也表明default box的shape数量越多,效果越好。
Defalut box分析:
![](https://i-blog.csdnimg.cn/blog_migrate/7417b5c6498baee247067494911c96b6.png)
SSD的一个核心是同时采用lower和upper的feature maps做检测。SSD中的Defalut box和Faster-rcnn中的anchor机制很相似。就是预设一些目标预选框,后续通过softmax分类+bounding box regression获得真实目标的位置。对于不同尺度的feature map 上使用不同的Default boxes。如上图所示,我们选取的feature map包括38x38x512、19x19x1024、10x10x512、5x5x256、3x3x256、1x1x256。具体怎么得到的看下面的表。我们总共可以获得8732个box,然后我们将这些box送入NMS模块中,获得最终的检测结果。
name | Out_size | Prior_box_num | Total_num |
conv4_3 | 38x38 | 4 | 5776 |
conv7(fc7) | 19x19 | 6 | 2166 |
conv8_2 | 10x10 | 6 | 600 |
conv9_2 | 5x5 | 6 | 150 |
conv10_2 | 3x3 | 4 | 36 |
conv11_2 | 1x1 | 4 | 4 |
8732 |
以上的操作都是在特征图上面的操作,即我们在不同尺度的特征图上面产生很多的bbox,如果映射到原始图像中,我们会获得一个密密麻麻的bbox集合,如下图所示:
![](https://i-blog.csdnimg.cn/blog_migrate/21c53b8c45011032045b93ae10ffb0ef.jpeg)
Prior 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匹配上。
Defalut box生成规则:
以feature map上每个点的中点为中心(offset=0.5),生成一些列同心的Defalut box(然后中心点的坐标会乘以step,相当于从feature map位置映射回原图位置)
正方形prior box最小边长为:,最大边长为:
每在prototxt设置一个aspect ratio,会生成2个长方形,长宽为: 和
![](https://i-blog.csdnimg.cn/blog_migrate/ffd359975ef976c0629fe4bb557292d7.jpeg)
而每个feature map对应Prior box的min_size和max_size由以下公式决定,公式中m是使用feature map的数量(SSD 300中m=6)
使用不同的ratio值,[1, 2, 3, 1/2, 1/3],通过下面的公式计算 default box 的宽度w和高度h:
而对于ratio=1的情况,指定的scale如下所示,即总共有 6 中不同的 default box
第一层feature map对应的min_size=S1,max_size=S2;第二层min_size=S2,max_size=S3;其他类推。在原文中,Smin=0.2,Smax=0.95。但是在SSD 300中prior box设置并不能和paper中上述公式对应:
min_size | max_size | |
---|---|---|
conv4_3 | 30 | 60 |
conv7(fc7) | 60 | 111 |
conv8_2 | 111 | 162 |
conv9_2 | 162 | 213 |
conv10_2 | 213 | 264 |
conv11_2 | 264 | 315 |
不过依然可以看出,SSD使用低层feature map检测小目标,使用高层feature map检测大目标,这也应该是SSD的突出贡献了。每一层中每一个点对应的prior box的个数,是由PriorBox这一层的配置文件决定的。其中SSD 300在conv4_3生成prior box的conv4_3_norm_priorbox层prototxt定义如下:
-
layer {
-
name:
"conv4_3_norm_mbox_priorbox"
-
type:
"PriorBox"
-
bottom:
"conv4_3_norm"
-
bottom:
"data"
-
top:
"conv4_3_norm_mbox_priorbox"
-
prior_box_param {
-
min_size:
30.0
-
max_size:
60.0
-
aspect_ratio:
2
-
flip: true
-
clip: false
-
variance:
0.1
-
variance:
0.1
-
variance:
0.2
-
variance:
0.2
-
step:
8
-
offset:
0.5
-
}
-
}
PS: min_size是必须要有的参数,否则不会进入对应的框的生成过程。论文跟实际代码是有一些出入的,Git上也有人在讨论这个,基本都选择无视论文。。。
这里还有一个比较关键的参数,就是step,在conv4-3中设置为8,这个又是怎么来的呢?
name | Out_size | Cal_scale | Real_scale |
conv4_3 | 38x38 | 7.8 | 8 |
conv7(fc7) | 19x19 | 15.78 | 16 |
conv8_2 | 10x10 | 30 | 32 |
conv9_2 | 5x5 | 60 | 64 |
conv10_2 | 3x3 | 100 | 100 |
conv11_2 | 1x1 | 300 | 300 |
实际就是原图与特征图 大小的比值,比如conv4_3 width = 38 ,输入的大小为300,那么scale=7.8,所以这里设置的step=8。这一部分的计算过程可以在 prior_box_layer.cpp的Forward_cpu中看到。
Prior box如何使用:
知道了Prior box如何产生,接下来分析Prior box如何使用。这里以conv4_3为例进行分析。
![](https://i-blog.csdnimg.cn/blog_migrate/e8e0004b5d4b65e8799c77f151798a80.png)
在conv4_3 feature map网络pipeline分为了3条线路,如上图:
1、经过一次batch norm+一次卷积后,生成了[1, num_class*num_priorbox, layer_height, layer_width]大小的feature用于softmax分类目标和非目标(其中num_class是目标类别,SSD 300的VOC数据集中num_class = 21)
2、经过一次batch norm+一次卷积后,生成了[1, 4*num_priorbox, layer_height, layer_width]大小的feature用于bounding box regression(即每个点一组偏移量[dxmin,dymin,dxmax,dymax])
3、生成了[1, 2, 4*num_priorbox]大小的prior box blob,其中2个channel分别存储prior box的4个点坐标和对应的4个variance。4个variance,这实际上是一种bounding regression中的权重。
后续通过softmax分类+bounding box regression即可从priox box中预测到目标。熟悉Faster RCNN的读者应该对上述过程应该并不陌生。其实pribox box的与Faster RCNN中的anchor非常类似,都是目标的预设框,没有本质的差异。区别是每个位置的prior box一般是4~6个,少于Faster RCNN默认的9个anchor;同时prior box是设置在不同尺度的feature maps上的,而且大小不同。
有一个细节是只有conv4_3层后加了一个Normalization 操作,其他的几层都没有,具体原因参考另一篇文章:Normalization on conv4_3 in SSD :https://blog.csdn.net/ytusdc/article/details/86612355
还有一个细节就是上面prototxt中的4个variance,这实际上是一种bounding regression中的权重。在图4线路(2)中,网络输出[dxmin,dymin,dxmax,dymax],即对应下面代码中bbox;然后利用如下方法进行针对prior box的位置回归:
-
decode_bbox->set_xmin(
-
prior_bbox.xmin() + prior_variance[
0] * bbox.xmin() * prior_width);
-
decode_bbox->set_ymin(
-
prior_bbox.ymin() + prior_variance[
1] * bbox.ymin() * prior_height);
-
decode_bbox->set_xmax(
-
prior_bbox.xmax() + prior_variance[
2] * bbox.xmax() * prior_width);
-
decode_bbox->set_ymax(
-
prior_bbox.ymax() + prior_variance[
3] * bbox.ymax() * prior_height);
上述代码可以在SSD box_utils.cpp的void DecodeBBox()函数见到。
Permute,Flatten And Concat Layers:
上一节以conv4_3 层分析了如何检测到目标的真实位置,但是SSD 300是使用包括conv4_3在内的共计6个feature maps一同检测出最终目标的。在网络运行的时候显然不能一个feature map单独计算一次softmax socre+box regression(虽然原理如此,但是不能如此实现)。那么多个feature maps如何协同工作?这时候就要用到Permute,Flatten和Concat这3种层了。其中conv4_3_norm_mbox_conf_perm的prototxt定义如下:
-
layer {
-
name:
"conv4_3_norm_mbox_conf_perm"
-
type:
"Permute"
-
bottom:
"conv4_3_norm_mbox_conf"
-
top:
"conv4_3_norm_mbox_conf_perm"
-
permute_param {
-
order:
0
-
order:
2
-
order:
3
-
order:
1
-
}
-
}
Permute是SSD中自带的层,Permute相当于交换blob中的数据维度。在正常情况下blob的顺序为:
bottom blob = [batch_num, channel, height, width]
经过conv4_3_norm_mbox_conf_perm后的blob为:
top blob = [batch_num, height, width, channel]
而Flattlen和Concat层都是caffe自带层。所有操作相当于各层输出中把channel放到了最后一个维度然后逆序相乘再总的相加。具体这两个层的细节参考另一篇文章:
深度学习中Concat层和Flatten层作用 :https://blog.csdn.net/ytusdc/article/details/86610897。
加入这几个层的原因分析:
SSD的 XX_conf 和 XX_loc层的输出,是用通道来保存特征向量的,所以这里需要将通道数调整到最后,也就是 permute所做的事情。通过该层后,数据的顺序被换成了 NHWC,再通过 flatten拉成一列。
Feature map合并方法:
![](https://i-blog.csdnimg.cn/blog_migrate/3b9e51fa3bfd5cdedcad89dc5732e445.png)
现在以conv4_3和fc7为例分析SSD是如何将不同size的feature map组合在一起进行prediction。上图展示了conv4_3和fc7合并在一起的过程中shape变化(其他层类似)。
1、对于conv4_3 feature map,conv4_3_norm_priorbox(priorbox层)设置了每个点共有4个prior box。由于SSD 300共有21个分类,所以conv4_3_norm_mbox_conf的channel值为num_priorbox * num_class = 4 * 21 = 84;而每个prior box都要回归出4个位置变换量[dx,dy,dx,dymax],所以conv4_3_norm_mbox_loc的channel值为4 * 4 = 16。
2、fc7每个点有6个prior box,其他feature map同理。
3、经过一系列图展示的shape变化后,最后拼接成mbox_conf和mbox_loc。而mbox_conf后接reshape,再进行softmax(为何在softmax前进行reshape,Faster RCNN有提及)。
4、最后这些值输出detection_out_layer,获得检测结果。
三、SSD训练过程:
jaccard overlap 计算示意图(其实就是IOU,叫法不同而已):
![](https://i-blog.csdnimg.cn/blog_migrate/e36b8dffb6346ba1cffa8e345dc36b6b.png)
然后看一张训练流程图,比较清晰明了:
![](https://i-blog.csdnimg.cn/blog_migrate/c7d9399c80a03c9600ec3d35d58d13aa.jpeg)
(1)每一个 prior box 经过Jaccard系数计算和真实框的相似度。
(2)阈值只有大于 0.5 的才可以列为候选名单;假设选择出来的是N个匹配度高于百分之五十的框。
(3)我们令 i 表示第 i 个默认框,j 表示第 j 个真实框,p表示第p个类。那么 表示 第 i 个 prior box 与 类别 p 的 第 j 个 ground truth box 相匹配的Jaccard系数,若不匹配的话,则
=0 。
(4)总的目标损失函数(objective loss function)为 localization loss(loc) 与 confidence loss(conf) 的加权求和。
损失函数 Loss计算:
总体目标损失函数定位损失(loc)和置信度损失(conf)的加权和:
对于SSD,虽然paper中指出采用了所谓的“multibox loss”,但是可以看到与常见的 Object Detection模型的目标函数相同,SSD算法的目标函数分为两部分:计算相应的default box与目标类别的confidence loss以及相应的location loss(位置回归)。其中N是匹配到GT(Ground Truth)的prior box数量,如果N=0,则将损失设为0;而 α 参数用于调整confidence loss和location loss之间的比例,默认 α=1。
SSD中的confidence loss是是在多类别置信度(c)上的softmax loss,公式如下:
其中 i 指代搜索框序号,j 指代真实框序号,p 指代类别序号,p=0 表示背景。其中中取1表示第 i 个prior box匹配到第 j 个GT box,而这个GT box的类别为 p 。
表示第i个搜索框对应类别p的预测概率。此处有一点需要关注,公式前半部分是正样本(Pos)的损失,即分类为某个类别的损失(不包括背景),后半部分是负样本(Neg)的损失,也就是类别为背景的损失。
而location loss(位置回归)是典型的smooth L1 loss:
其中, 为预测框,
为 ground truth。
为补偿(regress to offsets)后的默认框
的中心,
为默认框的宽和高
更详细的解释看一看下图:
1、Matching strategy(匹配策略):
在训练时,ground truth boxes 与 default boxe(就是prior boxes) 按照如下方式进行配对:
- 第一个原则:从ground truth box出发,寻找与每一个ground truth box有最大的jaccard overlap的default box,这样就能保证每一个groundtruth box一定与一个default box对应起来(所谓的jaccard overlap就是IOU,如图12)。 反之,若一个prior box没有与任何ground truth进行匹配,那么该prior box只能与背景匹配,就是负样本。一个图片中ground truth是非常少的, 而default box却很多,如果仅按第一个原则匹配,很多default box会是负样本,正负样本极其不平衡,所以需要第二个原则。
- 第二个原则:从default box出发,对剩余的还没有配对的default box与任意一个ground truth box尝试配对,只要两者之间的jaccard overlap大于阈值(一般是0.5),那么该default box也与这个ground truth进行匹配。这意味着某个ground truth可能与多个Prior box匹配,这是可以的。但是反过来却不可以,因为一个prior box只能匹配一个ground truth,如果多个ground truth与某个prior box的 IOU 大于阈值,那么default box只与IOU最大的那个Prior box进行匹配。注意:第二个原则一定在第一个原则之后进行,仔细考虑一下这种情况,如果某个ground truth所对应最大 IOU小于阈值,并且所匹配的Prior box却与另外一个ground truth的 IOU大于阈值,那么该Prior box应该匹配谁,答案应该是前者,首先要确保某个ground truth一定有一个Prior box与之匹配。但是,这种情况我觉得基本上是不存在的。由于Prior box很多,某个ground truth的最大 IOU 肯定大于阈值,所以可能只实施第二个原则既可以了。
- 显然配对到GT的default box就是positive,没有配对到GT的default box就是negative。只有正样本才会参与loss的计算。
![](https://i-blog.csdnimg.cn/blog_migrate/6e8c9c2ef185d0322b46ad935d0ef898.jpeg)
图14为一个匹配示意图,其中绿色的GT是ground truth,红色为Prior box,FP表示负样本,TP表示正样本。
2、Hard negative mining:
值得注意的是,一般情况下negative default boxes数量>>positive default boxes数量,直接训练会导致网络过于重视负样本,从而loss不稳定。为了保证正负样本尽量平衡,SSD在训练时采用了hard negative mining,即依据confidience loss对default box进行排序,挑选其中confidience loss高的box进行训练,将正负样本的比例控制在positive:negative=1:3。显而易见,用来训练网络的负样本为提取的负样本的子集,那么,我们当然选择负样本中容易被分错类的困难负样本来进行网络训练这样会取得更好的效果。有下面一种说法:SSD采用了hard negative mining,就是对负样本进行抽样,抽样时按照置信度误差(预测背景的置信度越小,误差越大)进行降序排列,选取误差的较大的top-k作为训练的负样本,以保证正负样本比例接近1:3。--自己还没有仔细验证。以后搞明白后补充。下面提供的是正负样本都做难例子挖掘。
具体过程如下:
正负样本区分:(通过定位信息(iou)初步划分,而后通过loss把hard example留下,loss越大越hard)
(2.1) 正样本获得
已经确定 default box,结合 ground truth,下一步要将 default box 匹配到 ground truth 上,根据上面两个原则,从 groudtruth box 出发给每个 groudtruth box 找到了最近(IOU最大)的 default box 放入候选正样本集。然后再从 default box 出发为 default box 集中寻找与 groundtruth box 满足 IOU>0.5 的的default box放入候选正样本集。
(2.2) 负样本获得(这是一个难例挖掘的过程)
在生成 prior boxes 之后,会产生很多个符合 ground truth box 的 positive boxes(候选正样本集),但同时,不符合 ground truth boxes 也很多,而且这个 negative boxes(候选负样本集),远多于 positive boxes。这会造成 negative boxes、positive boxes 之间的不均衡。训练时难以收敛。
(2.3)难例挖掘
将每一个GT上对应prior boxes的分类loss 进行排序。
对于候选正样本集:选择loss最高的m个 prior box 与候选正样本集匹配 (box 索引同时存在于这两个集合里则匹配成功),匹配不成功则从候选正样本集中删除这个正样本(因为这个正样本loss太低,易被识别,所以不在难例里,已经很接近 ground truth box 了,不需要再训练);
对于候选负样本集:选择loss最高的m个prior box 与候选负样本集匹配,匹配成功的则留下来作为最后的负样本,不成功剔除出候选负样本集,因为他们loss不够大,易被识别为背景,训练起来没难度没提升空间。
(2.4)举例:假设在这 8732 个 default box 里,经过 FindMatches 后得到候选正样本 P 个,候选负样本那就有 8732−P个。将 prior box 的 prediction loss 按照从大到小顺序排列后选择最高的 M个 prior box。如果这 P 个候选正样本里有 a 个 box 不在这 M 个 prior box 里,则将这 a个 box 从候选正样本集中踢出去。如果这 8732−P个候选负样本集中有 b个在这 M 个 prior box,则将这b个候选负样本作为正式负样本。即删除易识别的正样本,同时留下典型的负样本,组成1:3的prior boxes样本集合。SSD 算法中通过这种方式来保证 positives、negatives 的比例。
(2.5)Hard example mining
example mining 是选择出特定样本来计算损失函数;从实际问题出发 hard example 应该就是指定位较困难或分类较困难或者两者都困难的候选框。SSD 的 caffe 中支持 negative mining 和 hard example mining,当 share_location 参数为 true 时,只支持 negative mining。
Hard negative example 或 Hard positive example 的定义需要首先确定某个候选框是 negative example 还是 positive example。比如 SSD 中将与任意 gt_bbox 的 IOU 超过给定阈值 overlap_threshold(SSD 默认为 0.5)的当作正样本,即前景类别为正样本,背景类别为负样本。比如,极端的例子,当图像中没有 gt_bbox 时,那么所有的 default bboxes 都是 negative example。
SSD 中 negative mining 只计算分类损失而不计算定位损失,而 hard example mining 对分类损失和定位损失都进行计算。
SSD 的 negative mining 的过程为:
1)生成default bboxes,每个检测器对应特征图生成的default boxes数目为n*n*6或n*n*4;
2)匹配default boxes,将每个 default box 与 ground truth 匹配,保证每个ground truth 都能对应多个default boxes,避免漏检;
3)衡量default boxes,当第 i 个 default box 被匹配到第 j 个 gt_bbox,那么计算其属于背景类别的 softmax loss 或 cross entropy loss 值;
![](https://i-blog.csdnimg.cn/blog_migrate/be9e69b5817845f9701bee6d15e231f8.jpeg)
4)筛选default boxes, 计算完所有default boxes 的分类 loss后,按照 loss 排序,选择 loss 较大且与任意 gt_bbox 之间的 iou 小于 阈值neg_overlap 的样本中的前 3*num_positive 个负样本(保证留下的负样本“够坏”,同时保证1:3的正负比例)。
而后,这正负比为1:3的部分default boxes就是筛选全体default box后剩下的prior boxes,用这些prior box作为参考,对所有预测框其进行分类和回归,进行反向传播更新网络参数,即训练。
3、Data augmentation(数据增强):
![](https://i-blog.csdnimg.cn/blog_migrate/9c51c3937736cc3712760bc3554663c7.jpeg)
数据增强,即每一张训练图像,随机的进行如下几种选择:
1、使用原始的图像
2、采样一个 patch,与物体之间最小的 jaccard overlap 为:0.1,0.3,0.5,0.7 或 0.9
3、随机的采样一个 patch,采样的 patch 是原始图像大小比例是[0.1,1],aspect ratio在 1/2与2之间。当 groundtruth box 的 中心(center)在采样的patch中时,保留重叠部分。在这些采样步骤之后,每一个采样的patch被resize到固定的大小,并且以0.5的概率随机的 水平翻转(horizontally flipped)。
主要采用的技术有水平翻转(horizontal flip),随机裁剪加颜色扭曲(random crop & color distortion),随机采集块域(Randomly sample a patch)(获取小目标训练样本)
如上图所示,SSD算法使用了多种数据增强的方法,包括水平翻转(horizontal flip),随机裁剪(random crop)、颜色扭曲(color distortion 或者对比度调整),随机采集块域(Randomly sample a patch------目的———获取小目标训练样本)等。论文明确指出,数据增强可以明显的提高算法的性能。主要的目的是为了使得该算法对输入的不同大小和不同形状的目标具有更好的鲁棒性。直观的理解是通过这个数据增强操作可以增加训练样本的个数,同时构造出更多的不同形状和大小的目标,将其输入到网络中,可以使得网络学习到更加鲁棒的特征。
其实Matching strategy,Hard negative mining,Data augmentation,都是为了加快网络收敛而设计的。尤其是Data augmentation,翻来覆去的randomly crop,保证每一个prior box都获得充分训练而已。不过当数据达到一定量的时候,不建议再进行Data augmentation,毕竟”真”的数据比“假”数据还是要好很多。
4、Atrous Algothrim(获得更加密集的得分映射)
![](https://i-blog.csdnimg.cn/blog_migrate/96c671faec03061f6c37f60e3278f5be.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/7c73ab246775b1b63491b2aba400aada.jpeg)
作用:既想利用已经训练好的模型进行fine-tuning,又想改变网络结构得到更加dense的score map。这个解决办法就是采用Hole算法。如上图(a) (b)所示,在以往的卷积或者pooling中,一个filter中相邻的权重作用在feature map上的位置都是物理上连续的。如上图(c)所示,为了保证感受野不发生变化,某一层的stride由2变为1以后,后面的层需要采用hole算法,具体来讲就是将连续的连接关系是根据hole size大小变成skip连接的(图(c)为了显示方便直接画在本层上了)。不要被(c)中的padding为2吓着了,其实2个padding不会同时和一个filter相连。 pool4的stride由2变为1,则紧接着的conv5_1, conv5_2和conv5_3中hole size为2。接着pool5由2变为1, 则后面的fc6中hole size为4。
Atrous Algothrim理解2:
如上图所示,Atrous Algothrim可以在提高feature map大小的同时提高接收场的大小,即可以获得更加密集的score map。
5、NMS(非极大值抑制)
在SSD算法中,NMS至关重要,因为多个feature map 最后会产生大量的BB,然而在这些BB中存在着大量的错误的、重叠的、不准确的BB,这不仅造成了巨大的计算量,如果处理不好会影响算法的性能。仅仅依赖于IOU(即预测的BB和GT的BB之间的重合率)是不现实的,IOU值设置的太大,可能就会丢失一部分检测的目标,即会出现大量的漏检情况;IOU值设置的太小,则会出现大量的重叠检测,会大大影响检测器的性能,因此IOU的选取也是一个经验活,常用的是0.65,建议使用论文中作者使用的IOU值,因为这些值一般都是最优值。即在IOU处理掉大部分的BB之后,仍然会存在大量的错误的、重叠的、不准确的BB,这就需要NMS进行迭代优化。
四、SSD性能评估
1、模块性能评估
![](https://i-blog.csdnimg.cn/blog_migrate/702630b6703cc625f5e239f0aa8ad420.jpeg)
观察上图可以得到如下的结论:
数据增强方法在SSD算法中起到了关键性的作用,使得mAP从65.5变化到71.6,主要的原因可能是数据增强增加了样本的个数,使得模型可以获得更多不一样的样本,即提高了样本的多样性,使得其具有更好的鲁棒性,从而找到更接近GT的BB。
[1/2,2]和[1/3, 3]box可以在一定程度上提升算法的性能,主要的原因可能是这两种box可以在一定程度上增加较大和较小的BB,可以更加准确的检测到较大和较小的目标,而且VOC数据集上面的目标一般都比较大。当然,更多的比例可以进一步提升算法的性能。
atrous算法可以轻微提升算法性能,但是其主要的作用是用来提速,论文中表明它可以提速20%。主要的原因可能是虽然该算法可以获得更大的feature map和接收场,但是由于SSD本身利用了多个feature map来获取BB,BB的多样性已经足够,由于feature map扩大而多得到的BB可能是一些重复的,并没有起到提升检测性能的作用。
2、SSD加速的原因
![](https://i-blog.csdnimg.cn/blog_migrate/d95dc4a3b814edfd189f2c5e307cc20d.jpeg)
如上图所示,当Faster-rcnn的输入分辨率为1000x600时,产生的BB是6000个;当SSD300的输入分辨率为300x300时,产生的BB是8372个;当SSD512的输入分辨率为512x512时,产生的BB是24564个,大家像一个情况,当SSD的分辨率也是1000x600时,会产生多少个BB呢?这个数字可能会很大!但是它却说自己比Faster-rcnn和YOLO等算法快很多,我们来分析分析原因。
原因1:首先SSD是一个单阶段网络,只需要一个阶段就可以输出结果;而Faster-rcnn是一个双阶段网络,尽管Faster-rcnn的BB少很多,但是其需要大量的前向和反向推理(训练阶段),而且需要交替的训练两个网络;
原因2:Faster-rcnn中不仅需要训练RPN,而且需要训练Fast-rcnn,而SSD其实相当于一个优化了的RPN网络,不需要进行后面的检测,仅仅前向推理就会花费很多时间;
原因3:YOLO网络虽然比SSD网络看起来简单,但是YOLO网络中含有大量的全连接层,和FC层相比,CONV层具有更少的参数;同时YOLO获得候选BB的操作比较费时;
原因4:SSD算法中,调整了VGG网络的架构,将其中的FC层替换为CONV层,这一点会大大的提升速度,因为VGG中的FC层都需要大量的运算,有大量的参数,需要进行前向推理;
原因5:使用了atrous算法,具体的提速原理还不清楚,不过论文中明确提出该算法能够提速20%。
原因6:SSD设置了输入图片的大小,它会将不同大小的图片裁剪为300x300,或者512x512,和Faster-rcnn相比,在输入上就会少很多的计算,不要说后面的啦,不快就怪啦!!!
3、训练结果图
训练迭代了130K次,学习率为0.001(出现跳跃是因为之前没有加入VGG16的checkpoint),可以发现在100K次之后基本没有太大变化趋于收敛状态,最后第130K次时候的loss=3.4。
![](https://i-blog.csdnimg.cn/blog_migrate/05ad7f6c29fa148ca022e8792465d1bb.jpeg)
其中用于softmax分类的cross_entrpy和localization的loss也基本收敛以及正负样本个数 如下变化:
![](https://i-blog.csdnimg.cn/blog_migrate/1adb84962ce22d4319b1890b4a8deae9.jpeg)
训练后SSD300在VOC2007的mAP为62%,论文中为68%。
五、SSD网络结构优劣分析
优点:
SSD算法的优点应该很明显:运行速度可以和YOLO媲美,检测精度可以和Faster RCNN媲美。SSD对不同横纵比的object的检测都有效,这是因为算法对于每个feature map cell都使用多种横纵比的default boxes,这也是本文算法的核心。最后本文也强调了增加数据集的作用,包括随机裁剪,旋转,对比度调整等等。
缺点:
1、需要人工设置prior box的min_size,max_size和aspect_ratio值。网络中prior box的基础大小和形状不能直接通过学习获得,而是需要手工设置。而网络中每一层feature使用的prior box大小和形状恰好都不一样,导致调试过程非常依赖经验。(相比之下,YOLO2使用聚类找出大部分的anchor box形状,这个思想能直接套在SSD上)
2、虽然采用了pyramdial feature hierarchy的思路,但是对小目标的recall依然一般,并没有达到碾压Faster RCNN的级别。作者认为,这是由于SSD使用conv4_3低级feature去检测小目标,而低级特征卷积层数少,存在特征提取不充分的问题。所以增加输入图像的尺寸对于小的object的检测有帮助。另外增加数据集(此处主要是指裁剪)对于小的object的检测也有帮助,原因在于随机裁剪后的图像相当于“放大”原图像,所以这样的裁剪操作不仅增加了图像数量,也放大了图像。