SSD学习笔记
目标检测算法——SSD:Single Shot MultiBox Detector,是一篇非常经典的目标检测算法,十分值得阅读和进行代码复现,其论文地址是:https://arxiv.org/abs/1512.02325
一、前言
1.1 什么是SSD
从论文的题目《SSD:Single Shot MultiBox Detector》可以看出,single shot表明是one_stage检测算法,即不需要类似faster R-CNN中的RPN等区域推荐算法,一步就能得到预测坐标和类别,实现真正的end-to-end训练;multibox表示是多框预测,即SSD算法借鉴了faster R-CNN中的锚点框思想,对每个先验锚点框进行预测,判断其类别和目标的预测框。
1.2 为什么提出SSD
在SSD算法提出之前,R-CNN系列的目标检测算法,其准确率很高,但是这些算法需要消耗大量计算资源,特别是对于嵌入式设备或者终端设备,其算力无法满足此类算法,造成了无法进行实时目标检测。
目标检测的检测速度通常使用FPS进行衡量,即1秒能处理多少帧。Faster R-CNN的检测速度只有7FPS,虽然已经比以前的算法快很多了,但远远还达不到实时检测的效果。虽然后续对faster R-CNN做了很多改进来提高FPS,但这些增益都是以牺牲大量精度为前提。
因此,急需一种速度快且精度不低的目标检测算法。
1.3 如何平衡速度与精度
如下图所示,下图是R-CNN系列,YOLO和SSD的性能对比图(Ref.《目标检测算法之SSD》),可以看出SSD在速度和mAP上都有较大的提升。
那么,SSD能实现速度与精度的平衡,是通过以下方式来实现的:
a) 改变网络结构,并使用多尺度融合;
b) 精心设计先验锚点框,和锚点框匹配策略;
c) 使用多个tricks来提高精度,如用于平衡正负样本数量的难例挖掘(hard negative mining)和数据增强。
二、网络结构
如图1所示,是SSD的网络结构。在论文中,图片的输入尺寸为300*300*3,使用VGG16作为主干网络,同时,做出了以下修改:
- 将原本VGG16的FC6和FC7换成卷积层Conv6和Conv7,并依次加入新的层:Conv8_2,Conv9_2,Conv10_2,Conv11_2。具体而言,在Conv7层的特征图为19*19*1024,经过1*1*256和3*3*512-s2的卷积操作后,得到Conv8_2的特征图,其尺寸为10*10*512,依次类推。
- 为了实现多尺度融合,需要将不同层的特征图提取出来进行判断。在论文中,作者使用Conv4_3、Conv7、Conv8_2、Conv9_2、Conv10_2和Conv11_2的特征图来进行多尺度融合。如图2所示,每层特征图会分别经过3*3的卷积,得到2个tensor,分别用于进行坐标预测和类别置信度预测。其中,用于坐标预测的通道数是(num_anchor*4),num_anchor表示该特征图每个位置对应的锚点框数量,4表示(x_min,y_min,x_max,y_max);用于类别置信度预测的通道数是(num_anchor*num_classes),num_classes表示类别的数量(包含背景),对于VOC来说,num_classes=21,20个类别加上1个背景。另外,论文中会对Conv4_3层的特征图使用L2归一化后,再进行3*3的卷积,这样做的目的是,防止此层特征图的值过大,利于收敛。
对于需要融合的特征图,假设此特征图的尺寸是w*h,那么,对于每个位置(x,y),会预先生成N个锚点框(具体锚点框的细节,下面会叙述),因此,每张特征图会生成w*h*N个锚点框。SSD通过对每个锚点框进行位置回归和类别预测,并通过NMS非极大值抑制得到最终的检测结果。
SSD算法会生成一系列预测框(bounding boxes)和每个预测框的得分,然后通过NMS非极大值抑制得到最终的检测结果。如下图所示,是SSD的网络结构。
图1 SSD的网络结构
图2 特征图的处理
三、锚点框
SSD的锚点框借鉴了faster R-CNN的锚点框思想,但不同的是,在SSD中,每个特征图对应的锚点框均不相同,即锚点框会根据特征图的尺寸发生变化。例如,Conv4_3的锚点框和Conv7的锚点框的尺寸是不一样的。假定使用m张特征图进行预测判断,每张特征图的锚点框大小,可以通过下式进行计算:
$$s_k=s_{min}+\frac{s_{max}-s_{min}}{m-1}(k-1),k\in [1,m]$$
其中,$s_{min}=0.2$和$s_{max}=0.9$,表示Conv4_3特征图的锚点框的尺寸为0.2,Conv11_2特征图的锚点框尺寸为0.9。既然有了锚点框的大小,可以理解为面积,接下来就需要为锚点框设置不同的宽高比。作者设置了5种宽高比,分别是$a_r={1,2,3,1/2,1/3}$,因此,可以计算得到宽度$w_k^a=s_k\sqrt{a_r}$,高度为$h_k^a=s_k/\sqrt{a_r}$。对于宽高比为1的情况,额外增加一个锚点框,其尺寸为${s_k}'=\sqrt{s_ks_{k+1}}$。所以,一般而言,第i层特征图的(x,y)位置,具有6个锚点框。而第一层特征图和最后两层层特征图,每个位置只设置4个锚点框。因此,图1中的8732个锚点框是这样计算得到的,$38*38*4+19*19*6+10*10*6+5*5*6+3*3*4+1*1*4=8732$。
通过对不同特征图设置不同的锚点框,有利于检测不同尺寸的物体,大特征图可检测小物体,小特征图可以检测大物体。如图3所示,(a)表示带GT框的图像;(b)表示在8*8的特征图中,每个位置使用6个不同尺寸的锚点框,当某个锚点框与GT框的IOU大于阈值时,将其设置成正样本,该位置下其他锚点框为负样本;(c)表示4*4特征图下,红色虚线框用于预测狗的情况,会输出loc和conf两个tensor,loc表示相对于锚点框的偏移量,conf表示每个类别的置信度。
图3 锚点框匹配
当设定了锚点框后,就需要制定其匹配规则,即制定哪些锚点框用于回归GT框和预测类别。首先,为每个GT框匹配一个与其IOU最高的先验锚点框,保证了每个GT框都有对应的锚点框,来预测GT框;其次,当GT框与先验锚点框的IOU大于阈值(0.5)时,也指定该锚点框用来预测该GT框。当然,若锚点框A与多个GT框的IOU都大于阈值,则该锚点框A选择与其IOU最大的GT框。
图4是锚点框与GT框的匹配示意图,为了方便理解,将锚点框映射回原图尺寸,与GT框进行匹配。
图4 锚点框与GT框的匹配
四、其余策略
- SSD的损失函数继承了R-CNN系列的损失函数,如下所示,由位置损失和置信度损失组成,位置损失使用了smooth1,置信度损失使用多类别交叉熵:
$$L(x,c,l,g)=\frac{1}{N}(L_{conf}(x,c)+\alpha L_{loc}(x,l,g))L(x,c,l,g)=\frac{1}{N}(L_{conf}(x,c)+\alpha L_{loc}(x,l,g))$$
- 此外,SSD可以理解成对图片进行密集采样,得到8732个patch,然后对这些patch进行预测和回归。因此,会发现,大部分锚点框都会匹配上背景,也就是被设置成负样本。因此,会造成正负样本之间的不平衡。对于此情况,SSD使用了hard negative mining策略来缓解这一锚段。在SSD中,并没有使用所有的负样本,而是将这些匹配上背景的样本根据置信度损失进行降序排列,取出置信度损失进行排序,将损失较大的样本认为是难例(hard negative),需要模型重点学习。选取损失最大的前N个样本作为负样本,正样本与负样本的比例控制在1:3左右,对于那些没有选上的样本,label设置成-1,不参与训练当中。
- 为了扩大感受野,加快推理速度,还使用了空洞卷积。
- SSD中还采用了数据增强的策略,如对原图进行色域变换、扩增、采样的操作,具体可以参考这篇文章。
五、实验结果
(1)VOC测试结果
下表是SSD在VOC的实验结果图。与Fast R-CNN和Faster R-CNN进行对比,分别使用了300*300和 512*512的图片作为输入。在07+12+COCO数据集上来看,SSD300比Faster R-CNN的mAP提高了0.8%,SSD512提高了2.8%。此外,SSD的定位误差更小,因为SSD是直接回归目标的形状和进行分类,将定位和分类合成了一步。但是,对于相似目标,SSD容易产生混淆,可能是因为对不同种类的目标共享了位置。SSD还容易预测框尺寸的干扰,即在小目标上其性能比大目标要差。作者认为这可能是由于在浅层的时候,小目标物体包含的信息不多。当增加了分辨率的时候,这种情况得到了较好的改善。
(2)模型分析
为了了解SSD中各组成对结果的影响程度,作者使用SSD300进行了控制变量实验,结果如下图所示。
- 数据增强:在R-CNN系列中,采用的是原图或者对原图进行翻转等变换。而SSD中,使用了更多的策略,包括扩增、采样等。可以看出,使用数据增强的SSD,mAP提高了8.8%。但作者认为,同样的数据增强策略,对R-CNN系列可能会失效,因为在进入分类头的时候,使用了特征池化。
- 锚点框的多样性:在SSD中,对特征图的每个位置使用了6个不同形状的锚点框,每层特征图的锚点框也均不一致。当移除锚点框后,mAP都出现了不同比例的下降。使用不同尺寸的锚点框,使网络能更加简单对锚点框进行回归。但是不是锚点框越多越好呢?锚点框越多,推理速度也就越慢。这中间应该会有折中。
- 空洞卷积:在本实验中,使用的是带空洞卷积版本的VGG16。如果使用完全版本的VGG16,即保留pool5和对fc6/fc7不使用下采样,增加conv5_3进行特征融合。这样的话,能得到相同精度的结果,但速度却慢了20%。
- 多尺度融合:SSD的主要贡献在于在不同分辨率的特征层中使用了不同尺寸的锚点框,进行多尺度融合。为了比较这一做法的影响,作者去除某些用于特征融合的层,实验的结果如下表所示。为了保证一致性,锚点框的数量保持接近8732。可以看出,当特征层越来越少的时候,mAP也会随之下降,从74.3下降到62.4。
(3)推理时间
下表是SSD的推理时间对比图。可以看出,SSD中精度和速度上做到了比较好的平衡。
SSD是一种很优秀的one-stage框架,对后面很多目标检测算法有着深远的影响。读完论文,发现还是对SSD的了解不够深入,接下来,会对其源码进行分析。
SSD学习笔记的更多相关文章
- 深度学习笔记(十三)YOLO V3 (Tensorflow)
[代码剖析] 推荐阅读! SSD 学习笔记 之前看了一遍 YOLO V3 的论文,写的挺有意思的,尴尬的是,我这鱼的记忆,看完就忘了 于是只能借助于代码,再看一遍细节了. 源码目录总览 tens ...
- 深度学习笔记(七)SSD 论文阅读笔记简化
一. 算法概述 本文提出的SSD算法是一种直接预测目标类别和bounding box的多目标检测算法.与faster rcnn相比,该算法没有生成 proposal 的过程,这就极大提高了检测速度.针 ...
- 深度学习笔记(七)SSD 论文阅读笔记
一. 算法概述 本文提出的SSD算法是一种直接预测目标类别和bounding box的多目标检测算法.与faster rcnn相比,该算法没有生成 proposal 的过程,这就极大提高了检测速度.针 ...
- [学习笔记] SSD代码笔记 + EifficientNet backbone 练习
SSD代码笔记 + EifficientNet backbone 练习 ssd代码完全ok了,然后用最近性能和速度都非常牛的Eifficient Net做backbone设计了自己的TinySSD网络 ...
- Java学习笔记(04)
Java学习笔记(04) 如有不对或不足的地方,请给出建议,谢谢! 一.对象 面向对象的核心:找合适的对象做合适的事情 面向对象的编程思想:尽可能的用计算机语言来描述现实生活中的事物 面向对象:侧重于 ...
- 学习笔记:The Log(我所读过的最好的一篇分布式技术文章)
前言 这是一篇学习笔记. 学习的材料来自Jay Kreps的一篇讲Log的博文. 原文很长,但是我坚持看完了,收获颇多,也深深为Jay哥的技术能力.架构能力和对于分布式系统的理解之深刻所折服.同时也因 ...
- Oracle User Management FAQ翻译及学习笔记
转载 最近了解到AME 的东西,很迫切,先转载一篇 [@more@] Oracle User Management FAQ翻译及学习笔记 写在前面 本文主要是翻译的英文版的Oracle User Ma ...
- 学习笔记:The Log(我所读过的最好的一篇分布式技术文章)
前言 这是一篇学习笔记. 学习的材料来自Jay Kreps的一篇讲Log的博文. 原文非常长.可是我坚持看完了,收获颇多,也深深为Jay哥的技术能力.架构能力和对于分布式系统的理解之深刻所折服.同一时 ...
- OpenCV 学习笔记 07 目标检测与识别
目标检测与识别是计算机视觉中最常见的挑战之一.属于高级主题. 本章节将扩展目标检测的概念,首先探讨人脸识别技术,然后将该技术应用到显示生活中的各种目标检测. 1 目标检测与识别技术 为了与OpenCV ...
随机推荐
- Linux 通道
简单地说,一个通道接受一个工具软件的输出,然后把那个输出输入到其它工具软件.使用UNIX/Linux的词汇,这个通道接受了一个过程的标准输出,并把这个标准的输出作为另一个过程的标准输入.如果你没有重新 ...
- easy dragging script
下面的ahk脚本提供了windows下alt dragging的能力: ; Easy Window Dragging -- KDE style (requires XP/2k/NT) -- by Jo ...
- 从Docker在Linux和Windows下的区别简单理解Docker的层次结构
上篇文章我们成功在Windows下安装了Docker,输出了一个简单的Hello World程序.本文中我们将利用Docker已有的云端镜像training/webapp来发布一个简单Python的W ...
- openstack核心组件--keystone(1)
一.keystone介绍 keystone 是OpenStack的组件之一,用于为OpenStack家族中的其它组件成员提供统一的认证服务,包括身份验证.令牌的发放和校验.服务列表.用户权限的定义等等 ...
- Spring学习之==>入门知识
一.Spring是什么? Spring 是一种轻量级的.非侵入式的 Java/JavaEE 应用框架.Spring 使用的是基本的 JavaBean 来完成以前只可能由EJB完成的事情.然而,Spri ...
- IDEA下启动tomcat非常慢
笔者遇到的原因是在setclasspath.bat里面添加了参数 set JAVA_OPTS="-XX:-UseSplitVerifier -noverify -Djava.net.pref ...
- MySQL使用order by field()自定义排序
MySQL的自定义排序和Oracle相比,要简单得多. 假设在表v_education的列schoolRecord中,有以下字段:'小学','初中','高中','专科','本科','硕士','博士'. ...
- 使用gRPC打造服务间通信基础设施
一.什么是RPC rpc(远程过程调用)是一个古老而新颖的名词,他几乎与http协议同时或更早诞生,也是互联网数据传输过程中非常重要的传输机制. 利用这种传输机制,不同进程(或服务)间像调用本地进程中 ...
- 直方图匹配原理与python、matlab实现
直方图匹配本质上是让两幅图像的累积直方图尽量相似,累积直方图相似了,直方图也就相似了. 把原图像img的直方图匹配到参考图像ref的直方图,包括以下几个步骤: 1. 求出原图像img的累积直方图img ...
- flask 之(三) --- 筛选|分页|过滤
筛选 查询数据筛选语法:类名.query.筛选符 .all( ):获取结果集:.count( ):获取查询到的对象数量 类名.query.filter(类名.属性.运算符('xxx')).all() ...