YOLO与SSD学习

发布于 2020-11-19  2643 次阅读


YOLO与SSD学习

额外知识

1.smooth L1 loss与L1和L2的区别

考察如下几种损失函数,其中$x$为预测框与 groud truth 之间的差异:
$$
L_2(x)=x^2\tag{1}
$$

$$
L_1(x)=|x|\tag{2}
$$

$$
\mathrm{smooth}_{L_1}(x)= \begin{cases} 0.5x^2& \text{if } |x|<1\\ |x|-0.5& \text{otherwise} \end{cases}\tag{3}
$$

损失函数对$x$的导数分别为:
$$
\frac{\mathrm{d}L_2(x)}{\mathrm{d}x}=2x\tag{4}
$$

$$
\frac{\mathrm{d}L_1(x)}{\mathrm{d}x}=\begin{cases} &1 &\text{if } x\geq0 \\ &-1 &\text{otherwise} \end{cases}\tag{5}
$$

$$
\frac{\mathrm{d}\mathrm{\ smooth}_{L_1}}{\mathrm{d}x}=\begin{cases} &x &\text{if}\ |x|<1\\ &\pm1 &\text{otherwise}\tag{6} \end{cases}
$$

观察(4)可以发现,当$x$非常大的时候,损失函数的梯度非常大,容易梯度爆炸

观察(5)可以发现,梯度为常数,这会使在训练后期时,使损失函数很难收敛达到更高精度

所以它从两方面限制了梯度

  1. 当预测框与 ground truth 差别过大时,梯度值不至于过大
  2. 当预测框与 ground truth 差别很小时,梯度值足够小

2.hard negative mining(难例挖掘)

我个人理解有点类似Adaboost算法,就是不断选择那些hard的样本进行重复训练直到无法提升为止

在object detection中,当负例远多于正例时, 是预测结果偏向越负例. 所以可能有很多正例被模型预测为负例, 即False Negative(被模型预测为负的正样本)比较多。

所以我们需要去寻找一些hard negative,我们可以选择在第一次训练中得分最高,即最容易被判断为正样本的负样本为困难样本,加入负样本集进行再次训练

3.norm(范数)

向量的范数

p-范数
$$
||x||_p=(\sum_{i=1}^{m}|x_i|^p)^{\frac{1}{p}}
$$

SSD

因为对SSD的理解比较全面(一方面也因为yolo简单)所以先写了SSD

SSD采取了作为one-stage方法,除了与yolo在最后使用全连接层和卷积层的差别,还有SSD提取了不同尺度的特征图来进行检测,即大尺度特征图检测小物体,小尺度的特征图用来检测大物体,同时SSD采取了RCNN的思路,使用了Archors的思想。

网络架构

SSD一共有6层多尺度提取的网络,每层分别对 loc 和 conf 进行卷积,得到相应的输出

先验框的生成

SSD从Conv4_3开始,一共提取了6个特征图,其大小分别为 (38,38),(19,19),(10,10),(5,5),(3,3),(1,1),但是每个特征图上设置的先验框数量不同。

先验框的设置,包括尺度(或者说大小)和长宽比两个方面。对于先验框的尺度,其遵守一个线性递增规则:随着特征图大小降低,先验框尺度线性增加:
$$
s_k = s_{min} + \frac{s_{max} - s_{min}}{m-1}(k-1), k\in[1,m]
$$
对于长宽比一般采取$a_r\in \lbrace
1,2,3,\frac{1}{2},\frac{1}{3} \rbrace$

位置的编码与解码

其实网络预测得到的是边界框对于先验框的转换值

  1. 先验框位置 $d=(d^{cx},\space d^{cy}, \space d^{w}, \space d^{h})$
  2. 真实框位置 $g=(g^{cx},\space g^{cy}, \space g^{w}, \space g^{h})$

编码: 得到预测框相对于default box的偏移量$l$
$$
\hat{l}_{j}^{cx}=(g_{j}^{cx}-d_{i}^{cx})/d_{i}^{w}/variance[0]
$$

$$
\hat{l}_{j}^{cy}=(g_{j}^{cy}-d_{l}^{cy})/d_{i}^{h}/variance[1]
$$

$$
\hat{l}_{j}^{w}=log(\frac{g_{j}^{w}}{d_{i}^{w}})/variance[2]
$$

$$
\hat{l}_{j}^{h}=log(\frac{g_{j}^{h}}{d_{i}^{h}})/variance[3]
$$

解码也就是从预测值$L$得到边界框的真实值,不再赘述

先验框匹配

在训练过程中,首先需要确定训练图片中的 ground truth 与哪一个先验框来进行匹配,与之匹配的先验框所对应的边界框将负责预测它

SSD的先验框和ground truth匹配原则主要两点: 1. 对于图片中的每个gt,找到与其IOU最大的先验框,该先验框与其匹配,这样可以保证每个gt一定与某个prior匹配。 2. 对于剩余未匹配的priors,若某个gt的IOU大于某个阈值(一般0.5),那么该prior与这个gt匹配

损失函数

整个损失函数为两部分的加权

  • 位置损失函数$L_{loc}$
  • 置信度损失函数$L_{conf}$

整个损失函数为:
$$
L(x, c, l, g)=\frac{1}{N}\left(L_{c o n f}(x, c)+\alpha L_{l o c}(x, l, g)\right)
$$
其中:

  • N 是先验框的正样本数量;
  • c 为类别置信度预测值;
  • l 为先验框的所对应边界框的位置预测值;
  • g 为ground truth的位置参数。

$$
L_{loc}(x,l,g) = \sum_{i \in Pos}^N \sum_{m \in \lbrace cx, cy, w, h \rbrace} x_{ij}^k \mathtt{smooth}_{L1}(l_{i}^m - \hat{g}_j^m)
$$

$$
L_{conf}(x, c) = - \sum_{i\in Pos}^N x_{ij}^p log(\hat{c}_i^p) - \sum_{i\in Neg} log(\hat{c}_i^0)\quad \mathtt{where}\quad\hat{c}_i^p = \frac{\exp(c_i^p)}{\sum_p \exp(c_i^p)}
$$

YOLO

YOLO将物体检测作为一个回归问题进行求解,输入图像经过一次inference,便能得到图像中所有物体的位置和其所属类别及相应的置信概率。而rcnn/fast rcnn/faster rcnn将检测结果分为两部分求解:物体类别(分类问题),物体位置即bounding box(回归问题)

网络架构

YOLO检测网络包括24个卷积层和2个全连接层,如下图所示

其中,卷积层用来提取图像特征,全连接层用来预测图像位置和类别概率值

YOLO将输入图像分成SxS个格子,每个格子负责检测落入该格子的物体,每个单元格需要预测$(B*5+C)$个值。如果将输入图片划分为网$S*S$格,那么最终预测值为$S*S*(B*5+C)$ 大小的张量

针对论文中取$S=7,B=2,C=20$,所以输出是$7*7*30$的向量

细节

  1. 虽然每个格子可以预测B个bounding box,但是最终只选择只选择IOU最高的bounding box作为物体检测输出,即每个格子最多只预测出一个物体
  2. 针对confidence的计算公式为$confidence=Pr(Object) * IOU^{truth}_{pred}$
  3. 针对类别的计算公式为$classify=Pr(Class_i/Object)*confidence$

损失函数

因为yolo直接将整个问题看做回归问题处理(甚至分类问题同理),所以它直接使用了均方误差函数,但是针对不同的loss的权重不一样,所以作者又对其中loss赋予了不同的权重

  1. 有物体中心落入的cell,需要计算分类loss,两个predictor都要计算confidence loss,预测的bounding box与ground truth IOU比较大的那个predictor需要计算xywh loss
  2. 没有物体中心落入的cell,只需要计算confidence loss
  3. 针对不同的loss,作者给予了不同的权重

题外话

这些都是我的笔记,所以写的很简略和有点类似公众号的格式,唯一要求的就是latex的输入,当然文章也就没有那么高的要求啦:sunglasses: