yolo-v3

背景

YOLO是一种端到端的目标检测模型。YOLO算法的基本思想是:首先通过特征提取网络对输入特征提取特征,得到特定大小的特征图输出。输入图像分成grid cell,接着如果真实框中某个object的中心坐标落在某个grid cell中,那么就由该grid cell来预测该object。每个object有固定数量的bounding box,YOLO v3中有三个bounding box,使用逻辑回归确定用来预测的回归框。

先分析一下yolo_v3上保留的东西:

l “分而治之”,从yolo_v1开始,yolo算法就是通过划分单元格来做检测,只是划分的数量不一样。

l 采用"leaky ReLU"作为激活函数。

l 端到端进行训练。一个loss function搞定训练,只需关注输入端和输出端。

l 从yolo_v2开始,yolo就用batch
normalization作为正则化、加速收敛和避免过拟合的方法,把BN层和leaky relu层接到每一层卷积层之后。

l 多尺度训练。在速度和准确率之间tradeoff。想速度快点,可以牺牲准确率;想准确率高点儿,可以牺牲一点速度。

yolo每一代的提升很大一部分决定于backbone网络的提升,从v2的darknet-19到v3的darknet-53。yolo_v3还提供替换backbone——tiny darknet。要想性能牛叉,backbone可以用Darknet-53,要想轻量高速,可以用tiny-darknet。总之,yolo就是天生“灵活”,所以特别适合作为工程算法。

网络结构

在这里插入图片描述
在这里插入图片描述

l DBL:代码中的Darknetconv2d_BN_Leaky,是yolo_v3的基本组件。就是卷积+BN+Leaky relu。

l resn:n代表数字,有res1,res2, … ,res8等等,表示这个res_block里含有多少个res_unit。

l concat:张量拼接。将darknet中间层和后面的某一层的上采样进行拼接。拼接的操作和残差层add的操作是不一样的,拼接会扩充张量的维度,而add只是直接相加不会导致张量维度的改变。

整个yolo_v3_body包含252层,组成如下:

在这里插入图片描述

根据表0可以得出,对于代码层面的layers数量一共有252层,包括add层23层(主要用于res_block的构成,每个res_unit需要一个add层,一共有1+2+8+8+4=23层)。BN层和LeakyReLU层数量完全一样(72层),在网络结构中的表现为:每一层BN后面都会接一层LeakyReLU。卷积层一共有75层,其中有72层后面都会接BN+LeakyReLU的组合构成基本组件DBL。上采样和concat都有2次。每个res_block都会用上一个零填充,一共有5个res_block。

下面逐个分析

Backbone部分:

在这里插入图片描述

整个v3结构里面,是没有池化层和全连接层的。前向传播过程中,张量的尺寸变换是通过改变卷积核的步长来实现的,比如stride=(2, 2),这就等于将图像边长缩小了一半(即面积缩小到原来的1/4)。在yolo_v2中,要经历5次缩小,会将特征图缩小到原输入尺寸的1/2^5,即1/32。输入为416x416,则输出为13x13(416/32=13)。

yolo_v3也和v2一样,backbone都会将输出特征图缩小到输入的1/32。所以,通常都要求输入图片是32的倍数。yolo_v2中对于前向过程中张量尺寸变换,都是通过最大池化来进行,一共有5次。而v3是通过卷积核增大步长来进行,也是5次。(darknet-53最后面有一个全局平均池化,在yolo-v3里面没有这一层,所以张量维度变化只考虑前面那5次)。可以对比v2和v3的backbone看看:(DarkNet-19 与 DarkNet-53,)
在这里插入图片描述

Yolo_v3使用了darknet-53的前面的52层(没有全连接层),yolo_v3这个网络是一个全卷积网络,大量使用残差的跳层连接,并且为了降低池化带来的梯度负面效果,作者直接摒弃了POOLing,用conv的stride来实现降采样。在这个网络结构中,使用的是步长为2的卷积来进行降采样。

特征图融合部分:

在这里插入图片描述

为了加强算法对小目标检测的精确度,YOLO v3中采用类似FPN的upsample和融合做法(最后融合了3个scale,其他两个scale的大小分别是26×26和52×52),在多个scale的feature map上做检测。

作者在3条预测支路采用的也是全卷积的结构,其中最后一个卷积层的卷积核个数是255,是针对COCO数据集的80类:3*(80+4+1)=255,3表示一个grid cell包含3个bounding box,4表示框的4个坐标信息,1表示objectness score。

Output部分:

在这里插入图片描述

所谓的多尺度就是来自这3条预测之路,y1,y2和y3的深度都是255,边长的规律是13:26:52。yolo v3设定的是每个网格单元预测3个box,所以每个box需要有(x, y, w, h, confidence)五个基本参数,然后还要有80个类别的概率,所以3×(5 + 80) = 255(即一行代表了一个网格,由三个“5+80”元素组成)。那么总共有(1313+2626+52*52)*3=10674个先验框,如下:

在这里插入图片描述

网络中作者进行了三次检测,分别是在32倍降采样,16倍降采样,8倍降采样时进行检测。在网络中使用up-sample(上采样)的原因:网络越深的特征表达效果越好。比如在进行16倍降采样检测,如果直接使用第四次下采样的特征来检测,这样就使用了浅层特征,这样效果一般并不好,从而添加32倍降采样后的特征,但深层特征的大小太小,因此yolo_v3使用了步长为2的up-sample(上采样),把32倍降采样得到的feature map的大小提升一倍,也就成了16倍降采样后的维度。同理8倍采样也是对16倍降采样的特征进行步长为2的上采样,这样就可以使用深层特征进行detection。

如下图所示,85层将13×13×256的特征上采样得到26×26×256,再将其与61层的特征拼接起来得到26×26×768。为了得到channel255,还需要进行一系列的3×3,1×1卷积操作,这样既可以提高非线性程度增加泛化性能提高网络精度,又能减少参数提高实时性。52×52×255的特征也是类似的过程。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

核心点

聚类得到预测框的尺寸

对于Yolo v3关于bounding box的初始尺寸还是采用Yolo v2中的k-means聚类的方式来做。在yolo_v2和yolo_v3中,都采用了对图像中的object采用k-means聚类。 同样地,YOLO v3选择的默认框有9个。其尺寸可以通过k-means算法在数据集上聚类得到。在COCO数据集上,9个聚类是:(10×13);(16×30);(33×23);(30×61);(62×45); (59×119); (116×90); (156×198); (373×326)。三次检测,每次对应的感受野不同,32倍降采样的感受野最大,适合检测大的目标,所以在输入为416×416时,每个cell的三个anchor box为(116 ,90); (156
,198); (373 ,326)。16倍适合一般大小的物体,anchor
box为(30,61); (62,45); (59,119)。8倍的感受野最小,适合检测小目标,因此anchor box为(10,13); (16,30);
(33,23)。所以当输入为416×416时,实际总共有(52×52+26×26+13×13)×3=10647个proposal box。

在这里插入图片描述

预测框的输出-(tx,ty,tw,th,t0)

feature map中的每一个cell都会预测3个边界框(bounding box) ,每个bounding box都会预测三个东西:1. 每个框的位置微调量(4个值,中心坐标tx和ty,框的高度bh和宽度bw);2. 一个objectness
prediction ;3. N个类别,coco数据集80类,voc20类。然后采用和v2相同的公式给出最终的预测:

在这里插入图片描述

Yolo v3采用直接预测相对位置的方法。预测出b-box中心点相对于网格单元左上角的相对坐标。直接预测出(tx,ty,tw,th,t0),然后通过以下坐标偏移公式计算得到b-box的位置大小和confidence。

下图9种先验框的尺寸,下图中蓝色框为聚类得到的先验框。黄色框式ground truth,红框是对象中心点所在的网格:

在这里插入图片描述

网络输出

现在我们得到1W多个先验框的位置信息、置信度、类别概率向量,如下:
在这里插入图片描述

首先将类别概率中最大的类别用蓝色标出,

在这里插入图片描述

然后乘以置信度,得到联合概率,

在这里插入图片描述

然后用联合概率更换掉置信度,

在这里插入图片描述

然后设置阈值(阈值这个时候训练的时候设置低一些,测试的时候可以高一些),如果联合概率小于阈值,则将该预测框去掉,

在这里插入图片描述

然后将得到的先验框,按照联合概率的大小降序排列,

在这里插入图片描述

然后进行NMS,

在这里插入图片描述

NMS过程:

  1. 经过上述排序,我们知道“bb666”先验框的联合概率最高,不防假设“bb666”先验框预测类别“狗”。那么“bb666”先验框显示其预测类别是“狗”的把握最大,那么先将其拿出,放到新的地方储存区,
    在这里插入图片描述

  2. 现在将“bb666”先验框和其他预测类别是“狗”的,进行NMS,假若IOU大于阈值,则将其删除(这个阈值尽量低一些,因为如果两只狗挨得很近,这时候如果太高,很可能只能框出一只狗)。如下图,与绿框“bb666”先验框进行NMS,其中蓝框和粉红框与绿框IOU大于阈值,则将其删除,下图的虚线框

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  1. 这个时候假设剩余先验框中概率最大的是“bb95”,不妨假设其看到的是“自行车”(当然也有可能是上一个类别“狗”,也就是图中可能存在多个“狗”,而先验框预测的是另一个“狗”),那么将“bb95”先验框拿到新的存储区域,

在这里插入图片描述

  1. 还需要再对剩余的先验框按照联合概率重新排序

在这里插入图片描述

  1. 然后将“bb95”先验框和剩余的预测为“自行车”类别的先验框,进行相同的NMS操作,

在这里插入图片描述

  1. 这样一直循环,直到最后没有先验框,

在这里插入图片描述

损失函数

YOLOv3重要改变之一:No more softmaxing the classes。YOLO v3现在对图像中检测到的对象执行多标签分类。

早期YOLO,作者曾用softmax获取类别得分并用最大得分的标签来表示包含再边界框内的目标,在YOLOv3中,这种做法被修正。softmax来分类依赖于这样一个前提,即分类是相互独立的,换句话说,如果一个目标属于一种类别,那么它就不能属于另一种。但是,当我们的数据集中存在人或女人的标签时,上面所提到的前提就是去了意义。这就是作者为什么不用softmax,而用logistic regression来预测每个类别得分并使用一个阈值来对目标进行多标签预测。比阈值高的类别就是这个边界框真正的类别。用简单一点的语言来说,其实就是对每种类别使用二分类的logistic回归,即你要么是这种类别要么就不是,然后便利所有类别,得到所有类别的得分,然后选取大于阈值的类别就好了。

作者使用了logistic回归来对每个anchor包围的内容进行了一个目标性评分(objectness score)。根据目标性评分来选择anchor prior进行predict,而不是所有anchor prior都会有输出。

相比于v1中简单的总方误差,还是有一些调整的:除了w, h的损失函数依然采用总方误差之外,其他部分的损失函数用的是二值交叉熵。最后加到一起。下面为代码中损失函数:

在这里插入图片描述

其中只有v1给出损失函数,其余版本未给出,可以去看源码。其余版本可能未必是原始的。当然也可以利用其他的损失函数,比如RetinaNet中的“focal loss”或者GIoU等。

训练过程:

  1. 利用预训练

  2. 利用检测网络,得到1W左右的先验框;对其进行NMS操作

  3. 对于剩余的利用LOSS,进行迭代网络参数

测试:

  1. 利用检测网络得到先验框

  2. 进行nms,得到结果

可以改进的点:

YOLO-SPP

在第一层添加SPP层,也就是用不同的尺寸的池化层,分别池化,然后通道叠加,如下

在这里插入图片描述
在这里插入图片描述

NMS部分可以弹性变化,如下

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值