YOLOv2目标检测算法——通俗易懂的解析

目录

YOLOv2目标检测算法

前沿

前面我们讲过了 YOLOv1目标检测算法,不了解的小伙伴可以参考一下博文:

这篇文章我们仍然通俗的介绍下 YOLOv2YOLOv2又叫做 YOLO9000,顾名思义,就是能够检测出9000种类别(有点夸张了,实际上根本做不到,不过作者提到的思路倒是很值得借鉴)。
YOLOv2YOLOv1做了很多的改进,如加了 BNanchor,多尺度训练等 tricksYOLOv2YOLO系列承上启下的算法,可以说 YOLO算法真正的开始算是从 YOLOv2开始的,当然这也不是说 YOLOv1你不用了解了,了解 YOLOv1对学习后面的 YOLO系列具有很大的帮助。
YOLOv1属于 YOLO系类的最初版本,存在着很多的问题,如 recall比较低准确度差定位能力差检测小目标密集型目标性能很差等问题。我们看一下 YOLOv1跟他那个时代已经存在的目标检测模型进行比较。

YOLOv2目标检测算法——通俗易懂的解析
上面讲了 YOLOv1存在四个问题, recall比较低准确度差定位能力差检测小目标密集型目标性能很差,于是 YOLOv2就尝试着对 YOLOv1进行改进,尝试解决这些问题。下面我们正式进入 YOLOv2的讲解。

; 一.YOLOv2的改进

YOLOv2采取了各种各样的手段对 YOLOv1做改进:

  • BN
  • High Resolution Classifier(高分辨率的分类器)
  • Anchor(通过聚类得到)
  • Dimension Cluster
  • Direct location prediction
  • Fine-Grained Feature
  • Multi-Scale Training

下面我们一个一个的来看上面的 tricks分别都做了什么事情

1.1.BN

BN就是 Batch Normalization,批标准化, BN做了什么事情呢?实际上他就是对神经元的输出进行一个归一化的操作,把每个神经元的输出减去均值再除以标准差变成一个以 0为均值, 1为标准差的一个分布的过程。为什么要进行这个 BN操作呢,不做行不行呢? 我们知道很多激活函数如: sigmoidtanh激活函数,他们在 0附近是非饱和区(关于什么是饱和区什么是非饱和区请参考:激活函数中的硬饱和,软饱和,左饱和和右饱和)。如果神经元的输出太大或者太小的话就会陷入激活函数的饱和区,饱和区就意味着梯度消失(导数为 0),导致模型难以训练,所以我们通过 BN 强行的把神经元的输出集中到 0附近。 BN 是包含测试阶段和训练阶段的,尤其要注意测试阶段是怎么处理的,用不好反而适得其反,具体可以参考:Batch Normalization详解以及pytorch实验以及我的一篇博文关于 BNLN的简单介绍:Batchnorm和Layernorm的区别。通过上面的对 BN层的介绍,我们不难得出 BN层一般放在输出特征层的后面,激活函数的前面。总结一下 BN层有哪些好处:

  • 加快模型训练的收敛速度
  • 改善梯度,远离饱和区
  • 可以使用大的学习率,使得模型对初始化不敏感(如果没有使用 BN层就有可能导致神经元的输出都在非饱和区,所以经过BN之后对初始化的敏感度就降低了。)
  • 起到正则化的作用,防止过拟合甚至可以起到 dropout层。 *这里留一个问题:BN和dropout都可以防止过拟合,为什么他们两个一块用不行?

具体可参考:BN和Dropout同时使用的问题

YOLOv2目标检测算法——通俗易懂的解析

; 1.2.High Resolution Classifier

一般模型的训练都是以224 × 224 224\times224 224 ×224尺寸大小在ImageNet上进行训练的,而我们的 YOLOv1模型最后的输入图像时448 × 448 448\times448 448 ×448,如果一个模型原来是在小尺寸上进行训练的现在又在大尺寸上进行训练,那么网络就要学会切换这两种分辨率会带来模型性能的下降。 YOLOv2怎么解决这个问题呢?作者用了最简单粗暴方法,直接在分类图像数据集上以448 × 448 448\times448 448 ×448的尺寸进行骨干网络的训练,让网络适应大分辨率。实际上作者训练的时候是只在分类图像训练骨干网络的最后10个 eopchs切换到448 × 448 448\times448 448 ×448,节省训练时间。通过使用 High Resolution Classifier,模型提高了3.5%mAP。

1.3.anchor

YOLOv2目标检测算法——通俗易懂的解析

anchorYOLOv2的核心。 YOLOv3YOLOv4YOLOv5也是用 anchor机制,近期的一些目标检测算法开始使用 anchor free机制。下面我们来讲下什么是 anchor机制。我们在 YOLOv1里面没有使用 anchor机制,直接使用两个 bounding box,谁跟 ground truth的 I o U IoU I o U大,谁负责去拟合这个 ground truth。这个时候可能会遇到一个问题,这两个 bounding box是不受任何约束的,想怎么变怎么变,想多大就多大,想多宽就多宽,不受约束,你觉得让这样的完全不受限制的框去拟合 ground truth好吗,他能够很准确的预测出待检测物体吗?我们不能说他不好,显然很难训练,没有给他一个限定范围,完全让他俩任意生长,这样做显然是不好的。于是在 YOLOv2里面就引入了 anchor机制,我们不让这两个 bounding box随机生长了,给他们一个限制,加个紧箍咒,给他们一个参考,这个参考就是 anchor,又叫做 先验框。如上图所示以两个 anchor为例,一个瘦高,一个矮胖分别负责预测不同形状的物体。这样的话 bounding box就不会随机生长了,就会有了自己的使命了,知道自己应该预测什么样的物体了。所以这个时候每个预测框只需要预测出它相较于这个 anchor的偏移量就行了。

YOLOv2目标检测算法——通俗易懂的解析

这个时候你又该问了,偏移量又是个什么鬼?不急,带我娓娓道来,上面我们知道了什么是 anchor,所谓的 anchor就是预先设置好的一个限制框,预测框只能根据这个限制框进行预测。下面我们讲下偏移量。上图就是 YOLOv2给出的改进,通过预测偏移量代替直接预测 bounding box,你看到这可能一脸懵逼,这么多符号都是啥意思?我来解释下其中的含义:

  • b x , b y , b w , b h b_{x},b_{y},b_{w},b_{h}b x ​,b y ​,b w ​,b h ​:模型最终得到的检测结果。
  • t x , t y , t w , t h t_{x},t_{y},t_{w},t_{h}t x ​,t y ​,t w ​,t h ​:模型要预测的结果。
  • c x , c y c_{x},c_{y}c x ​,c y ​: grid的左上角坐标。
  • p w , p h p_{w},p_{h}p w ​,p h ​: anchor的宽和高,因为 anchor是人为设定的,所以这两个值是固定的。

有没有发现上面少了一项,置信度。置信度的标签是P r ( o b j e c t ) ∗ I o U ( b , o b j e c t ) = σ ( t o ) Pr(object)*IoU(b,object)=\sigma(t_{o})P r (o bj ec t )∗I o U (b ,o bj ec t )=σ(t o ​),这地方和 YOLOv1是一样的,只不过这地方的置信度经过了一个归一化操作。
通过上面 anchor机制,我们从直接预测 bounding box改为预测一个偏移量,这个偏移量是什么呢,他是不是就是一个基于 anchor框的宽和高和 grid的先验位置的偏移量,得到最终目标的位置,这种方法也叫作 location prediction。注意,因为物体的宽高可能很大,所以并没有对t w , t h t_{w},t_{h}t w ​,t h ​进行限制。只是把t x , t y t_{x},t_{y}t x ​,t y ​中心坐标限制在了 grid里面了(这里有个小小的 bug,我们先不讲,可以自己先想一下, YOLOv4会改进)。刚才我们说了t x , t y , t w , t h t_{x},t_{y},t_{w},t_{h}t x ​,t y ​,t w ​,t h ​是模型要预测的值,那么这几个值应该怎么计算呢?

YOLOv2目标检测算法——通俗易懂的解析

grid cell进行归一化:

YOLOv2目标检测算法——通俗易懂的解析

观察上面的图,我们可以计算出:
t x = l o g [ 0.07 1 − 0.07 ] = − 1.12 t y = l o g [ 0.116 1 − 0.116 ] = − 0.882 t w = l o g ( 240 280 ) = − 0.067 t h = l o g ( 380 230 ) = 0.218 t_{x}=log[\frac{0.07}{1-0.07}]=-1.12\ t_{y}=log[\frac{0.116}{1-0.116}]=-0.882\ t_{w}=log(\frac{240}{280})=-0.067\ t_{h}=log(\frac{380}{230})=0.218 t x ​=l o g [1 −0.07 0.07 ​]=−1.12 t y ​=l o g [1 −0.116 0.116 ​]=−0.882 t w ​=l o g (280 240 ​)=−0.067 t h ​=l o g (230 380 ​)=0.218
关于上面的 0.070.116这些值是怎么来的,我知道你肯定有疑问。下面我们来看下。
首先要明确一下,我们要对每个 grid cell都进行归一化操作,也就是每个计算都是针对每个 grid cell来的。我们知道b x = s i g m o i d ( t x ) + c x b_{x}=sigmoid(t_{x})+c_{x}b x ​=s i g m o i d (t x ​)+c x ​,又因为s i g m o i d ( t x ) = 1 1 + e − t x sigmoid(t_{x})=\frac{1}{1+e^{-t_{x}}}s i g m o i d (t x ​)=1 +e −t x ​1 ​,从而可以推出t x = l o g ( b x − c x 1 − ( b x − c x ) ) t_{x}=log(\frac{b_{x}-c_{x}}{1-(b_{x}-c_{x})})t x ​=l o g (1 −(b x ​−c x ​)b x ​−c x ​​),其他坐标同理,代入 anchor框的宽高、 grid的坐标和预测框的宽高即可计算出t x , t y , t w , t h t_{x},t_{y},t_{w},t_{h}t x ​,t y ​,t w ​,t h ​四个值。
通过上面计算之后,要预测的值就变成了t x , t y , t w , t h = − 1.12 , − 0.882 , − 0.063 , 0.132 t_{x},t_{y},t_{w},t_{h}=-1.12,-0.882,-0.063,0.132 t x ​,t y ​,t w ​,t h ​=−1.12 ,−0.882 ,−0.063 ,0.132这是一个偏移量,这个时候再预测是不是比之前直接预测 bounding box容易多了。
理解这个anchor的核心就是,先验框是事先设定好的,但是呢,我只需要设定的anchor的宽高信息,中心点坐标我自己来预测,因为这个中心点坐标已经被限制在了这个anchor所在的grid cell中了,再怎么预测都不会逃出这个anchor所在的grid cell。
通过上面的讲解,我相信你对 anchor和偏移量已经有了了解了,下面我们回归正题,继续回到 YOLOv2。在 实际训练和预测的时候, YOLOv2是把整个图像给划分成13 × 13 13\times13 13 ×13个 grid,每个 grid5anchor,就是事先指定了5种大小不同的先验框,每个 anchor都对应一个预测框,而这个预测框只需要去负责预测输出他相对于他所在的 anchor偏移量就行了。如下图所示,如果要预测小女孩,人工标注框的中心点落在哪个grid里面就应该由哪个 grid产生的五个 anchor中与 ground truth的I o U IoU I o U最大的那个 anchor去负责拟合 ground truth。而这个 anchor对应的预测框只需要预测他相较于这个 anchor的偏移量就行了,意思就是在这个 anchor的基础上进行预测。

YOLOv2目标检测算法——通俗易懂的解析

YOLOv2目标检测算法——通俗易懂的解析
我们知道每个 grid 都有 5anchorground truth落在哪个 grid就由哪个 grid产生的五个 anchor中的一个来负责预测预测这个 ground truth,总共5个 anchor,那么由哪一个 anchor去负责预测呢?由与 anchor的I o U IoU I o U最大的那个去负责预测。 这个 anchor对应的预测框只需要输出它相比于它所在的 anchor的偏移量就行了。
我们上面有讲到 YOLOv2最后输出的网格大小是13 × 13 13\times13 13 ×13,这个网格的长宽都是奇数,是为了便于预测物体的只有一个中心的 grid,如果是偶数的话就会有好几个。
通过上面的介绍可以知道 YOLOv2模型输出的结构也改了,如下图所示,在 YOLOv1里面没有用 anchor,而是直接划分成7 × 7 7\times7 7 ×7个 grid,每个 grid输出两个 bounding box,每个 bounding box有两个未知参数和一个置信度,以及每个 grid还预测出了 20个类别的条件类别概率。在 YOLOv2里面模型就变得稍微复杂一些, YOLOv1里面的类别是由 grid负责,在 YOLOv2里面类别变成由 anchor负责了,每个 grid产生 5anchor,每个 anchor除了产生 4个定位参数和一个置信度参数之外还有 20个类别的条件类别概率,所以在 YOLOv2里面每个 anchor都会产生 25个数,总共输出5 × 25 = 125 5\times25=125 5 ×25 =125个数。即 YOLOv2总共输出13 × 13 × 125 = 21125 13\times13\times125=21125 13 ×13 ×125 =21125个数。最终的目标检测结果就是从这21125个数里面提取出来的。
YOLOv2目标检测算法——通俗易懂的解析
下图可视化了 YOLOv2anchor的产生过程。
YOLOv2目标检测算法——通俗易懂的解析
上面每个 grid将产生 5anchor,你有没有疑问,为什么一定是5个,我产生10个不行吗?当然可以,只不过没必要,太浪费,导致网络参数太多。作者通过聚类的方法对 PASCAL VOCCOCO数据集的长宽比进行了聚类操作,黑色框表示VOC数据集,紫色框表示COCO数据集。通过观察左图可以发现,聚类的长宽比种类越多,所覆盖的I o U IoU I o U也越大,但是模型也会变的更复杂,作者在此取了个折中,直接取值为5,兼顾了准确度效率。长宽度如下图的有图所示。通过聚类的方法确定 anchor数目。比双阶段的目标检测,如 Faster RCNN手动去选择 anchor要科学很多,聚类产生 anchor一直到 YOLOV5还在用,后面就开始使用 anchor free了。
YOLOv2目标检测算法——通俗易懂的解析

; 1.4.Fine-Grained Features(细粒度特征)

总结一句话就是长宽变为原来的一半,通道数变为原来的4倍。如下图的展示了一个可视化,就是网络中的Pass Throuth层。

YOLOv2目标检测算法——通俗易懂的解析

1.5.Multi-Scale Training

在模型训练期把不同的图像大小输入到模型,这个地方你还不会有疑问,输入图像大小变了,我的网络模型不用调整吗?作者肯定考虑了这个问题,他用了一个全局平均池化层,对每个通道求平均来替换全连接层。如下图所示,速度跟图像尺寸成反比,精度跟输入图像尺寸成正比。

YOLOv2目标检测算法——通俗易懂的解析
最后我们再来看张图,作者加了这些tricks到底有没有用。
YOLOv2目标检测算法——通俗易懂的解析
上面我们讲的都是针对 YOLOv2为什么会更好,下面我们再来介绍下 YOLOv2为什么会更快。作者换了骨干网络,我们知道 YOLOv1作者使用的是 VGG骨干网络,很臃肿,在 YOLOv2里面换成了作者自己设计 Darknet19
YOLOv2目标检测算法——通俗易懂的解析

; 二.损失函数

下面我们讲一下 YOLOv2的损失函数。

YOLOv2目标检测算法——通俗易懂的解析
YOLOv2论文里面并没有提到上面的损失函数,网上大神根据 YOLOv2的代码整理出来的。
首先,我们看下损失函数的最外层,总共有三次求和,分别是遍历所有的宽,高和 anchor的个数。然后是这个求和符号后面总共有三项,每项前面还有一个条件系数,这个系数非0即1。系数后面又有个λ \lambda λ,表示权重:
  1. 第一项(第一行)是预测框或者说 anchorground truth的I o U IoU I o U是否小于0.6,代码中给的阈值 Thresh为0.6,他们是被抛弃的框,并不负责预测物体,他们的置信度越为0越好,括号里面为什么会有个负号?他表示是( 0 − b i j k o ) 2 (0-b_{ijk}^o)^2 (0 −b ijk o ​)2,0就是那些被抛弃的框的标签,b i j k o b_{ijk}^o b ijk o ​表示预测框置信度。怎么计算I o U IoU I o U? 可以参考我的另一篇博文,I o U IoU I o U的进化之路。IoU、GIoU、DIoU、CIoU四种损失函数总结
  2. 第二项(第二行)是否是前12800次迭代,即是否是模型训练的早期。在模型训练的早期遍历四个定位参数,要让anchor的四个参数与预测框的四个参数尽可能的重合。就是让模型在训练的早期让五个 anchor能够各司其职,尽快找到自己负责的物体,让模型能够更加的稳定。
  3. 第三项(第三行及后面的)是这个 anchor负责检测物体,一个 grid产生5个 anchor,这个负责检测物体的 anchor就是5个 anchor里面与 ground truth最大的那个 anchor,也就是一个 ground truth只分配给一个 anchor。这个地方你会不会有疑问,负责预测物体的 grid的里面的不是与I o U IoU I o U最大但是又与 ground truth的I o U IoU I o U大于0.6的那些 anchor怎么处理。或者你也可以这样理解,总共三类 anchor,第一类是与 gouund truth的I o U IoU I o U最大的 anchor,用来负责预测物体,第二类是与 gouund truth的I o U IoU I o U小于0.6的,也就是损失函数第一项,第三类是与 gouund truth的I o U IoU I o U大于0.6但又不是与 ground truth的I o U IoU I o U最大的那些 anchor怎么处理?作者怎么处理的呢?他是直接把第三类的给抛弃了。对于负责预测物体的这个 anchor总共要计算三项,分别是定位误差、置信度误差、分类误差。定位误差就是计算 ground truth的位置和预测框的位置的误差。置信度误差就是计算 anchor与标注框 ground truth的I o U IoU I o U与预测框置信度得误差,这里 anchor与I o U IoU I o U的标签是置信度标签, YOLOv1也是这样设计的。而分类误差就是计算标注框类别和预测框类别的误差,并且遍历所有类别。

三.检测更多类别

损失函数我们讲过了,下面我们来继续接着讲作者是怎么加测更多类别的。
不是重点,简单了解即可,我们知道 COCO也不过就80个类别,作者是怎么做到能够检测出9000各类别的,是在夸大其词还是真的能够做到检测9000个类别?
YOLOv2作者是这样做的,他把 COCO数据集和 ImageNet数据集进行联合训练,我们知道 ImageNet数据集有两万多个类别,但是呢 ImageNet又没有定位标签,只有分类标签,并且 ImageNet的分类细粒度还很高,比如狗这个类别,他是什么狗,是阿拉斯加还是二哈,还是金毛,拉布拉多等。于是作者把他两个联合起来训练让模型能够学习到更多细粒度的特征。主要就是让目标检测数据集学定位,分类数据集学识别。这个地方简单了解即可,这里不做过多介绍。
至此,我们的YOLOv2模型理论部分也基本上介绍完了, YOLOv3的理论部分我们下篇文章再讲,在此,附一个 YOLO系列的文章链接:
YOLOv1目标检测算法——通俗易懂的解析
YOLOv3目标检测算法——通俗易懂的解析
YOLOv4目标检测算法——通俗易懂的解析
YOLOv5目标检测算法——通俗易懂的解析
欢迎各位大佬批评指正。

Original: https://blog.csdn.net/qq_38683460/article/details/126333243
Author: I松风水月
Title: YOLOv2目标检测算法——通俗易懂的解析

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/682253/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球