YOLOv1和YOLOv2
我是根据这两个视频学习的:
YOLOv1:全网最清楚的YOLO V1原理讲解,打牢YOLO目标检测算法基础!_哔哩哔哩_bilibili
YOLOv2:YOLOv2算法精讲,超级清晰,包你听懂!_哔哩哔哩_bilibili
知识补充
目标检测是计算机视觉的重要任务,它有两个子任务:检测和定位
检测是识别这张图片里面有什么
定位是不仅要识别出这张图片里面有什么,还要知道这个物体在这张图片的位置,画出边界框
主流方法:one-stage方法和two-stage方法(单阶段检测方法和双阶段检测方法)
单阶段方法主要注重推理速度,例如:YOLO/SSD/RetinaNet,从图像中同时预测物体的类别和位置,速度更快,主要用于视频监控
两阶段方法主要注重推理精度,例如:Faster R-CNN/Mask R-CNN/Cascade R-CNN
这两张图就对比了单阶段方法和双阶段方法的过程,它们都是对输入图像先经过一个主干网络backbone进行特征提取,不同的是,单阶段方法会直接给出类别和边界框,而两阶段方法会先生成一系列候选区域,然后再进行分类和定位任务,得到类别和边界框
目标检测领域的重要数据集:MSCOCO数据集,包含了丰富物体的标注
边界框是矩形的区域标签,在监督学习中,目标检测模型会利用这些边界框来学习图像的内容
对于模型预测给出的边界框,它的评价指标有IoU(交并比),它表示模型预测的box和数据集中标注的真实box,它们的交集比上它们的并集,来衡量预测框和真实框它们融合的程度,这是一个0~1之间的数,当预测框和真实框完全重合时,IoU就是1,当预测框和真实框没有重合时,IoU就是0
YOLO
YOLO:You Only Look Once,是一个先进的实时检测方法,与传统的检测方法不同,YOLO是在整个图像上同时进行检测,而不像传统算法那样对图像的多个区域进行分类检测,具有更高的效率和检测速度
虽然YOLO在许多场景中表现优秀,但对小物体和相互接近的物体的检测表现较差,这是因为YOLO的网格系统会限制检测的精度
YOLO的创造者:Joseph Redmon,于2015年首次提出了YOLO框架,后面又开发了YOLOv2和YOLOv3,但是在2020年,他因为AI在军事问题中的应用而产生伦理顾虑,发现YOLO的算法被用于在无人机上进行军事打击,所以他停止了计算机视觉的研究
在Joseph Redmon放弃研究之后,Alexey Bochkovskiy在2020年接手了这份工作,发布了YOLOv4,重点优化了网络的超参数,并引入了IoU的损失函数,进一步提升了检测精度和稳定性
YOLOv1
输入图像的尺寸为448x448x3,也就是每一张图像的大小为448x448像素,且有3个通道,分别为RGB,图像会经过若干的卷积层,我们这里叫Back-Bone网络,然后通过全连接网络再输出一个7x7x30的张量(tensor)
训练阶段:7x7x30的tensor作为网络的输出,这个输出的目的是通过和输入图像的标签建立联系,也就是通过损失函数来计算损失,来优化网络的权重,从而使得预测能够更加接近真实的标签
推理阶段:网络的输出就是一个一个效果很好的边界框,同时边界框带有框内物体的类别信息
对物体进行标注
首先将图像分为SxS个网格,对于YOLOv1这个算法,S是7,就是会分成7x7的网格
每个网格会有一个标签向量:[x,y,w,h,Objectness,Class1,Class2,...]
x,y是物体的中心点相对于网络的坐标,w,h是物体边界框的高度和宽度,Objectness是物体存在的概率,如果物体的中心位于这个网格中,那么Objectness就是1,否则为0,Class1,Class2,...表示网格中的物体属于不同类别的概率
例如这个狗的例子,这个狗的中心落在了这个网格上,所以这个网格对应的标签,它的Objectness就是1,因为这是一个狗的中心,不是其他类别的中心,所以只有狗这个类别是1,其他的是0
x、y、w和h描述了这个边界框的信息,x和y是物体的中心点相对于这个网格的坐标,例如以网格的左上角为(0,0),右下角为(1,1),所以x是0.25,y是0.60,w和h是整个边界框占图像的比例,狗的边界框大约是2.5个网格的长度,所以w是2.5除以7,大约为0.34,h大约是4个网格的长度,所以是4除以7,大约是0.57
如果出现多个物体的中心点落在一个网格里面,YOLOv1无法处理这种情况,YOLOv1仅为该网格分配一个类别标签
YOLOv1的输出
YOLOv1的输出是一个7x7x30的tensor,详细解释如下:
YOLO算法将目标检测视为一个回归问题,把图像分成SxS的网格,YOLOv1的输出是一个7x7x30的tensor,可以看出有1x1x30的tensor,然后有49个1x1x30的tensor堆叠起来的。每一个1x1x30的tensor对了图像中一个网格中的预测结果,每一个网格会预测出B个边界框,对于YOLOv1取的B为2,也就是会预测出两个边界框
比如红色的网格,它在输出中所对应的两个边界框分别是紫色和绿色的第一行,对于绿色的网格,它在输出中对应的两个边界框就是第二行,每一个边界框有五个值,这五个值分别是x,y,w,h和置信度,前四个值描述了所预测出来边界框的位置
置信度的计算公式为:
Pr(Object)表示网格中是否存在物体的概率,如果网格中存在物体,这个概率就是1,否则为0,IoU是预测框和真实框的交并比,如果网格中没有物体,那么置信度就为0,如果网格中有物体,那置信度就等于真实框和预测框之间的IoU值
同时每一个网格还负责预测一系列的类别概率,在网格中有物体的情况下是第i类的概率:
,即1x1x30的tensor最右边白色部分的区域,我们会预测20个类别,所以白色部分有20个,是tensor的11到30的位置
训练阶段的tensor
输入图像会被分成SxS个网格,每个网格就负责预测物体中心落在该网格中的类别和边界框,红框是真实框,在训练阶段通过前向传播,模型会给出两个边界框,我们会选择其他在一个与真实框进行比对,选择的方法是:我们会分别计算这两个边界框与真实框的交并比,显然大的黄色的边界框与红色的真实框交并比会比较高,所以我们会删除小的黄色边界框,留下大的黄色边界框,然后计算大的黄框与红色的真实框之间的损失,通过这个损失来进行反向传播,来更新参数
损失函数的计算公式:
YOLOv1的输出是一个7x7x30的tensor,其中每一个1x1x30的tensor的结构如图所示,分为两个边界框,每个边界框有五个坐标,前四个坐标是描述边界框的位置大小,最后一个坐标是描述置信度,两个box之后是20个类别概率,对于其中第i个概率,它描述的就是模型认为这个box所框柱的物体是第i个类别的概率
损失函数分为三个部分:
第一个是边界框回归损失,用来计算真实框的xywh和预测框的xywh之间的差别,使用的是一个简单的平方损失函数,其中1(ij)(obj)描述的是第i个网格中的第j个box,如果第j个box是我们选择的box,则1(ij)(obj)取1,否则取0,也就是说我们这里只计算用于检测的那个box与真实框之间的损失,λ是用来调节不同损失之间的权重,取7
第二个是边界框得分预测损失,用来计算物体存在的置信度误差,分为两项,第一项是对于第i个网格的用于检测的那个box,它的置信度和网格中存在物体的概率(Ci要么是0,要么是1),它们之间的平方损失,第二项是对于第i个网格的不用于检测的box,它的置信度和网格中存在物体的概率的平方损失,前面乘以一个λ,取0.5
第三项是类别预测损失,用于计算模型预测类别概率和真实类别概率之间的误差,1(i)(obj)表示如果有某个物体落在了第i个网格里,这项就取1,否则取0,这个损失计算的是每个网格所预测的这20个类别概率分别与真实概率的平方损失
把这些一起求和,就构成了YOLOv1完整的损失函数
推理阶段的tensor
在推理阶段,每个网格会输出两个预测框,也就是说我们会得到7x7x2=98个预测框,每一个预测框都有一个自己的置信度,我们用粗细来区分了不同的置信度,置信度越大,越粗,同时我们还知道了每一个网格最有可能预测的物体是哪个,公式为:
Pr(Class(i) | Object)表示在网格中有物体的情况下是第i个类别的概率,乘上该网格中有物体的概率,再乘上预测框和真实框之间的IoU,前两项相乘就得到了网格中是第i个类别的概率
通过这个全概率,我们得到了一个概率图,知道了每一个网格最有可能预测的物体是哪个,两个图片结合到一起,就变成了彩色的框图,现在的问题就变成了,怎么从这98个预测框中选出最好的两个框,也就是最后的预测结果,这就用到了一项技术,非极大值抑制(NMS)
由公式可知,前面所得到的概率图是将两个预测框的置信度分别乘以后面条件概率构成的向量,得到两个全概率,这样对于每一个网格,我们会得到2个新向量,我们有49个网格,所以会得到98个由全概率组成的向量,这98个向量的每一个维度都表示这个预测框是这个类的概率,我们会依次处理这每一个类别的概率,比如第一个类别是狗,我们会设置一个阈值(threshold),这里取0.2,将是狗类别的概率小于0.2的值直接抹零,然后将这98个向量,重新按照dog的概率大小进行排序,得到右边这98个向量,也就是bb7的概率最大,bb84概率最小
我们将这一列单独拿出来,我们会将概率最大的bb7也第二大的bb46进行比较,如果这两个框的IoU大于0.5,那我们认为这两个框的重合比例是很大的,它们可能框的是同一个物体,那我们就要删掉一个,所以我们将概率小的0.3置为0
然后我们用同样的方法,找到概率第三大的预测框,然后去和红色的预测框进行比较,我们发现,这两个的IoU是小于0.5的,所以我们可以知道这两个可能框住的不是同一只狗,保留这个蓝框,以此类推,我们会比较这97个概率,它们和bb7概率的IoU,然后作出决定,是保留还是删除
比较完与bb7的概率后,我们会将0.2视为新的最大概率,继续将之后的预测框与bb40这个预测框的IoU进行比较,例如bb23和bb40的IoU是大于0.5的,它们可能框柱的是同一个物体,所以我们将bb23的0.1置为0,以此类推,直到后面的元素全部是0时结束
这里假设我们只保留了0.5和0.2这两个框,显然,还没有结束,这个蓝色的预测框显然不是狗,因为我只是在狗的类别里面保留了它,但是在后面的类别里面,比如自行车类别,可能也保留了bb40,而且它的概率比0.2大,那肯定要把bb40的框赋给自行车类别了,因此我们前面对dog类别的操作要对后面的类别全部都做一次
比如我们对于第二个类别bicycle,先将概率小于0.2的置零,然后按照从大到小的顺序进行排序,以此类推,直到最后一个类别结束
最后我们得到的98个向量所组成的矩阵是一个很稀疏的矩阵,有很多零,我们会挑出不全为零的box,并把它画在输入图像上,得到这样三个box,我们还要为这三个box赋予标签,赋予标签的时候,可能这个box所对应的类别的概率不只有一个,比如刚刚的0.2和0.5,那我们选择值最大的
YOLOv2
对于YOLOv1,输入图像被划分为7x7的网格,每个网格只能预测两个边界框,并且这两个边界框属于同一个类别,所以YOLOv1最多只能预测出98个边界框,49个类别,这种设计就导致了几个问题:
1.在处理小而密集的物体时表现不好,小而密集的物体的中心会落在同一个网格中,但一个网格只能预测两个边界框,所以其中的一些就预测不出来,同时如果图片中的物体较多,多于49个时,其他类别的物体就检测不出来了;2.在面对一个网格中包含多个类别时,YOLOv1也会感到力不从心,比如两个类别的物体同时出现在一个网格中,但一个网格只能输出一个类别,必然会忽略另一个物体,这显然就限制了它在多目标检测任务中的能力;3.YOLOv1对不常见的物体的横纵比表现不佳,对于那些横纵比表现与众不同的物体,训练集中没有覆盖到,那么YOLOv1就无法给出理想的边界框预测;4.相比来看,YOLOv1相较于先进的两阶段检测方法,比如R-CNN、Fast R-CNN和Faster R-CNN,YOLOv1的速度虽然很好,但是准确率仍然存在着一些劣势
那么YOLOv2就在其基础之上进行了一些改进,网络结构上的改进主要有两点:1.使用了新的主干网络Darknet19;2.实现了对细粒度特征的提取;在训练策略上的改进主要有:1.高分辨率分类器;2.多尺度的训练策略
在训练阶段,网络输出的目的是为了优化网络的参数,所以我们关注的重点是YOLOv2的输出是什么样子的网络结构,它的输出是如何与图像的标签通过损失函数进行关联,这样才能通过反向传播,更新网络的参数
在推理阶段,我们要关注的是YOLOv2的输出是如何转化为最终的预测的,这里几乎和YOLOv1是一样的
Darknet-19
Darknet-19是一个深度卷积神经网络,在现在来看是一个平平无奇的网络,但是在当时,它还是有可圈可点的地方的
在这个卷积网络中,每个卷积模块里,在数学里,两个3x3卷积的感受野是等于一个5x5卷积的,三个3x3卷积的感受野等于一个7x7卷积,这就意味着,通过组合几个较小的卷积核,网络就能够有效地进行特征提取,获得一个比较大的感受野,避免了更大的卷积核所带来的计算开销,但是在近几年的研究中,人们发现三个3x3卷积的感受野是远不如一个7x7的感受野的,所以在近几年的卷积网络中,人们经常是一个更大的卷积核来获得一个更大的感受野
从图中可以看出,3x3卷积中都夹了一个1x1卷积,1x1卷积的作用是它不改变特征图的大小,但是它能够调整通道的维度,通过调整通道的维度来减小计算量,先把通道数降低,然后再进行3x3卷积
Darknet-19的优势在于减少了参数量的同时,提高了网络效率,还保留了足够的感受野
Darknet-19中还有两个技术细节:Batch Normalization和Global Average Pooling,现在来看不是很先进的技术了,但在当时来看还是很新的
批归一化(Batch Normalization):有助于加速模型的收敛,并防止梯度消失或爆炸,进一步提高了模型的稳定性,在Darknet-19中,不管是3x3卷积,还是1x1卷积,后面都会跟着一个Batch Normalization,技术的具体后面会讲
全局平均池化(Global Average Pooling):它发生在网络的最后阶段,我们把输出的特征图的每一个通道堆叠成一个值,比如在图中,输出特征图是1000个通道,那我们把每一个通道都取一个平均值,就得到了一个1000维的向量,将它输送到Softmax层进行分类,能够避免YOLOv1那种通过堆叠多个全连接网络来进行分类所造成的参数爆炸的问题
YOLOv2是一个目标检测模型,所以最后没有平均池化层和Softmax层,所以这里不介绍全局平均池化技术了
批归一化
在深度学习中,训练过程通常会遇到一个问题,叫做内部协变量偏移,这个问题是指网络中每一层的输入分布会随着网络参数的更新而不断发生变化,具体来说,就是随着训练的进行,网络的每一层都会受到前一层参数更新的影响,这个影响通常是渐进的,但随着层级的加深,前面层微小的变化就可能在后面被逐层地放大,这就意味着,随着训练的进行,网络的每一层都需要不断的试验前一层输出的新的分布,从而导致训练过程中的收敛速度变慢,这种现象的后果就会是梯度消失或梯度爆炸,由于层和层之间输入的不断变化,就可能导致梯度在反向传播的过程中出现梯度消失或梯度爆炸这种现象,使得训练的过程不稳定,针对这种现象,我们往往要进行非常精细的超参数调整,比如参数的初始化,如果这些参数设置的不当,训练也会变得非常困难,同时我们也难以使用像sigmoid这样的饱和非线性激活函数
对于sigmoid函数,当输入值比较大或比较小的时候,梯度是几乎为0的,就出现了梯度消失的现象,使得网络的更新是非常缓慢的
为了解决这个问题,就提出了批归一化技术,要对每一层的输入进行标准化,使其大致符合方差为1,均值为0的,这个标准化是一个mini-batch上进行的
处理来自全连接层输出的数据
输入的数据结构如图所示,假如我们有一个小批量数据集x,它由m个样本组成,每个样本有d个特征,可以理解为一个d x m的矩阵,每一行代表一个样本,每一列代表一个特征,我们要对这个矩阵中每个元素进行归一化,归一化的方式就是减均值,除以标准差
首先我们需要计算每个特征的均值,对于第k个特征,它的均值的计算公式就是第一个,将第k个特征的m个样本加在一起,然后取平均就是第k个特征的均值,对应于矩阵中,则是将一列求和,然后取平均得到每个特征的均值,在计算方差时也是,计算一列上数据的方差,也就是第二个公式
对于第k个特征的第i个元素,用它原来的值减去均值,除以标准差来得到更新后的值,这里的是一个小的波动,来防止分母为0,这样我们就将第k个特征的数据进行了标准化,使得它符合均值为0,方差为1的高斯分布,若是对所有特征都进行这样处理,这样的处理有点死板了,网络的表达能力受到了限制,所以我们对于每一个归一化后的数值还会乘以一个
,加上一个
,这两个参数是在网络中自动学习的,
叫做伸缩参数,
叫做平移参数,使得每一层数的分布在大致符合方差为1,均值为0的高斯分布的基础上,又有一些微小的波动,有一些多样性
首先是一个全连接层或卷积层,然后对这个层的输出进行Batch Normalization,然后再将它送入激活函数中进行处理,刚刚我们说的Batch Normalization的处理方法是对全连接层的数据的,对于卷积网络,我们如何计算均值和方差呢?
处理来自卷积网络层输出的数据
我们的处理手段是,对于卷积网络,Batch Normalization是对每个通道进行归一化的,比如这是一个batch,它有两个样本,我们会在蓝色的通道上算一个均值,得到,算一个方差,得到
,然后对这个蓝色通道的每一个元素,用
和
进行归一化,其他通道同理
为什么对于卷积网络的处理是在每个通道上进行呢?我们认为卷积层的一个通道就类比于全连接层的一个特征维度
卷积网络的两个假设:局部连接和参数共享
局部连接:每个卷积核和输入图像进行卷积的时候,只是和输入图像的一个局部区域进行卷积,得到输出特征图的一个元素,然后在输入特征图上进行扫描,得到完整的输出特征图
参数共享:同一个卷积核在扫描输入图像的时候,在不同的位置应该有相同的权重的,也就是说,我们认为,一个卷积核就是我们提取的一个特征,比如输入是一张人脸图像,蓝色的卷积核是提取眼睛的特征,对应于输出的一个通道,绿色的卷积核负责提取鼻子这个特征,然后对应于输出的一个通道,因此批归一化需要对每个通道进行归一化,这样就可以确保每个特征在这个小批量上是具有一致的分布的
Batch Normalization具有一个很显著的问题,就是训练阶段和推理阶段的适配,在推理阶段,由于我们没有整个batch的数据,那么批归一化就不能在一个小批量上计算了,取而代之的是使用在训练阶段累积的运行统计量,那么这些统计量就包含了训练过程中不断更新的全局信息,在推理时,我们使用的均值和方差有以下两种方法:
1.第一种方法就是使用训练阶段的全局均值和方差,我们会计算所有batch的第k个特征,然后加起来取一个平均,来得到推理阶段要用到的第k个特征的均值,对于第k个特征的方差,也是同理,我们会计算所有batch上第k个特征的方差,然后取一个均值,在训练阶段,我们用到的是1/m,是一个有偏的方差,在推理阶段,我们希望用到的是一个无偏的方差,所以是m/m-1
这种方法有一个缺点,就是要存储在训练阶段所有batch的均值和方差,改良的方法如下
2.第二种方法是在训练中使用指数滑动平均来更新均值和方差
在归一化方法中,不止有batch norm,还有layer norm、instance norm和group norm,batch norm主要用于卷积网络中,layer norm通常用于循环网络中
这是没有使用批归一化的网络:
这是使用归一化的网络:在全连接层和激活函数中间使用了批归一化
以下展示了训练过程中SimpleNet第一层后激活分布,红色曲线是没有使用批归一化,它的激活分布是偏离了理想的高斯分布,随着训练的进行,激活分布会变得不稳定,导致模型难以收敛,绿色曲线代表了使用批归一化,即使在训练了20个epoch后,它的激活分布仍然是一个很平稳的高斯分布,批归一化帮助保持了激活值的稳定性,缓解了内部协变量的偏移
以下图片展示了训练损失随着迭代次数的变化,可以看到,带有批归一化的模型,它的收敛速度明显是更快的,训练损失能够在短时间内迅速的下降,且具有良好的稳定性
批归一化一开始提出的动机是缓解协变量偏移,但之后的研究发现,批归一化的主要优势并不是缓解了内部的协变量偏移,可以看到,橙色的是没有采用批归一化的每一层的激活分布,蓝色的是使用了每一层的激活分布,可以看到,使用了批归一化的内部协变量偏移相对于没有使用批归一化,得到了缓解,并且准确率要比没有使用批归一化的时候要好得多
但是作者又进行了一个实验,他在使用批归一化的基础上又加入了一些噪声发现,它的协变量偏移比没有使用噪声且没有加入批归一化的协变量偏移,还要严重,但准确率曲线比它要好,和使用了批归一化但没有加入噪声的准确率差不多,这就说明了批归一化优化训练的原因并不是它能够缓解协变量偏移,那是什么原因呢?
作者提出,它为训练的目标函数空间引入了平滑约束,原来优化目标函数的地形图是这样的,通过批归一化增加了平滑约束,使得目标函数空间变得更加平滑,有助于减少训练过程中的剧烈波动,模型可以使用更大的学习率,找到更好的局部机制
通过引入批归一化,网络的mAP提高了2%
细粒度特征的提取
在YOLOv2中,随着这些卷积层的堆叠,特诊图的分辨率也逐渐地降低,作者认为这损失了很多细粒度的特征,导致了小尺寸物体的识别效果不佳,为了结合浅层的高分辨率特征和深层的低分辨率特征,YOLOv2通过passthrough层,将它们整合在一起,使得网络能够同时利用这两种特征,就是将26x26x512的tensor和13x13x1024的tensor两个整合在一起
将26x26x512的特征图分为四个部分,每一个部分是13x13x512的,然后拼接起来,再和13x13x1024拼接起来,这个组合的过程并且是如果进行重排的,我们稍后再讲,最后就得到了13x13x3072,也就是网络在绿色格子的输出
通过细粒度特征的融合,YOLOv2能够更好地处理不同尺寸的物体,尤其是在检测小物体时有了更强的能力,这样的改进,使得网络的mAP提高了1%
组合的过程
我们以4x4x3的tensor为例,它有三个通道,对于第一个通道,蓝色位置所对应的元素,也就是,从第一行第一列元素开始,从竖列和行列,都隔一个元素取一个,得到的这四个蓝色的元素,拼成了输出特征图的一个通道,同理,对于输入的第二个通道,这四个蓝色元素也能拼成输出特征图的第二个通道,以此类推,这样我们就得到了输出特征图的前三个通道,接着从一行二列开始,以此类推,这样4x4x3的tensor就变成了2x2x12的tensor
高分辨率分类器
在YOLOv1中,图像分类任务会被作为一个预训练步骤在分辨率是224x224的ImageNet数据集上进行训练,来帮助网络学习到有效的学习特征,在进行目标检测的时候,网络的输入分辨率会被提高到448x448,这样会使网络在学习检测任务时需要调整权重和参数,以应对分辨率的变化对特征提取的影响
在YOLOv2中,作者采取了不同的方法来处理这个问题,在预训练阶段,YOLOv2仍然在224x224输入分辨率的ImageNet数据集下进行分类任务的预训练,在此基础上,YOLOv2进行了一个微调,将输入分辨率从224放大到448,并在ImageNet数据集上微调了10个epoch,网络就获得了更多时间来调整参数,使得能够更好地适应放大后的分辨率,由于在微调中,网络已经见过比较大的分辨率了,因此在训练目标检测任务的时候,就能够更有效地利用这一分辨率,提高了4%mAP
在YOLOv2中,最后使用的输入图像的大小从448x448调整到了416x416,目的是使得输出特征图的空间维度变为奇数,左边是YOLOv2的主干网络,输入的是416x416的图像,输出的是13x13的tensor,也就是奇数x奇数的tensor,如果改成448x448的输入,输出就会变成14x14,是一个偶数x偶数的输出,它们有什么区别呢?
和YOLOv1一样,输出是多少x多少的大小,那么我们就认为是把输入图像划分为了多少x多少的网格,那么训练阶段,真实框的中心点落在了哪个网格,就用这个网格去拟合这个真实框
作者认为,很多物体的中心会落在整张图像的中心上,例如右边这张图,狗的中心落在了这四个网格的中点,究竟用哪个网格来表示这个物体呢,并且不管用哪个网格,这个点都偏离网格很远,这对训练也是不利的
多尺度训练
在多尺度训练中,每次加载图像,图像的大小会根据当前的批次进行调整,比如使用320x320的输入尺寸,随着训练的进行,经过10个batch,我们就会更改输入分辨率的大小,可能改成352x352的,可能改成416x416的,可能改成608x608的,这种随机选择不同尺寸的方式,就确保了网络能够适应不同大小的物体,并且,通过使用不同的分辨率进行训练,网络不会过度地依赖某一种特定的尺度,这就减少了对训练中特定物体尺寸的过拟合,使得模型提升对不同尺寸物体的泛化能力,YOLOv2又提高了1.5%mAP
输入的尺寸改变之后,网络的结构是不用改的,因为网络的结构其实就是一个一个卷积核,它和输入的尺寸是无关的,只是最后输出的特征图的大小改变了,输出特征图的大小改变了,对应的标签也要随着改变,首先边界框的长宽我们要按照比例进行调整,边界框中心点的坐标我们也要按照比例进行调整,总之我们要确保标签在新的图像尺寸中也是位置准确的,调整完标签之后,就可以与网络的输出进行匹配了
高分辨率分类器和多尺度训练的区别
高分辨率分类器发生在预训练阶段,也就是分类网络的训练阶段,它的输入图像的尺寸是固定的,就是448x448,它是为了从训练分类网络到训练预测网络,切换分辨率的时候不至于产生很大的不适,它的实现方式就是在预训练的分类网络中通过修改输入的分辨率,让网络在高分辨率的情况下进行训练,从而提高在分类任务中的表现
多尺度训练发生在检测训练任务阶段,输入图像的尺寸是动态变化的,每隔十个批次就会重新选择一个输入分辨率,这样做的目的是增强模型对不同尺寸输入的适应性,实现方式是在多尺度训练中动态调整输入尺寸,促使网络在不同分辨率下进行学习,提高其对各种尺度物体的检测能力
训练阶段的处理
YOLOv2网络输出的数据结构,在YOLOv2中,输出的张量是13x13x5x(4+1+C),13x13是特征图的尺寸,它对应输入图像上的13x13个网格,5表示每个网所预测出的边界框,YOLOv1是预测出两个边界框,(4+1+C)表示边界框的输出内容,有四个预测框参数、
、
和
,预测的是输出边界框的位置信息,和YOLOv1不同,这里的位置不直接就是预测框的具体位置了,而是相对于锚框的微调值,我们稍后介绍,还有一个置信度参数,表示网络对物体是否存在的信息,计算公式为:网络中有物体的概率乘上预测框和真实框的IoU,和YOLOv1不同的是,网络的输出不直接是置信度了,而是
,这个
放在
函数里面,才是置信度
YOLOv1中,是两个预测框共享了一组类别概率,在YOLOv2中,每一个边界框都有一个类别概率,这也就代表了YOLOv2输出的五个预测框,可以有五个不同的类别的,和YOLOv1相同,这个概率是一个条件概率,在网格有物体的情况下,它是第i类的概率,我们如果要得到全概率,就要用这个条件概率乘上网格中是否有物体存在的概率
如果我们采用20个类别的话,这里的输出就是13x13x5x(4+1+20)的结构
锚框
锚框(Anchor Boxes),在YOLOv1的初期训练阶段,网络对于边界框的预测是非常任意的,这样就无法捕捉到物体的真实边界框,这种猜测就会对不同的物体表现的差异比较大,比如竖条形状的边界框预测人会比较好,但预测车就会表现地很差
但在实际的应用场景中,边界框并不是任意的,比如汽车的形状和尺寸很相似,因此它们的边界框也具有相似的长宽比,行人的边界框通常也具有相似的尺寸和比例的,这就意味着在物体的检测中,我们可以利用物体的几何特性来设计一个更合适的边界框,在YOLOv2的后续版本中,模型就引入了锚框的概念,锚框是预定义的边界框形状,就是它的大小长宽都是固定的,是人为设定好的
比如我们可以定义这五个锚框,在采用锚框后,模型不会任意预测5个边界框了,它会基于这五个锚框进行预测,它会预测五个相对于锚框的偏移量,通过这个锚框和锚框的偏移量,我们就能确定模型预测的预测框,换句话说,锚框就像是最初始的预测框,网络通过调整锚框和锚框的偏移量来优化预测框,使得预测框更加地准确
蓝框就是预测框,它的中心点坐标就是和
,宽度是
,高度是
,负责预测这个预测框的网格就是这个红色的网格,这个红色网格左上角的坐标定义为(
,
),与这个蓝色预测框所匹配的锚框,(每一个预测框都是由一个锚框生成的)我们记录这个锚框的宽度是
,高度为
,YOLOv2会预测出来五个数,
、
、
、
和
我们看它们是如何转化为预测框的参数的,与Faster R-CNN不同,这里和
的位置是直接预测得到的,没有使用到锚框。网络的输出
经过
函数,得到的认为是预测框的中心点相对于网格的左上角偏移的坐标,相当于YOLOv1中x的坐标,这里是
(
),
(
)同理,这两个输出结果是介于0~1之间的,这样模型最终得到的检测框的中心点一定在对应的网格中,不会偏离的太远,最后加上
或者
后就能得到预测框的中心点坐标,预测框的
和
是在锚框的基础上生成的,它是用锚框的宽度
乘以一个指数偏移量
,这个
是网络的输出,这里也就建立了预测框大小和锚框大小的关系,通过这种直接位置预测的方法,mAP又提高了5%
和YOLOv1一样,在训练阶段,真实框的中心点位于哪个网格中,那个网格就负责预测物体的位置和类别,通过前向传播,网络会输出五个预测框,这五个预测框不像YOLOv1那样随机生成的,它是基于五个anchor偏移得到的,我们就保留这五个预测框中和真实框的IoU最大的那个预测框,未来我就用它来进一步精细地调整,来拟合真实框,对于这个图,只有小女孩的中心点落到了网格里面,假如还有一个物体落到了这个网格里面,那我就会在五个预测框里面保留两个,保留和小女孩的真实框的IoU大的,再保留和另一个物体真实框的IoU大的,也就是网格中有几个物体,就会输出几个预测框。如果两个物体都是瘦高形状,那也会输出基于两个不同anchor的偏移,不会基于一个anchor
损失函数
YOLO的损失函数分为三个部分,分别是定位损失、置信度损失和类别损失,、
、
和
是预测框的位置和大小,
、
、
和
是锚框的位置和大小,其中
和
是人为设定的,并将锚框的中心点设置在了真实框的中心点上,那么
就是0.5+
,定位损失用来计算边界框的位置误差,它分为两项,第一项是计算所有预测边界框与锚框之间的位置误差,并且它只在前12000步进行,也就是在训练初期,我们希望模型先来学习锚框的位置,希望
尽量接近
,也就是说希望
(
)尽量接近0.5,
尽量接近
,也就是希望
和
尽量接近0;第二项是对于第i个网格所生成的第j个预测框,如果这个检测框是负责检测物体的预测框,我们就计算这个预测框的位置和真实框的位置之间的位置损失,x、y、w和h是真实框的位置信息
置信度损失,第一项是对于第i个网格的第j个预测框,如果是负责检测物体的预测框,我们就计算它的置信度和标签的置信度之间的损失,和YOLOv1一样,标签的置信度是非0即1的;第二项是对于第i个网格的第j个预测框,如果它不是负责检测物体的预测框,我们看它和真实框之间的IoU,如果是大于阈值的,我们就认为这个预测框里是包含目标的,那么它就不参与这一项置信度损失的计算,否则我们就认为这一项是不包含物体的,然后计算置信度损失,置信度的真值是0
分类损失,第i个网格的第j个预测框,如果是负责检测物体的预测框,计算它的c个类别概率和真实框的c个类别概率之间的损失,和YOLOv1一样
人为给定的锚框不是随便给的,YOLO采用K-means聚类的方法来识别出训练数据中最适合的锚框,具体做法是:我们对训练数据进行K-means聚类,然后把这些训练数据的真实框聚为K个类,选择K个聚类中心作为K个锚框,K-means一般是对向量进行聚类的,通过计算样本之间的距离,比如欧氏距离或马氏距离来衡量相似度,那对于边界框怎么衡量距离呢?答案是使用IoU,边界框之间的IoU越大,我们就认为它们之间的距离越近,这张图就展示了不同的聚类数目与真实框之间的平均IoU,可以看出,随着锚点数量的增加,IoU的准确性是逐渐增大的,但是最终是趋于平缓的,但是聚类数越多,就会带来更大的开销,所以我们这里就采用了手肘法,选择一个类似于手肘的地方,在这个的时候,聚类数目不是特别多,同时也有一个比较高的精度了,如果聚类地再多,收益也不大,右边就展示了五个锚框的形状,紫色的矩形是来自于COCO数据集聚类得到的锚框,白色的矩形表示VOC数据集聚类得到的锚框,可以看出这两种锚框大小是相似的,是因为现实生活中物体的边界框并不是随机分布的,它们是具有特定的比例和形态特征的
推理阶段的处理
首先输入图像会被分割为多个网格单元,对于YOLOv2是13x13个网格单元,每个网格都会产生五个预测框,这五个预测框是基于anchor偏移得到的,这个预测框不止有坐标信息,还有类别信息,以及置信度信息,通过非极大值抑制技术来保留置信度较高的那些框,同时移除重叠度较大的低置信度框,最终YOLO就会根据每个框的类别概率和置信度输出最合适的边界框,就输出了bicycle和car,这就是最终的检测结果
这张图是论文中的一张图,对比了引入刚才介绍的种种改进策略以后,在VOC数据集上mAP的变化,可以看到,在引入这些技术之后,几乎都使得mAP有了增长,除了使用anchor使得mAP有了一个很小的下降,这个下降是可以忽略不计的,那我们为什么还要引入anchor呢?是因为在引入anchor之后,对召回率的影响非常显著,同时计算量减少了33%
这样,通过以上方法的改进,YOLOv1从63.4%的mAP提高到了YOLO2的78.6%的mAP
那速度如何呢?这个表格展示了不同模型的Top1准确率、Top5准确率、浮点运算量和GPU速度,可以看到Darknet19在GPU速度上表现非常突出,达到了200FPS,同时保持了比较高的准确率,Top1准确率达到了74.0%,Top5准确率达到了91.8%,但相较于其他模型,它所使用的浮点运算量是5.85Bn,也比较少,这样Darknet19就成功地在准确性和速度上找到了一个比较好的平衡
这张图是不同输入的YOLOv2的表现,可以看到,在相同速度的情况下,YOLOv2的精度最高,在相同精度的情况下,YOLOv2的速度最快
所以YOLOv2在当时是一个非常好的目标检测算法