目标检测 SSD 算法

1. 概述

SSD[1] 是在 2016 年提出的单阶段目标检测算法,全称是 Single Shot Multibox Detector。从全称来看,Single shot 也能看出 SSD 算法属于 One-stage 的方法,MultiBox Detector 是 SSD 算法的另一特点,即多框预测,这个在后面会详细介绍。

回顾目标检测算法发展的历史,SSD 算法是在单阶段的 YOLO(严格来说是 YOLO v1[2])之后提出的,因此也是借鉴了 YOLO 的单阶段的优越性,并在此基础上做了优化:

  1. SSD 采用了不同尺度和长宽比的 Default Box,这个与 Faster R-CNN[3] 中的锚框 Anchor 很相似,对于算法的最终效果的影响还是比较大的。YOLO 在后续的版本中也重新加入了先验框,你会发现大家都在互相借鉴彼此优秀的地方;
  2. SSD 中采用 CNN 直接检测,而不是像 YOLO v1 算法在 CNN 后再接全连接层做分类和回归;
  3. SSD 采用了多尺度的特征做分类和回归,这有助于不同尺度的目标的检测。

2. SSD 算法原理

传统的 two-stage 的算法,如 Faster R-CNN 虽然在效果上还不错,但多阶段的过程严重限制了检测的速度,SSD 与 YOLO 类似,是采用 one-stage 的算法,在检测速度上得到了极大提升,也极大降低了算法的整体复杂程度,首先我们看一下 SSD 算法的网络结构,从网络结构出发看看 SSD 是如何在 one-stage 中解决目标检测问题的。

2.1. SSD 的网络结构

SSD 的网络结构如下图所示:

从 SSD 的网络结构可以看出,与 YOLO v1 不同的是,在 YOLO v1 中最后采用全连接层,如下所示:

而在 SSD 中,直接采用卷积对不同的特征图来进行提取检测结果。另一点是,在 SSD 中采用了多尺度特征图用于检测,这里所谓多尺度特征图,就是采用大小不同的特征图进行检测。这样做的好处是低层特征图分辨率高、感受野小,适合检测小目标。而高层特征图分辨率低、感受野大,适合检测大目标。这样既模拟了多尺度处理的效果,又共享了参数。

2.2. 层级特征图

在上图中的 YOLO v1 中,采用的是最后一个语义特征层,也就是大小为 7×7×307\times 7\times 30特征层,这样的设计无法同时兼顾大的目标和较小的目标,因此在 SSD 中优化了这点,在单个网络中使用层级的特征图。低层特征图分辨率高、感受野小,适合检测小目标;高层特征图分辨率低、感受野大,适合检测大目标。这样既模拟了多尺度处理的效果,又共享了参数,能够同时处理大目标和小目标。在文献[1]中的 SSD 中共取了 66层,分别为 Conv4_3、Conv7、Conv8_2、Conv9_2、Conv10_2、Conv11_2。

2.3. Default Box

虽然 SSD 摒弃了 Faster R-CNN 的 two-stage 的过程,但是还是借鉴了 Faster R-CNN 中 Anchor 的理念,设计了 Default Box。Default Box 是设置在每一个层级的 Feature Map 上每个单元的尺度或者长宽比不同的目标框,模型训练的过程就是以这些 Default Box 为基准的,逐步逼近真实的 Ground Truth。Default Box 的设置过程如下图所示:

在 SSD 中,Default Box 的设置涉及到两个层面,分别为尺度和长宽比。与 Faster R-CNN 中不同,在 SSD 中,Default Box 是设置在每个特征图上面的,因此对于每一个特征图,需要设置不同的尺度。如何理解尺度呢?尺度可以理解为 Default Box 相对于原图的比例。

假设当前共使用 mm个特征图进行预测,其中第 kk层特征图上 Default Box 的尺度 sks_k按以下公式计算:

sk=smin+smax−sminm−1(k−1),k∈[1,m]s_k=s_{min}+\frac{s_{max}-s_{min}}{m-1}\left ( k-1 \right ),\quad k\in\left [ 1,m \right ]

在参考文献[1]中,设置 smin=0.2s_{min}=0.2,smax=0.9s_{max}=0.9,这表示最低层尺度为 0.20.2,最高层为 0.90.9,中间层均匀分布。例如在文献[1]中,SSD 的输入图像大小为 300×300300\times 300,则当 s=0.2s=0.2时,表示的是对应实际像素边长为 300×0.2=60300\times 0.2=60像素,是一个归一化的值(注意,这个后面会使用到)。

在文献[1],共使用的特征图个数为 66,但是 Conv4_3 这一层的尺度单独设置,因此设置 m=5m=5,各特征图对应的大小和尺度分别为:

  • Conv4_3:大小为 38×38×51238\times 38\times 512,尺度 ss为 0.10.1(这个尺度是单独设置的)
  • Conv7:大小为 38×38×51238\times 38\times 512,尺度 s1s_1为 0.20.2
  • Conv8_2:大小为 10×10×51210\times 10\times 512,尺度 s2s_2为 0.3750.375
  • Conv9_2:大小为 5×5×2565\times 5\times 256,尺度 s3s_3为 0.550.55
  • Conv10_2:大小为 3×3×2563\times 3\times 256,尺度 s4s_4为 0.7250.725
  • Conv11_2:大小为 1×1×2561\times 1\times 256,尺度 s5s_5为 0.90.9

有了尺度,还需要通过长宽比来覆盖不同形状的目标。在参考文献[1]中为 Default Box 设置了五个长宽比:

ar∈{1,2,3,12,13}a_r\in \left\{ 1,2,3,\frac{1}{2},\frac{1}{3}\right\}

对于长宽比 ara_r,Default Box 的宽度和高度分别计算为:

wka=skar,hka=skarw_k^a=s_k\sqrt{a_r},\quad h_k^a=\frac{s_k}{\sqrt{a_r}}

注意,与尺度一样,宽高也是相对于原图的比例。当 ar=1a_r=1时,w=h=skw=h=s_k,得到一个正方形 Default Box。除了这个正方形的 Default Box,在文献[1]中,还额外增加了一个尺度为 sk′=sksk+1s_k'=\sqrt{s_ks_{k+1}}的正方形 Default Box。这一共就是在每一个特征图的 cell 上有 66个 Default Box。

注意:在文献[1]中,conv4_3、conv10_2、conv11_2 三层不使用 3:1 和 1:3 两个极端长宽比,每层只放置 4 个 Default Box。文献中解释是:conv4_3 的特征尺度与其他层差异较大,需要 L2 归一化处理,因此简化了该层的 Default Box 配置。

Default Box 的中心点被设置在特征图每个单元格的中心。对于第 kk层特征图,其大小为 ∣fk∣×∣fk∣\left | f_k\right |\times \left | f_k\right |,第 (i,j)\left(i,j\right)个单元格的中心坐标为:

(i+0.5∣fk∣,j+0.5∣fk∣),i,j∈[0,∣fk∣)\left ( \frac{i+0.5}{\left | f_k\right |},\frac{j+0.5}{\left | f_k\right |} \right ),\quad i,j\in \left[0, \left | f_k\right |\right)

注意,这是一个归一化到原图的坐标。其中,(i,j)\left(i,j\right)表示的是每个单元格 cell 的左上角的位置,如下图所示:

这里的 (1,1)\left(1,1\right)表示的就是 6 所在的单元格。

2.4. Ground Truth 与 Default Box 匹配

通过以上的分析,Default Box 最终都被归一化到原图中了,因此,在与 Ground Truth 进行匹配之前,先需要将 Ground Truth 中边界框坐标进行归一化,归一化公式为:

gx=xpixelWimage,gy=ypixelHimage,gw=wpixelWimage,gh=hpixelHimageg_x=\frac{x_{pixel}}{W_{image}},\quad g_y=\frac{y_{pixel}}{H_{image}},\quad g_w=\frac{w_{pixel}}{W_{image}},\quad g_h=\frac{h_{pixel}}{H_{image}}

接下来进行Ground Truth 与 Default Box 的匹配,匹配逻辑决定了对于指定的 Ground Truth,由哪个或者哪几个 Default Box 来负责。在 SSD 中匹配的逻辑如下:

  1. 每个 GT 匹配 IoU 最大的 Default Box

对于图像中的每一个 Ground Truth 框,计算它与所有 Default Box 的 IoU,然后选择 IoU 最大的那个 Default Box 作为正样本。这样能保证对于每一个 Ground Truth,至少存在一个 Default Box 对其负责。

  1. 剩余 Default Box 按 IoU 阈值匹配

对于剩下的还没有被匹配的 Default Box,如果它与某个 Ground Truth 的 IoU 大于阈值(文献[1]中取 0.50.5),也将它匹配到该 GT,作为正样本。这样就允许一个 Ground Truth 匹配到多个 Default Box,这也是 MultiBox Detector 的来源。

通过以上的两步,就组成了所有的正样本,而所有没有匹配任何 Ground Truth 的 Default Box 则为负样本。这里也会存在负样本远远多于正样本呢的情况,在 SSD 中使用难负样本挖掘,也就是对负样本按置信度损失排序,选取损失最高的那些,使正负样本比例保持在 1:31:3左右。这样训练更稳定,避免大量简单负样本主导梯度。

这里的 IoU 的计算都可以在归一化的坐标中进行计算。

2.5. 损失函数

确定了正负样本后,对于损失函数,也是包含了两个部分,分别为位置损失(locatization loss, loc)和置信度损失(confidence loss, conf),如下图所示:

最终的损失函数是这两个部分的加权求和:

L(x,c,l,g)=1N(Lconf(x,c)+αLloc(x,l,g))L\left ( x,c,l,g \right )=\frac{1}{N}\left ( L_{conf}\left ( x,c \right )+\alpha L_{loc}\left ( x,l,g \right ) \right )

其中,NN 表示的是匹配到 Ground Truth 的 Default Box 数量,也就是正样本的数量。LconfL_{conf} 为置信度损失,LlocL_{loc} 为位置损失,α\alpha 为定位损失与置信度损失的权重,文献[1]中取 α=1\alpha =1。

置信度损失 LconfL_{conf} 是 Softmax 交叉熵损失,用于分类,正样本对应了真实的类别,而负样本则是对应了背景类。其具体公式为:

Lconf(x,c)=−∑i∈PosNxijplog(c^ip)−∑i∈Neglog(c^i0)L_{conf}\left ( x,c \right )=-\sum_{i\in Pos}^{N}x_{ij}^plog\left ( \hat{c}_i^p \right )-\sum_{i\in Neg}log\left ( \hat{c}^0_i \right )

其中,i∈Posi\in Pos 表示的是正样本的 Default Box,同样的,i∈Negi\in Neg 表示的是负样本的 Default Box,pp 表示的是真实的类别标签。xijpx_{ij}^p 是一个指示器,当第 ii 个 Default Box 匹配到第 jj 个 Ground Truth 且类别为pp 时,xijp=1x_{ij}^p=1,否则 xijp=0x_{ij}^p=0。c^ip\hat{c}_i^p 表示的是预测第 ii 个 Default Box 属于类别 pp 的 Softmax 值,同样,c^i0\hat{c}^0_i 表示的是预测第 ii 个 Default Box 属于背景类的 Softmax 值。

位置损失 LlocL_{loc} 只针对正样本,需要修正预测出的边界框与真实边界框之间的偏差,其具体公式为:

Lloc(x,l,g)=∑i∈Pos∑m∈{cx,cy,w,h}xijksmoothL1(lim−g^jm)L_{loc}\left ( x,l,g \right )=\sum _{i\in Pos}\sum _{m\in \left\{ cx,cy,w,h\right\}}x_{ij}^ksmooth_{L_1}\left ( l_i^m-\hat{g}_j^m \right )

其中,i∈Posi\in Pos 表示的是正样本的 Default Box,∑i∈Pos\sum _{i\in Pos} 表示针对所有的正样本计算。∑m∈{cx,cy,w,h}\sum _{m\in \left\{ cx,cy,w,h\right\}} 表示的是需要对所有的坐标分量计算,包括中心点 cx,cycx,cy 和宽高 w,hw,h。xijkx_{ij}^k 是一个指示器,当第 ii 个 Default Box 匹配到第 jj 个 Ground Truth 且类别为 kk 时,xijk=1x_{ij}^k=1,否则 xijk=0x_{ij}^k=0,这里与具体的类别无关。liml_i^m 表示的是第ii 个 Default Box 的偏移量,g^jm\hat{g}_j^m 表示的是第 jj 个 Ground Truth 相对于其匹配的 Default Box 的编码偏移量,其具体的形式为:

g^jcx=gjcx−dicxdiw\hat{g}_j^{cx}=\frac{g_j^{cx}-d_i^{cx}}{d_i^w}

g^jcy=gjcy−dicydih\hat{g}_j^{cy}=\frac{g_j^{cy}-d_i^{cy}}{d_i^h}

g^jw=log(gjwdiw)\hat{g}_j^{w}=log\left( \frac{g_j^{w}}{d_i^w} \right)

g^jh=log(gjhdih)\hat{g}_j^{h}=log\left( \frac{g_j^{h}}{d_i^h} \right)

其中,dicx,dicyd_i^{cx},d_i^{cy} 为第 ii 个 Default Box 的中心坐标,diw,dihd_i^{w},d_i^{h} 为第 ii 个 Default Box 的宽高。Smooth L1 损失函数为:

smoothL1(x)={0.5x2if  ∣x∣<1∣x∣−0.5otherwise  smooth_{L_1}\left ( x \right )=\begin{cases} 0.5x^2 & \text{if}\;\left | x\right |< 1 \\ \\ \left | x\right |-0.5 & \text{otherwise}\; \end{cases}

Smooth L1 在误差较小时用平方项,梯度平滑;误差较大时用线性项,对离群点更鲁棒。相比 L2 损失,它不易被极端误差主导,训练更稳定。

3. 总结

SSD 借鉴了 YOLO v1 的单阶段的目标检测的速度优势,同时又借鉴了 Faster R-CNN 中 Anchor 的设计逻辑,增加了先验框,相比较与 two-stage,保留了速度的优势,同时又能提升整体的效果;在此基础上,还采用了层级的特征图,优化了在 YOLO v1 中只有单个特征图的问题,能够同时适应大目标和小目标。要注意一点的是,在 SSD 中先验框是相对于原图设计的,其先验框的值是相对于原图的归一化的值,因此,损失函数的计算都是在原图空间中完成的。

参考文献

[1] Liu W, Anguelov D, Erhan D, et al. Ssd: Single shot multibox detector[C]//European conference on computer vision. Cham: Springer International Publishing, 2016: 21-37.

[2] Redmon J, Divvala S, Girshick R, et al. You only look once: Unified, real-time object detection[C]//Proceedings of the IEEE conference on computer vision and pattern recognition. 2016: 779-788.

[3] Faster r-cnn: Towards real-time object detection with region proposal networks[J]. Advances in neural information processing systems, 2015, 28.