引言
前不久Redmon宣布将退出视觉的研究,让许多YOLO算法的爱好者遗憾不已。
YOLO是one-stage物体检测的代表性算法之一,自从出道以来,就以检测速度著称,但是v1和v2版本的算法检测精度偏低,比two-stage方法低太多,而且由于算法本身的设计问题,导致小目标经常无法检测到。
Redmon在2018年重新改进了该算法,主要包括引进了FPN的网络设计和检测头部,改善了损失函数和先验框设计等等。
Bounding Box
先验框还是沿用了v2版本的设计,每个框会预测四个坐标数据:
t
x
t_x
tx,
t
y
t_y
ty,
t
w
t_w
tw,
t
h
t_h
th,这个四个坐标是经过实际坐标数据变换而成的,变换的公式如下:
b
x
=
σ
(
t
x
)
+
c
x
b
y
=
σ
(
t
y
)
+
c
y
b
w
=
p
w
e
t
w
b
h
=
p
h
e
t
h
\begin{aligned} & b_x = \sigma (t_x) + c_x \\ & b_y = \sigma (t_y) + c_y \\ & b_w = p_w e^{t_w} \\ & b_h = p_h e^{t_h} \end{aligned}
bx=σ(tx)+cxby=σ(ty)+cybw=pwetwbh=pheth
其中,
b
x
b_x
bx,
b
y
b_y
by,
b
w
b_w
bw,
b
h
b_h
bh分别是实际预测框的中心x和y坐标、宽和高,
c
x
c_x
cx,
c
y
c_y
cy是先验框所在网络的左上角坐标,
p
w
p_w
pw,
p
h
p_h
ph分别是先验框的宽和高。公式中几个变量的关系如下图所示。
通过上面的公式的反变换,可以计算出
t
x
t_x
tx,
t
y
t_y
ty,
t
w
t_w
tw,
t
h
t_h
th的大小,损失函数是以这四个变换后的坐标值作为计算对象,使用MSE的方法。
YOLOv3的先验框和ground truth之间关联与先前的版本方法不同,之前的版本一个网络里的所有检测框只跟一个ground truth对应,而v3网格里的不同检测框可以分别对应一个ground truth。匹配方规则如下:
- 一个先验框只和一个ground truth绑定,如果先验框没有和ground truth绑定,那么就不会计算这些先验框的坐标损失函数;
- 如果先验框与某个ground truth框的IoU大于其他的先验框,那么该先验框就和这个ground truth绑定在一起,在先验框的目标得分上标记为1;
- 在剩余的检测框中,如果与某个ground truth的IoU大于0.5,那么该框也会绑定该ground truth。
分类器
与之前版本采用softmax的方法不同,v3使用的是每个类别的逻辑回归分类器,在损失函数上则使用二值交叉熵。softmax每次只能预测一个类别,不适合用在多标签的数据上,而类别独立的逻辑回归则可以很好地应用在像Open Images这种多类别的数据集上。
多尺度
v1和v2版本的YOLO只能在一个尺度上(13*13)预测位置,导致了之前小目标物体经常无法被检测到。YOLOv3则是在3个不同的尺度上分别基于三种大小的先验框进行预测。
v3算法的多尺度预测方法借鉴了FPN的思想,在backbone的最后一层网络用来生成bounding box、目标值和分类的3维tensor,在COCO实验中,这个维度大小是
N
×
N
×
[
3
∗
(
4
+
1
+
80
)
]
N \times N \times [3*(4+1+80)]
N×N×[3∗(4+1+80)],其中N是输出特征的长宽大小(第一个尺度上是13),4是前面介绍的bounding box的坐标值,1是该框是否为目标的预测,80则是COCO数据集的类别数。
在第二个尺度上,将第一个尺度上的卷积特征经过一个两倍的上采样,和backbone上最后一个
26
×
26
26 \times 26
26×26上的特征向量concate在一起,再经过几层卷积后,输出尺度(26)的3维tensor。
第三个尺度的处理方法与第二个相似,不同的是用第二个尺度的卷积特征上采样和backbone中
52
×
52
52 \times 52
52×52的特征衔接在一起。
这样处理的作用是充分利用最后提取的卷积信息和高分辨率上的特征互相融合补偿,高分辨率的特征能预测更多小目标的物体,而低分辨率的语义特征信息则提取得更充分,两则互相补充促进。
作者通过k-means的方法聚类了9个先验框,将9个框任意平均分配给三个尺度上,每个尺度3个。在COCO数据集中,9个聚类框大小分别是:
(
10
×
13
)
(10\times13)
(10×13),
(
16
×
30
)
(16\times30)
(16×30),
(
33
×
23
)
(33\times23)
(33×23),
(
30
×
61
)
(30\times61)
(30×61),
(
62
×
45
)
(62\times45)
(62×45),
(
59
×
119
)
(59\times119)
(59×119),
(
116
×
90
)
(116\times90)
(116×90),
(
156
×
198
)
(156\times198)
(156×198),
(
373
×
326
)
(373\times326)
(373×326)。
Backbone
作者也对之前的特征提取backbone进行改进,相比YOLOv2的Darknet-19,v3版本增加了残差模块的思想,每个残差块由
3
×
3
3\times3
3×3和
1
×
1
1\times1
1×1的卷积和shorcut连接构成,同时将卷积层数增加到了53层,所以新的backbone就叫做Darknet-53,就这么言简意赅。Darknet-53的网络结构如下图所示。
论文中将Darknet-53和ResNet-101和ResNet-152在ImageNet上作对比,从下面这个表格可以看出,Darknet-53的网络在分类精度上与ResNet-101相当,略小于ResNet-152,但是在计算量比两者都小,在推理速度上是ResNet-101的1.5倍,是ResNet-152的两倍。
实验结果
话不多说,直接上表格吧。
从表格中可以看出,YOLOv3在COCO数据集上的AP几乎和SSD相当,但是速度却高出了3倍,不过和RetinaNet相比,精度上还有不小的差距。
如果使用IoU为0.5的指标进行比较,YOLOv3的性能确实相当不错的,不仅远超SSD,几乎可以和RetinaNet相媲美,但是随着IoU的增加,YOLOv3的精度却下滑得很快。主要原因是YOLOv3这种one-stage的检测算法在框位置的准确性上和two-stage的算法还是有一定劣势的,所以在IoU较小的时候,还能有较高的精度,但是在对IoU要求较高的指标上,准确度就大不如two-stage的算法。
作者还给出了另外一张图,充分显示了作者的特立独行风格,将自己的算法置于第二个象限。结果就不用多说,大家看图就知道了。总之,作者想表达的意思就是:YOLOv3的算法更好更快。
作者在论文中还提到他做过的一些无效的尝试,比如anchor box的x, y坐标预测,对x, y采用线性预测和Focal loss等,给出的原因是:不知道为什么!哈哈哈。
后记
YOLOv3的确是一个非常强大的算法,在18年的时候我使用该算法在公司的数据集上进行尝试,mAP几乎比Faster R-CNN高出了8个点,与加入FPN的Faster R-CNN持平,这的确是一个不小的成就。当然也有可能跟数据集本身的特点有关,不过除了精度之外,YOLOv3的速度真的是吊打two-stage的方法,相同配置相同精度下高出5倍的速度不是问题,在对算力和速度要求比较高的设备和场合非常友好。算法本身采用纯C实现,也方便于部署。