本篇是关于目标检测算法YOLOv1的学习笔记。网上的博客大多是摘抄翻译论文中的重点内容加上自己的理解,或者是梳理论文的大致思路,在没看过原文的情况下可能总会有些看不懂的地方。所以强烈建议博客搭配原文食用。
原文链接:You Only Look Once: Unified, Real-Time Object Detection
一、YOLOv1的创新点及优势
YOLOv1是CVPR2016的文章, 相比于当时比较优秀的目标检测算法(如R-CNN、DPM), YOLO有如下创新点和优势:
1. 主要创新点:
- 不像其它目标检测算法(例如R-CNN)采用region_proposal(回归问题) + classifiers(分类问题)的检测方式,而是将目标检测当作一个回归(regression) 问题来处理。
- 使用单个网络,输入一整张图像仅经过一次推理可以得到图像中所有目标的检测框和所属类别。同时可以直接端到端(end-to-end) 地训练和优化网络。
2. 算法优势:
- YOLO的首要优势就是快,同时可以保持较高的准确率。其标准版模型在Tian X GPU上可以达到实时的45fps。另外YOLO还提供了一个fast版本,速度高达150fps,同时其检测精度大概是其它实时检测系统的2倍。
- YOLO使用全图的上下文信息,使得它相比于Fast R-CNN有更少的背景错误(在没有目标的背景区域错误地检测出目标)
- 泛化能力、通用性更好,面对新领域和意外输入时地表现比R-CNN等更稳定。
二、目标检测逻辑和模型输出表示
YOLO目标检测的基本流程如下:
a. 将输入图片尺寸Resize为448*448(YOLOv1只能输入固定尺寸的图像);
b. 经过单个CNN网络进行特征提取和预测;
c. 通过设定阈值筛选检测框。
1. 目标检测逻辑(重点难点)
YOLO首先将输入图片切成S*S
个网格:
(1)每个网格预测 B
个Bbox(边界框) ,以及每个边界框的confidence值,confidence表征对应边界框内存在目标的把握,以及框位置、大小的准确度。
每个边界框对应5个参数:x
,y
,w
,h
,confidence
。其中,
- (
x
,y
) 表示边界框中心 相对于网格 的坐标; -
w
,h
表示边界框 相对于整张图像 的宽和高(意思是边界框的中心坐标必须在网格内,但其宽和高不受网格限制、可以随意超过网格大小); confidence
定义为:当边界框中不存在目标时,confienec应等于0;当边界框中存在目标时,confidence应等于这一边界框和物体的真实边界框的IoU,可以表示为:
【需要注意的是:这里说的“边界框中存在目标”是指目标的中心位置落入该边界框中。例如上面第二张图中,“狗”的中心位置落在第5行第2列的网格当中,那么只有这个网格产生的B个边界框内才算是存在“狗”这一目标,最终YOLO会指派这B个边界框中和“狗”的真实标注框IoU最高一个来专门负责检测这只“狗”,在文章中这被称作specialization(专门化)】
(2)每个网格还会预测 C
个条件类别概率值,它表示当有目标的中心位置“落入”该网格中时,这一目标属于C个类别的概率分布。
2. 模型输出表示
根据以上目标检测逻辑,模型最终输出S*S*(B*5+C)
大小的tensor。在YOLOv1论文中,选用了S=7,B=2,由于使用的PASCAL VOC数据集有20个类别标签,因此C=20,于是模型最终预测输出一个7*7*30
的tensor。
图解YOLO 一文中将输出的tensor可视化,以助于我们理解。
三、网络设计及训练
YOLO网络借鉴了GoogleLeNet图像分类模型(也就是Inception v1)。不同的是,YOLO并没有采用Inception模块,而是简单采用11 reduction层后跟33卷积层。标准版YOLO共有24个卷积层后跟2个全连接层(网络结构如下图)。Fast YOLO则只有9个卷积层,其它参数和标准版一致。
模型训练相关设置如下:
- 预训练:模型首先在ImageNet图像数据集上进行预训练。参与预训练的模型并不是上图所示完整的模型结构,仅是其前20个卷积层+1个平均池化层+1个全连接层,且参与预训练模型的输入是244*244。
- 模型微调:在预训练完成后,对预训练好的图像分类模型进行微调,以实现目标检测。具体做法是:(1)添加4个卷积层和2个全连接层(个人理解这里应该会把预训练模型最后的全连接层替换掉),新添加的层采用随机初始化参数;(2)为了更好地提取视觉信息,将输入图像的分辨率由
244*224
提高到448*448
。 - 归一化:通过分别除以图像的宽和高使输出中的w、h归一化到[0,1]区间;通过将坐标(x,y)限制为特定网格中的相对位置,同样使其归一化至[0,1]区间。
- 激活函数:最终的全连接层采用线性激活函数(linear activation);其它所有层均采用leaky ReLU激活函数。
- 损失函数:YOLO采用均方和误差(sum-squared error)作为损失函数,因为它很容易进行优化。但是它对于提高平模型的平均精度却不是十分理想,于是针对以下几个问题进行优化:
- 位置误差和分类误差对loss的贡献应当是不同的,因此在计算loss时引入来修正坐标损失。
- 每张图像中都有许多网格是不包含任何目标的(即没有目标的中心点落入这些网格内),这会使得大部分网格内边界框的confidence值偏向于0,变相放大了包含目标的网格的confidence误差在计算梯度时的影响。YOLO引入来修正这一影响。
- 相同的位置偏差对大物体的IoU error的影响要远小于对小物体的影响,因此YOLO通过将物体大小的信息项(w,h)开平方来修正平衡二者的影响。
最终修正后的损失函数(loss function)的表达式为:
- 训练超参数
- num_epochs(训练周期数)大约为135
- batch_size = 64
- 优化器:momentum=0.9,decay=0.0005
- 学习率前期采用了warm up,之后随着训练的进行再逐渐衰减
- 正则化(抑制过拟合)
- dropout(rate=0.5)
- 采用随机缩放和平移的方式进行数据增强
四、模型推理
YOLO进行推理和训练时一样,对于一张图片只需要由单个模型进行一次推理。对于PASCAL VOC数据集,模型会预测出98个检测框(S*S*B=7*7*2
).
YOLO使用划分网格的方式进行检测。多数情况下,模型能够清晰地判断目标中心位置“落入”了哪个网格,然后对于一个目标仅用一个边界框去预测它的位置。然而,对于一些比较大的物体、或者位于多个网格边界的物体,可能会被多个网格同时较好地定位,这时采用非极大抑制(NMS) 的方法,即对于同一目标只保留confidence(这里等于IoU)最大的边界框。
五、YOLOv1算法缺陷
本文不再介绍YOLOv1实验效果上的相关内容,感兴趣的话可以直接阅读原文。原文中提到了YOLOv1算法的一些缺陷:
- 由于每个网格只能预测2个边界框和1个类别,这限制了对相近目标的检测数量,尤其是比较集种的小物体检测(如鸟群)。
- 由于模型从数据中学习,对于常规的数据能够较好泛化,但难以推广到一些不寻常的长宽比或配置,即泛化能力有限。
- 损失函数设计还不够合理,主要是其中定位误差的影响、尤其是对大小物体的处理上。
参考文献