1. SSD 算法简介
SSD(Single Shot MultiBox Detector)是 Wei Liu 等人在 ECCV 2016 上提出的单阶段(one-stage)目标检测算法。它的核心设计思想是:在一个前向传播中直接预测目标框的类别和位置偏移,无需单独的区域提议(Region Proposal)阶段。
SSD 的主要创新包括:
- 使用多尺度特征图(multi-scale feature maps)进行检测,大特征图负责检测小目标,小特征图负责检测大目标
- 在每个特征图的每个空间位置设置一组默认框(default boxes)(也称为 anchor boxes / prior boxes),不同层的默认框有不同的尺度和长宽比
- 直接通过卷积预测每个默认框的类别分数和边界框偏移,端到端训练
SSD 在 VOC2007 上达到了 74.3% mAP(使用 300x300 输入)和 76.8% mAP(使用 512x512 输入),在速度和精度的平衡上超越了同期 YOLO v1 和 Faster R-CNN。
2. 网络架构详解
2.1 整体结构概览
SSD 的网络由两部分组成:
- 基础网络(Base Network):标准图像分类网络去掉最后的全连接分类层。论文使用 VGG-16(截断至 conv5_3)
- 附加层(Extra Feature Layers):在基础网络后添加一系列卷积层,逐步降低空间分辨率,产生多个尺度的特征图
SSD 架构示意: |
2.2 基础网络:VGG-16 与 ResNet
VGG-16 作为 Backbone:
原始的 SSD 使用 VGG-16 作为骨干网络(截断在conv5_3),并做了如下修改:
- 将 VGG-16 的 FC6 和 FC7 全连接层替换为卷积层(使用空洞卷积保持感受野)
- FC6 替换为:3x3 空洞卷积,dilation=6,输出 1024 通道
- FC7 替换为:1x1 卷积,输出 1024 通道
- 去掉所有 Dropout 层和 FC8 分类层
VGG-16 backbone 参数配置: |
ResNet 作为 Backbone:
后续工作(如 DSSD)将 VGG-16 替换为 ResNet-101,获得了显著的精度提升。使用 ResNet 时:
- 在 ResNet 的 conv3_x 输出后额外添加反卷积层来增强特征图分辨率
- 特征提取能力比 VGG-16 更强,尤其对小目标
2.3 额外卷积层(Extra Feature Layers)
| 层名 | 输入尺寸 | 卷积参数 | 输出尺寸 | 下采样方式 |
|---|---|---|---|---|
| Conv6 (FC6) | 19x19x512 | 3x3x1024, dil=6 | 19x19x1024 | - |
| Conv7 (FC7) | 19x19x1024 | 1x1x1024 | 19x19x1024 | - |
| Conv8_1 | 19x19x1024 | 1x1x256 | 19x19x256 | - |
| Conv8_2 | 19x19x256 | 3x3x512, s2 | 10x10x512 | stride=2 |
| Conv9_1 | 10x10x512 | 1x1x128 | 10x10x128 | - |
| Conv9_2 | 10x10x128 | 3x3x256, s2 | 5x5x256 | stride=2 |
| Conv10_1 | 5x5x256 | 1x1x128 | 5x5x128 | - |
| Conv10_2 | 5x5x128 | 3x3x256, s2 | 3x3x256 | stride=2 |
| Conv11_1 | 3x3x256 | 1x1x128 | 3x3x128 | - |
| Conv11_2 | 3x3x128 | 3x3x256 | 1x1x256 | valid padding |
2.4 多尺度检测层的设计哲学
SSD 从 6 个不同分辨率的特征图上进行检测(实际使用 6 层,conv4_3 + FC7 + conv8_2 + conv9_2 + conv10_2 + conv11_2):
| 检测层 | 特征图尺寸 | 感受野 | 主要负责检测的目标尺寸 |
|---|---|---|---|
| conv4_3 | 38x38 | 小(~30-60 px) | 极小目标 |
| fc7 | 19x19 | 中(~60-110 px) | 小目标 |
| conv8_2 | 10x10 | 中偏大(~110-160 px) | 中等目标 |
| conv9_2 | 5x5 | 大(~160-220 px) | 较大目标 |
| conv10_2 | 3x3 | 很大(~220-280 px) | 大目标 |
| conv11_2 | 1x1 | 最大(~280-350 px) | 超大目标 |
为什么需要多尺度检测?
深度卷积网络中,浅层特征图空间分辨率高但语义信息弱,适合定位小目标;深层特征图空间分辨率低但语义信息强,适合对大目标进行分类。SSD 的多尺度检测策略使其能够同时利用不同深度的特征信息,从而在不同尺度的目标上都有良好的检测效果。这与图像金字塔(image pyramid)的思想类似,但计算开销小得多。
2.5 L2 归一化(conv4_3 专用)
conv4_3 层的特征值尺度(norm)通常比其他层大许多(约为 20:1),如果直接与其他层的特征混用,会导致训练不稳定。SSD 在 conv4_3 的输出后添加了一个 L2 归一化层,并引入一个可学习的缩放因子 $\gamma$:
$$ \text{output} = \gamma \cdot \frac{x}{\|x\|_2} $$
初始 $\gamma = 20$,让模型在学习过程中自行调整到合适的尺度。
3. 默认框(Default Boxes)设计与匹配策略
3.1 默认框的尺度分配
SSD 为每个检测层设计了一组默认框,这些默认框的尺度(scale)随着层加深而线性递增:
$$ s_k = s_{\min} + \frac{s_{\max} - s_{\min}}{m - 1}(k - 1), \quad k \in [1, m] $$
其中 $s_{\min} = 0.2$,$s_{\max} = 0.9$(相对于输入尺寸的比例),$m = 6$ 是检测层的数量。
实际每一层的尺度为:
- conv4_3: $s_1 = 0.2$ (即 $0.2 \times 300 = 60$ px,但实际设为 30 px)
- fc7: $s_2 = 0.34$(~102 px)
- conv8_2: $s_3 = 0.48$(~144 px)
- conv9_2: $s_4 = 0.62$(~186 px)
- conv10_2: $s_5 = 0.76$(~228 px)
- conv11_2: $s_6 = 0.9$(~270 px)
注意:conv4_3 的 scale 缩小处理($s_{\min}/2 = 0.1$)。
3.2 默认框的长宽比
每个空间位置设置多种长宽比的默认框。标准长宽比集合为:
$$ a_r \in \left\{1, 2, 3, \frac{1}{2}, \frac{1}{3}\right\} $$
对于每个长宽比 $a_r$,默认框的宽和高分别为:
$$ w_k^a = s_k \sqrt{a_r}, \quad h_k^a = \frac{s_k}{\sqrt{a_r}} $$
对于长宽比为 1 的情况,额外增加一个尺度为 $s_k’ = \sqrt{s_k \cdot s_{k+1}}$ 的默认框:
$$ w_k^1 = h_k^1 = \sqrt{s_k \cdot s_{k+1}} $$
各层默认框配置总结:
| 检测层 | 长宽比 | 每位置默认框数 | 总默认框数 |
|---|---|---|---|
| conv4_3 | 1, 2, 1/2 | 4 (含 $s_k’$ 的方形框) | 38x38x4 = 5,776 |
| fc7 | 1, 2, 3, 1/2, 1/3 | 6 | 19x19x6 = 2,166 |
| conv8_2 | 1, 2, 3, 1/2, 1/3 | 6 | 10x10x6 = 600 |
| conv9_2 | 1, 2, 3, 1/2, 1/3 | 6 | 5x5x6 = 150 |
| conv10_2 | 1, 2, 1/2 | 4 | 3x3x4 = 36 |
| conv11_2 | 1, 2, 1/2 | 4 | 1x1x4 = 4 |
总计默认框数量:$38^2 \times 4 + 19^2 \times 6 + 10^2 \times 6 + 5^2 \times 6 + 3^2 \times 4 + 1^2 \times 4 = 5,776 + 2,166 + 600 + 150 + 36 + 4 = 8,732$
这些默认框密集地覆盖了输入图像的各种位置和尺度,为后续的预测和匹配奠定了基础。
3.3 默认框匹配策略(Matching Strategy)
SSD 通过 Jaccard 重叠(即 IoU, Intersection over Union)将默认框与真实框(ground truth boxes)进行匹配:
- 最佳匹配:对于每个真实框,选择与其 IoU 最高的默认框作为正样本
- 阈值匹配:对于所有默认框,如果与任意真实框的 IoU > 阈值(通常设为 0.5),则也标记为正样本
Pseudo-code: Matching Strategy |
经过匹配后,大部分默认框都是负样本(背景类),正样本通常占总默认框的 1% 不到。这个严重的正负样本不平衡问题由困难负样本挖掘(Hard Negative Mining)来解决。
3.4 默认框的中心坐标和尺寸编码
对于特征图位置 $(i, j)$,其默认框的中心坐标(归一化到 $[0, 1]$):
$$ cx = \frac{i + 0.5}{|f_k|}, \quad cy = \frac{j + 0.5}{|f_k|} $$
其中 $|f_k|$ 是第 $k$ 个特征图的宽度/高度(假设为方形)。
4. 预测卷积层(Prediction Convolutions)
4.1 预测头的设计
对于每个检测层,SSD 使用一组小的卷积核(3x3 convolutions with padding=1)直接预测默认框的类别分数和边界框偏移:
类别预测:对于 $K$ 个类别(含背景类),每个空间位置、每个默认框需要预测 $K$ 个分数:
conv_cls: 3x3 conv, output channels = num_boxes_per_location * num_classes |
边界框回归:对于每个默认框,预测 4 个偏移量(中心坐标 cx, cy 的偏移和宽度 w, 高度 h 的对数缩放):
conv_loc: 3x3 conv, output channels = num_boxes_per_location * 4 |
数值示例(conv4_3 层):
- 每位置 4 个默认框
- 类别数(含背景):VOC 为 21,COCO 为 81
- 分类输出通道:4 x 21 = 84
- 回归输出通道:4 x 4 = 16
4.2 边界框编码(Bounding Box Encoding)
SSD 使用与 Faster R-CNN 类似的边界框编码方式。对于默认框 $d = (d^{cx}, d^{cy}, d^w, d^h)$ 和真实框 $g = (g^{cx}, g^{cy}, g^w, g^h)$,编码后的回归目标 $\hat{g}$ 为:
$$ \hat{g}^{cx} = \frac{g^{cx} - d^{cx}}{d^w}, \quad \hat{g}^{cy} = \frac{g^{cy} - d^{cy}}{d^h} $$
$$ \hat{g}^{w} = \log\left(\frac{g^w}{d^w}\right), \quad \hat{g}^{h} = \log\left(\frac{g^h}{d^h}\right) $$
解码时:
$$ g^{cx} = d^{cx} + \hat{g}^{cx} \cdot d^w, \quad g^{cy} = d^{cy} + \hat{g}^{cy} \cdot d^h $$
$$ g^w = d^w \cdot \exp(\hat{g}^{w}), \quad g^h = d^h \cdot \exp(\hat{g}^{h}) $$
5. 损失函数
SSD 的总损失函数为分类损失和定位损失的加权和:
$$ L(x, c, l, g) = \frac{1}{N} \left[ L_{\text{conf}}(x, c) + \alpha L_{\text{loc}}(x, l, g) \right] $$
其中 $N$ 是匹配的正样本默认框数量,$\alpha$ 是平衡系数(通常设为 1),$x$ 是匹配指示矩阵。
5.1 定位损失:Smooth L1
SSD 使用 Smooth L1 损失进行边界框回归。对于匹配到第 $k$ 类、第 $j$ 个真实框的第 $i$ 个默认框:
$$ L_{\text{loc}}(x, l, g) = \sum_{i \in \text{Pos}} \sum_{m \in \{cx, cy, w, h\}} x_{ij}^k \cdot \text{smooth}_{L1}(l_i^m - \hat{g}_j^m) $$
其中:
$$ \text{smooth}_{L1}(z) = \begin{cases} 0.5 z^2, & |z| < 1 \\ |z| - 0.5, & |z| \geq 1 \end{cases} $$
Smooth L1 的优点:相比于 L2 损失,对离群值(outliers)不那么敏感,训练更稳定;相比于 L1 损失,在零点附近是光滑的,梯度连续。
5.2 置信度损失:Softmax Cross-Entropy
$$ L_{\text{conf}}(x, c) = -\sum_{i \in \text{Pos}} x_{ij}^p \log(\hat{c}_i^p) - \sum_{i \in \text{Neg}} \log(\hat{c}_i^0) $$
其中 $\hat{c}_i^p = \frac{\exp(c_i^p)}{\sum_p \exp(c_i^p)}$ 是经过 softmax 的类别概率,背景类为 $p=0$。
5.3 困难负样本挖掘(Hard Negative Mining)
SSD 检测中的一个关键挑战是极端的正负样本不平衡。在 8732 个默认框中,通常只有数个到数十个正样本,其余全部是负样本。简单地将所有负样本用于训练会导致模型倾向于预测”所有框都是背景”。
Hard Negative Mining 算法:
Algorithm: Hard Negative Mining in SSD |
通常将正负样本比例控制在 1:3 左右(即 $k = 3 \times N_{\text{pos}}$),这样既保证了足够的负样本参与训练,又避免了负样本淹没模型的问题。
为什么困难负样本挖掘有效?
- 简单的负样本(模型已经可以正确预测为背景)不会产生有意义的梯度信号
- 困难负样本(模型误将背景预测为某类别)能提供最有价值的梯度信息,引导模型学习到正确的分类边界
- 保持正负比例平衡有利于训练稳定
6. 数据增强与训练策略
6.1 数据增强方法
SSD 使用了广泛的数据增强来提升模型鲁棒性:
| 增强方法 | 参数设置 | 目的 |
|---|---|---|
| 随机裁剪(Random Crop) | IoU约束:[0.1, 0.3, 0.5, 0.7, 0.9] | 模拟目标被部分遮挡的情况 |
| 颜色抖动(Color Jitter) | 亮度、对比度、饱和度、色调 | 提升对光照变化的鲁棒性 |
| 随机翻转(Random Flip) | 水平翻转,概率 0.5 | 使模型不受目标朝向影响 |
| 尺寸变化(Resize) | 统一 resize 到 300x300 | 保证固定输入尺寸 |
随机裁剪的具体实现:
Algorithm: SSD Sampling Strategy for Data Augmentation |
6.2 训练配置
| 参数 | 设置 |
|---|---|
| 优化器 | SGD |
| 动量(Momentum) | 0.9 |
| 权重衰减(Weight Decay) | 0.0005 |
| Batch Size | 32 |
| 初始学习率 | 0.001 (前 40k 迭代),之后降至 0.0001,再降至 0.00001 |
| 总迭代数 | 120k (VOC0712) |
| 学习率衰减策略 | 在第 80k 和 100k 迭代时衰减为原来的 1/10 |
| 权重初始化 | Xavier (所有卷积层) |
7. SSD vs YOLO vs Faster R-CNN 对比
7.1 核心设计差异
| 维度 | Faster R-CNN | YOLO v1 | SSD |
|---|---|---|---|
| 检测范式 | Two-stage | One-stage | One-stage |
| 区域提议 | RPN(独立网络) | 无(网格划分) | 无(默认框) |
| 特征图尺度 | 单一(RPN + RoI Pooling 后处理) | 单一(7x7 网格) | 多个(6 个尺度) |
| Anchor/Default Box | 9 种 anchors(3 尺度 x 3 比例) | 无 explicit anchor | 4-6 每层,共 8732 个 |
| 正负样本平衡 | RPN 中 1:1(大约) | NMS + 阈值 | Hard Negative Mining 1:3 |
| 速度 (VOC2007) | 5-7 FPS | 45 FPS | 59 FPS(300x300),22 FPS(512x512) |
| mAP (VOC2007) | 73.2% | 63.4% | 74.3%(300x300),76.8%(512x512) |
7.2 SSD 相比 YOLO v1 的优势
- 多尺度检测:SSD 从不同分辨率的特征图上做预测,对尺度变化的适应性强于 YOLO v1 的单一特征图
- 默认框 vs 网格:SSD 的密集默认框比 YOLO v1 的稀疏网格(7x7=49 个预测位置)提供了更好的空间覆盖和更多的正样本匹配机会
- 卷积预测 vs 全连接:SSD 使用全卷积的预测头,参数更少、效率更高;YOLO v1 在最后使用了全连接层
- 小目标检测更好:得益于 conv4_3 的大特征图(38x38)检测小目标,SSD 对小目标的检测能力明显优于 YOLO v1
7.3 SSD 相比 Faster R-CNN 的优势与不足
优势:
- 速度更快:单阶段设计避免了 RPN 和 RoI Pooling 等耗时步骤
- 更简单:无需单独的区域提议网络和 RoI 对齐操作
不足:
- 小目标检测仍不如 Faster R-CNN(后者通过 RoI Pooling 对每个 proposal 重新提取特征,精度更高)
- 默认框的超参数(尺度、长宽比)需要手工调整
7.4 视觉化对比
Faster R-CNN (Two-stage): |
8. SSD 的改进与变体
8.1 DSSD(Deconvolutional SSD)
DSSD 的主要改进:
- 将 VGG-16 backbone 替换为 ResNet-101,获得更强的特征提取能力
- 在预测层之间添加反卷积模块(deconvolutional module),将高层的强语义信息传递到低层特征图中
- 这种”自上而下”的特征融合显著提升了小目标检测性能(VOC2007 mAP:78.6%)
8.2 FSSD(Feature Fusion SSD)
在 SSD 的多个检测层之间添加特征融合模块,将各层特征上采样到相同分辨率后拼接(concatenate),再生成新的特征金字塔用于检测。
8.3 RetinaNet(Focal Loss)
虽然 RetinaNet 不是 SSD 的变体,但它解决了 SSD 面临的核心问题:极端的正负样本不平衡。RetinaNet 提出了 Focal Loss:
$$ \text{FL}(p_t) = -\alpha_t (1 - p_t)^\gamma \log(p_t) $$
其中 $(1 - p_t)^\gamma$ 自动降低简单负样本的权重,使得模型无需 Hard Negative Mining 就能处理类别不平衡。$\gamma = 2$ 是常用设置。
8.4 RefineDet
将 Two-stage 的”先粗后精”思想引入 SSD:先通过 Anchor Refinement Module(ARM)对默认框进行初步调整,再通过 Object Detection Module(ODM)进行最终检测。
9. 非极大值抑制(NMS)
9.1 NMS 在 SSD 中的作用
SSD 产生 8732 个预测框,其中绝大多数是冗余的(同一目标被多个默认框检测到)。NMS 用于去除重复检测:
Algorithm: Non-Maximum Suppression (NMS) |
9.2 类别感知 NMS vs 类别无关 NMS
- 类别无关 NMS(Faster R-CNN 风格):对所有类别的框一起做 NMS。速度快但可能抑制不同类别的重叠目标。
- 类别感知 NMS:每个类别独立做 NMS。SSD 使用此方式,能更好地处理同一空间位置有不同类别目标的情况。
SSD 先对每类的预测框做 Top-K 筛选(保留得分最高的 K=200 个框),再对每个类别独立做 NMS,最后综合所有类别的结果。
10. 面试高频问答
Q1: SSD 为什么叫 “Single Shot”?与 Two-stage 检测器的本质区别是什么?
“Single Shot” 意味着整个检测过程(从图像到预测框)只经过一次前向传播,不像 Faster R-CNN 那样需要先通过 RPN 生成区域提议(First Shot),再通过 RoI Pooling + 分类回归头处理每个提议(Second Shot)。SSD 直接在单次前向传播中完成分类和回归,这使得它的速度通常比 Two-stage 方法快 5-10 倍。
Q2: SSD 的默认框(Default Box)和 Faster R-CNN 的 Anchor 有何异同?
相同点:两者都是在每个特征图位置预先设计的一组固定形状和大小的参考框,用于后续的分类和回归预测。
不同点:
- Anchor 只在 RPN 最后一层(或 FPN 的各层)特征图上设置,而 SSD 的默认框分布在 6 个不同分辨率的特征图上
- Anchor 的尺度和比例通常比较统一(如 3 尺度 x 3 比例 = 9 个),而 SSD 的默认框在不同层有不同的尺度和长宽比配置
- Faster R-CNN 中 anchor 仅用于 RPN 的二分类(前景/背景)和粗略回归,而 SSD 的默认框直接用于最终的分类和细粒度回归
Q3: 为什么 SSD 对���目标检测效果不如大目标?
主要原因有三:
- conv4_3(检测小目标的主要层)虽然分辨率高,但语义特征不够强,缺乏足够的上下文信息
- 预设的默认框最小尺度为 30px,对于小于 30px 的目标,可能没有任何默认框与之匹配(IoU < 0.5)
- 后续的改进(如 DSSD、FPN-based SSD)通过特征融合缓解了这个问题,但原始 SSD 缺少高层语义到低层特征的传递机制
相比之下,Faster R-CNN 的 RoI Pooling 会对每个提议区域的深层特征图做裁剪和 pooling,即使小目标也能利用深层的强语义特征。
Q4: Hard Negative Mining 在训练过程中是如何运作的?为什么不能简单用正负样本加权来替代?
Hard Negative Mining 在每个 batch 中动态筛选最具误导性的负样本(即模型将其错误地以高置信度预测为某个非背景类别的默认框)。这种动态选择比静态加权更有效,因为:
- 哪些负样本是”困难”的会随着训练进行而变化(早期的困难负样本在后期可能变为简单负样本)
- 静态加权需要对每个默认框固定一个权重,而实际训练中 8000+ 个负样本的”难度”分布是持续变化的
- HNM 确保了每个 batch 中最有价值(即梯度最大)的负样本参与训练,相当于一种”主动学习”策略
不过,Focal Loss 通过 $(1-p_t)^\gamma$ 动态调节每个样本的损失贡献,在 RetinaNet 中证明不需要显式的 HNM 也能处理类别不平衡。
Q5: 如果让你重新设计 SSD,你会做哪些改进?
几个可能的改进方向:
- 加入特征金字塔网络(FPN):将深层强语义特征通过上采样 + 横向连接传递到浅层,提升小目标检测
- 替换 backbone 为更现代的网络:如 EfficientNet 或 ConvNeXt,在相同计算预算下获得更好的特征提取能力
- 将 Hard Negative Mining 替换为 Focal Loss:简化训练流程,让所有负样本参与训练但自动降低简单样本的权重
- 学习默认框的配置:使用如 Guided Anchoring 或 NAS(Neural Architecture Search)自动搜索每层最优的锚框尺度和比例
- 加入自注意力机制:在检测层之间加入 Transformer-style 的 cross-scale attention 来更好地融合多尺度信息

