You Only Look Once: Unified, Real-Time Object Detection
针对问题:目标检测
1. 核心思想
YOLO的核心思想就是利用整张图片作为网络的输入,直接在输出层回归 bounding box 的位置和所属类别。
YOLO将一幅图像分成 S × S ( S = 7 ) S\times S(S=7) S×S(S=7)个网格(grid cell),每个网格要预测 B ( B = 2 ) B(B=2) B(B=2)个 bounding box,每个bounding box 除了要回归自身的位置( x , y , w , h x, y, w, h x,y,w,h)之外,还要附带预测一个置信度(confidence,可以暂且简单理解为画的框与真实框 groundtruth 框的交并比 IoU ),即一共5个参数。同时,每个网格有一组条件类别概率(共 C C C个类别),则当网格中存在物体时,其输出为一个 S × S × ( 5 × B + C ) S \times S \times (5\times B+C) S×S×(5×B+C)的张量。
举例说明:如果图像输入为 448 x 448,取 S=7,B=2,一共有 20 个类别 (C=20),则输出就是一个 7 x 7 x 30 的张量。
关于输出张量的内容,我们再结合下图来理解一下:
下面我们讲一下有关网格的细节:
由上述知,bounding box 包含5个预测 ( x , y , w , h , c ) (x, y, w, h, c) (x,y,w,h,c),其中 ( x , y ) (x, y) (x,y)表示 bounding box 的中心相对于其所在的网格左上角的偏移量, ( x c , y c ) (x_c, y_c) (xc,yc)表是 box 的中心。因为我们谈论的重点的是在偏移量上,所以 ( x , y , w , h , c ) (x, y, w, h, c) (x,y,w,h,c)都需要被归一化到 ( 0 , 1 ) (0, 1) (0,1)区间。
如何实现归一化呢?
对于 ( w , h ) (w, h) (w,h),
w = b o x 的 宽 度 图 片 总 宽 度 , h = b o x 的 高 度 图 片 总 高 度 \begin{aligned}w = \frac{box 的宽度}{图片总宽度},\ \ h = \frac{box 的高度}{图片总高度}\end{aligned} w=图片总宽度box的宽度, h=图片总高度box的高度
对于 ( x , y ) (x,y) (x,y),要相对复杂一点
x
=
x
c
⋅
S
w
i
d
t
h
i
m
a
g
e
−
c
o
l
=
x
c
w
i
d
t
h
g
r
i
d
−
c
o
l
\begin{aligned}x = x_c \cdot \frac{S}{width_{image}}-col=\frac{x_c}{width_{grid}}-col\end{aligned}
x=xc⋅widthimageS−col=widthgridxc−col
y
=
y
c
⋅
S
h
e
i
g
h
t
i
m
a
g
e
−
r
o
w
=
y
c
h
e
i
g
h
t
g
r
i
d
−
r
o
w
\begin{aligned}y = y_c \cdot \frac{S}{height_{image}}-row=\frac{y_c}{height_{grid}}-row\end{aligned}
y=yc⋅heightimageS−row=heightgridyc−row
( r o w , c o l ) (row, col) (row,col)的含义如下图所示,注意下标从0开始。
预测的时候,我们讲,如果某个 object 的中心落在一个网格中,则这个网格就负责预测这个 object. 虽然每个网格可以预测
B
B
B个bounding box,但是最终只选择IOU最高的 bounding box 作为物体检测输出,即每个网格最多只预测出一个物体。当物体画面占比较小时,如图像中包含畜群或鸟群,每个网格将包含多个物体,但却只能检测出其中一个。这是YOLO方法的一个缺陷。
2. 网络框架
受GoogLeNet启发,YOLO V1有24个卷积层+2个全连接层。没有用Inception模块,而是用1×1卷积+3×3卷积。1×1卷积用来降维,3×3卷积用来恢复到正常通道数。
YOLO V1在 ImageNet1000 类上预训练,预训练的时候只使用网络的前20个卷积层 + 1个全连接。
预训练后用到检测网络上,去掉全连接,加了4个卷积层和2个全连接。
3. loss func
首先,每个网格有 30 维,其中 8 个维度是回归的 box 的坐标,2 个维度是 box 的置信度,还有 20 个维度是类别(注意 B = 2 B = 2 B=2)
下面给出 loss func 的完整形式,之后再逐条解释内部的东西:
接着,我们按照如下的 loss func 的形式来仔细分析。
l o s s = b o x 的 回 归 + 预 测 物 体 的 置 信 度 + 预 测 背 景 的 置 信 度 + 类 别 的 预 测 loss = box 的回归 + 预测物体的置信度 + 预测背景的置信度 + 类别的预测 loss=box的回归+预测物体的置信度+预测背景的置信度+类别的预测
在 loss func 中作者使用平方和衡量误差,主要是考虑到它很容易进行优化。但是细节上存在两个问题:
- 将分类误差与定位误差赋予一样的权重,这显然是不合理的
- 如果一个网格中不包含 object,那么这些网格预测的 box 的置信度就会被推到 0,相比于较少的有 object 的网格, 这种在做法会导致训练早起发散
于是,引入了两个权重系数 λ c o o r d , λ n o o b j \lambda_{coord}, \lambda_{noobj} λcoord,λnoobj:
- 作者认为定位误差应该被重视,给这些损失以更大的 loss weight, λ c o o r d \lambda_{coord} λcoord在 pascal VOC 中取为 5
- 没有 object 的 box 的confidence loss 应该被赋予更小的 loss weight, λ n o o b j \lambda_{noobj} λnoobj在 pascal VOC 中取为 0.5
于是,我们有了
l o s s = λ c o o r d b o x 的 回 归 + 预 测 物 体 的 置 信 度 + λ n o o b j 预 测 背 景 的 置 信 度 + 类 别 的 预 测 loss = \lambda_{coord}\ box 的回归 + 预测物体的置信度 + \lambda_{noobj}\ 预测背景的置信度 + 类别的预测 loss=λcoord box的回归+预测物体的置信度+λnoobj 预测背景的置信度+类别的预测
对于不同大小的 box,相比于大 box 预测偏一点,小 box 预测偏一点似乎更不能忍受。但是用平方和衡量误差,对于大小 box,同样的偏移产生的误差是相同的。为缓解这个问题,作者采用了开方的办法:对 box 的 weight 和height 开平方根,这样小 box 的偏移会产生较大的误差
如,
( 50 − 48 ) 2 ≈ 0.020410 , ( 3 − 1 ) 2 ≈ 0.535900 (\sqrt {50}-\sqrt{48})^2 \approx 0.020410,\ \ (\sqrt {3}-\sqrt{1})^2 \approx 0.535900 (50−48)2≈0.020410, (3−1)2≈0.535900
这样一来,第一项的内容就确定了
λ c o o r d b o x 的 回 归 = λ c o o r d ∑ ∑ ( x i − x i ^ ) 2 + ( y i − y i ^ ) 2 + λ c o o r d ∑ ∑ ( w i − w i ^ ) 2 + ( h i − h i ^ ) 2 \lambda_{coord}\ box 的回归 = \lambda_{coord}\sum\sum(x_i-\hat{x_i})^2+(y_i-\hat{y_i})^2+ \lambda_{coord}\sum\sum(\sqrt{w_i}-\sqrt{\hat{w_i}})^2+(\sqrt{h_i}-\sqrt{\hat{h_i}})^2 λcoord box的回归=λcoord∑∑(xi−xi^)2+(yi−yi^)2+λcoord∑∑(wi−wi^)2+(hi−hi^)2
对比完整的 loss func,我们发现少了个示性函数,为什么要有这个示性函数呢?
回想前面提到网格是如何做预测的: 如果某个 object 的中心落在一个网格中,则这个网格就负责预测这个 object
于是,在 loss func 中,只有当某个网格中有object的时候才对classification error进行惩罚;只有当某个box predictor 对某个 ground truth box 负责的时候,才会对 box 的 coordinate error进行惩罚,而对哪个ground truth box 负责就看其预测值和 ground truth box 的 IoU是不是在那个网格的所有 box 中最大
到此为止,整个 loss func 就讲清楚了,最后提一处, C C C是 box 的置信度,其计算公式如下:
C = P r ( O b j e c t ) ∗ I O U p r e d t r u t h \begin{aligned}C = Pr(Object)*IOU_{pred}^{truth}\end{aligned} C=Pr(Object)∗IOUpredtruth
其中, P r ( O b j e c t ) Pr(Object) Pr(Object)为示性函数,如果有 object 落在网格中,则取 1,反之,取 0
最后,我们再看一眼完整的 loss func
4. Testing
测试的时候,每个网格预测的 class信息 ( P r ( C l a s s i ∣ O b j e c t ) Pr(Class_i | Object) Pr(Classi∣Object) )和 bounding box预测的置信度信息( P r ( O b j e c t ) ∗ I O U p r e d t r u t h Pr(Object) \ast IOU^{truth}_{pred} Pr(Object)∗IOUpredtruth) 相乘,就得到每个bounding box 的 class-specific confidence score
对每一个网格的每一个 box 执行相同的操作,总共
7
×
7
×
2
=
98
7\times 7 \times 2 = 98
7×7×2=98个 box
得到每个 box的 class-specific confidence score 以后,设置阈值,滤掉得分低的 boxes,对保留的 boxes 进行 NMS 处理(关于 NMS 处理参考NMS——非极大值抑制),就得到最终的检测结果。
下面示例狗狗的 NMS 处理过程:
我们重复上面的过程计算其他类别,最终得到 NMS 处理完之后,box 的很多类别置信度都被置为了0,而在 box 的类别置信度向量中,最大值指明了这个 box 的预测类别。
5. 总结
优点
- 速度快,能够达到实时的要求
缺点
- YOLO V1 对相互靠的很近的物体,还有很小的群体检测效果不好,这是因为一个网格中只预测了两个框,并且只属于一类;
- 对测试图像中,同一类物体出现的新的不常见的长宽比和其他情况是,YOLOV1泛化能力偏弱;
- 由于损失函数的问题,定位误差是影响检测效果的主要原因。尤其在大小物体的处理上,还有待加强。