Yolo(You Only Look Once)是一种one-stage目标检测算法,即仅需要 “看” 一次就可以识别出图片中物体的class类别和位置。作为one-stage的开山鼻祖,YOLOv1以其简洁的网络结构和GPU上的实时检测速度而一鸣惊人,打破了R-CNN的“垄断”地位,为目标检测领域带来巨大的变革。
Yolov1将目标检测任务重新定义为单个回归问题,仅使用一个卷积神经网络直接预测图像的Bounding box及其class类别的概率。 并且检测速度较快,普通的Yolov1模型实时处理图像速度可达到45帧每秒。更轻小的Fast Yolo,每秒处理速度则可高达155帧。
尽管以现在的眼光看Yolov1是由很多弊端的,但是它是后续one-stage工作的基础,里程碑意义不可磨灭。
Yolov1整体网络结构如下图。
Yolov1的Backbone网络仿照GoogLeNet网络搭建,但并没有采用Inception模块,而是使用1x1卷积层和3x3卷积层堆砌。
从整体来看,Yolov1网络接收一张输入图像大小为448x448的RGB图像,经由Backbone网络处理后输出一个空间大小被降采样了64倍(网络最终的stride为64(448/7=64))的特征图,该特征图是一个维度为7x7x1024的三维张量,其中7x7是特征图的宽和高,1024是将经过卷积网络处理后的通道数。特征图再经过全连接层处理、维度转换等操作,输出7x7x30的一维张量。
Yolov1的输入和输出如下图所示。
为什么是7x7x30的输出?
Yolov1将一个448x448的原图片分割为7x7=49个grid cell,每个grid cell预测B个Bounding box的坐标(x,y,w,h)和box内是否包含目标物体的置信度confidence(共5个参数,B=2),以及该grid cell包含的目标物体属于C个class类别中某一类的概率(训练数据集为voc2012,包含20个class类别,C=20),所以每一个grid cell对应 (5x2+20=) 30个预测参数。
综上,网络最终输出的预测参数总量就是SxSx(5B+C),其中(S=输入图像尺寸/网络最大的stride)。
将输入的图像划分为SxS的grid cell,如果某个目标物体的中心点落到其中一个grid cell中,则该grid cell会负责检测此目标物。其中,Yolov1中,S=7,即划分为49个grid cell。
如下图狗的中心落在了阴影的小grid cell中,则该grid cell负责预测狗。
每个grid cell会预测B个Bounding box边界框(Yolov1中B=2,当然无论B的数量是多少,一个grid cell只负责预测一个目标,因此7×7=49个grid cell最多只能预测49个物体。),每个Bounding box有自己对应的置信度,这些Bounding box大小尺寸可随意,但是生成的Bounding box的中心点必须在grid cell中。
每个Bounding box可以用(x,y,w,h,c)这五个参数表示,其中,
(x,y):表示Bounding box预测框的中心坐标相较于该Bounding box(中心点)归属的grid cell左上角的偏移量,取值在0-1之间。如下图,绿点是grid cell的左上角(0,0),红色和蓝色框是该grid cell包含的2个Bounding box,二者中心坐标分别为红点和蓝点。二者的(x,y)分别是(0.5,0.5)和(0.9,0.9)。
注意:Bounding box的中心坐标一定是在其对应grid cell里面,因此红点和蓝点的坐标可以归一化到0-1之间。
(w,h):表示Bounding box预测框的宽和高相对于原图片宽和高的比例。Yolov1输入图像是448*448,假设Bounding box预测框的宽和高是44.8个像素,则w=0.1,h=0.1。
c:置信度confidence,用于表征网格中是否有目标物中心点或包含目标物的概率以及预测的边框位置的准确度。对于边界框位置的准确度,通常(使用预测的Bounding box与物体真实的边界框的)交并比IoU(Interaction over Union)来衡量。IoU越接近于1,表明目标物边框与边界框重合度越高。置信度计算公式为: c o n f i d e n c e = P r ( O b j e c t ) ∗ I o U p r e d t r u t h confidence=Pr(Object)*IoU_{pred}^{truth} confidence=Pr(Object)∗IoUpredtruth ,Pr(Object)表示Box中包含目标物的概率。若Box中包含目标物,Pr(Object)=1,此时置信度等于IoU,反之置信度为0。
每个grid cell会预测出20个class类别概率(Yolov1中C=20,训练数据集是20类),可通过条件概率计算得到,记为 P r ( c l a s s i ∣ o b j e c t ) Pr(class_i|object) Pr(classi∣object) 。
P r ( c l a s s i ∣ o b j e c t ) ∗ P r ( O b j e c t ) ∗ I o U p r e d t r u t h = P r ( c l a s s i ) ∗ I o U p r e d t r u t h Pr(class_i|object)*Pr(Object)*IoU_{pred}^{truth}=Pr(class_i)*IoU_{pred}^{truth} Pr(classi∣object)∗Pr(Object)∗IoUpredtruth=Pr(classi)∗IoUpredtruth
无论一个grid cell中包含多少Bounding box,一个grid cell只能预测一个物体,这是Yolov1对小目标物体检测性能较差的原因。如果原图片比较密集,grid cell中可能存在多个物体,Yolo模型只能预测其中一个,那么自然会忽略grid cell内的其它物体。
我们知道深度学习的训练即就是通过梯度下降和反向传播法的迭代去微调网络神经元的权重,以使得损失函数最小化的过程。
目标检测是一个典型的监督学习问题,训练集上会给定输入图像及其标签(标记好ground truth),算法的实现思路就是尽可能的去拟合人工标记的框,使损失函数达到最小。训练阶段,每个grid cell预测两个Bounding box,与ground truth交并比(IoU)最大的那个Bounding box负责拟合ground truth。
预训练: 首先在ImageNet(1000-class类别)数据集上预训练一个分类网络,该网络是Yolov1网络结构中所示的前20个卷积网络++1个平均池化层+1个全连接层,网络输入是224x224。
模型微调:
(1):在预训练模型基础上添加4个卷积层和2个全连接层(这里直接会替换预训练模型中的一个全连接层),新添加的层采用随机初始化参数。
(2):为了提取更细粒度的视觉信息,因此将网络输入图像的分辨率由224x224调整到448x448。
归一化:
(1):分别除以图像的宽和高使输出中的w、h归一化到[0,1]区间。
(2):通过将坐标(x,y)限制为特定网格中的相对位置,同样使其归一化至[0,1]区间。
激活函数:最终的全连接层采用线性激活函数,其它所有层均采用leaky ReLU激活函数。
损失函数:具体介绍见下文。
Yolov1损失函数包括三部分:边界框损失(Bounding box loss)、置信度损失(confidence loss)和分类损失(classification loss),其中置信度损失又可以细分为包含目标的Bbox的置信度损失和未包含目标的Bbox的置信度损失两种。计算方法如下:
注意
这里对宽和高的损失处理分别取了根号,因为如若不取根号,损失函数往往更倾向于调整尺寸比较大的预测框。例如20个像素点的偏差,对于800x600的预测框几乎没有影响,此时IoU值还是很大,
但是对于30x40的预测框影响就很大。取根号就是为了尽可能消除大尺寸框和小尺寸框之间的差异。其本质也就是尺度归一化。
Yolov1网络输入是448x448的图像,输出是7x7x30的张量。每张图片分成49个grid cell,每个grid cell预测2个Bounding box,整个推理过程会产生98个检测框。多数情况下,模型能够清晰的判断目标中心位置位于哪个grid cell,然后仅用一个Bounding box预测目标位置。对于较大或者位于多个网格边界的目标物,可能会被多个网格同时较好地定位,此时则采用非极大值抑制NMS的方法,去除冗余,即对于同一目标物只保留置信度(这里等于IoU)最大的Bounding box。
注意:训练阶段不需要NMS处理。
推理过程如下图所示。每个grid cell包含2个Bounding box和20个class类别class类别的条件概率,每个Bounding box又会包含4个box位置坐标和1个box置信度,每个box置信度与20个class类别class类别的条件概率分别相乘,得到一个权概率(20*1),因此每个grid cell有2个权概率,整个推理过程有7x7x2=98个权概率。
然后将98个权概率分别以颜色(class类别)和粗细(box置信度)加持,可视化即可得到如下图②的98个框。经过NMS非极大值抑制之后,进而得到图③的检测结果。
NMS核心思想:
选择权概率最高的作为输出,与该输出重叠的去掉,不断重复这一过程直到所有候选对象处理完成。
NMS计算方法:
网络输出7x7x30的张量,计算NMS即是求每一个grid cell中, c l a s s i class_i classi位于第j个Bounding box的得分。该得分表示 c l a s s i class_i classi位于第j个Bounding box的可能性/概率。
每个网格包括:20个class类别对象的概率*2个Bounding box的置信度=40个得分(候选对象)。49个网格共1960个得分。每种class类别对象分别进行NMS,那么每种对象有1960/20=98个得分。
NMS处理过程:
设置Score阈值,低于该阈值的候选对象对应的Score置零。
遍历每一个对象class类别(20个class类别):
遍历每个对象class类别的98个得分:
输出列表即为预测的对象。
至此,关于Yolov1网络结构、算法流程、训练及推理原理的讲解基本完成。关于Yolov1是如何工作的,相信读者也有了基本的认识。然而,“纸上得来终觉浅,绝知此事要躬行”,只有亲自动手才能够真正地掌握所学到的知识。为此,我们将在下一章进入实战环节。