社区计算机视觉课程文档

YOLO

Hugging Face's logo
加入 Hugging Face 社区

并获得增强的文档体验

开始使用

YOLO

目标检测简短介绍

卷积神经网络在解决图像分类问题上迈出了巨大的一步。但仍有一个重要任务需要解决:目标检测。目标检测不仅需要从图像中对物体进行分类,还需要准确预测其在图像中的位置(在本例中,即物体边界框的坐标)。YOLO的重大突破正是在此。在深入YOLO之前,让我们先回顾一下使用CNN进行目标检测算法的历史。

RCNN, Fast RCNN, Faster RCNN

R-CNN (基于区域的卷积神经网络)

RCNN是使用卷积神经网络进行目标检测最简单可行的方法之一。简单来说,其基本思想是检测一个“区域”,然后使用CNN对该区域进行分类。这是一个多步过程。基于此思想,RCNN论文于2012年发表[1]

RCNN采用以下步骤:

  1. 使用选择性搜索算法选择区域。
  2. 使用基于CNN的分类器从区域中分类目标。

为了训练目的,论文提出了以下步骤:

  1. 从目标检测数据集中检测到的区域制作数据集。
  2. 在区域数据集上微调Alexnet模型。
  3. 然后将微调后的模型用于目标检测数据集。

以下是RCNN的基本流程图 rcnn

Fast RCNN

Fast RCNN致力于在原始RCNN的基础上进行改进。他们增加了以下四项改进:

  • 单阶段训练,而非像RCNN那样的多阶段训练。使用多任务损失。
  • 无需磁盘存储。
  • 引入ROI池化层,只从感兴趣区域获取特征。
  • 训练端到端模型,与多步骤RCNN/SPPnet模型不同,使用多任务损失。

fast_rcnn

Faster RCNN

Faster R-CNN完全消除了选择性搜索算法的需求!这些特性使得推理时间比Fast R-CNN提高了90%!

  • 它引入了RPN(区域提议网络)。RPN是一个基于注意力的模型,它训练模型“关注”图像中包含目标的区域。
  • 它将RPN与Fast RCNN合并,使其成为一个端到端的目标检测模型。

Faster RCNN

特征金字塔网络(FPN)

  • 特征金字塔网络是一种用于目标检测的Inception模型。
  • 它首先将图像下采样为低维嵌入。
  • 然后再次上采样。
  • 从每个上采样图像中,它试图预测输出(在本例中是类别)。
  • 但相似维度特征之间也存在跳跃连接!

请参考以下取自论文的图片。[20]

FPN FPN2

YOLO架构

YOLO是当时一项开创性的创新。它是一个实时目标检测器,可以端到端地通过单个网络进行训练。

YOLO之前

之前的检测系统包括在图像块上使用图像分类器。像可变形部件模型(DPM)这样的系统使用滑动窗口方法,分类器在整个图像上以均匀间隔的位置运行。

其他工作,如RCNN,使用两步检测。首先,它们通过区域提议网络生成边界框,检测许多可能的感兴趣区域。然后,分类器通过所有提议区域进行最终预测。还需要进行后处理,例如优化边界框,消除重复检测,以及根据场景中其他对象重新评分边界框。

这些复杂的流水线速度慢,难以优化,因为每个独立组件都必须单独训练。

YOLO

YOLO是一个单步检测器,边界框和对象类别在同一次通过中同时预测。这使得系统超快 - 每秒45帧的速度。

目标检测的重新定义

YOLO将目标检测任务重新定义为一个单一的回归问题,预测边界框坐标和类别概率。

在这个设计中,我们将图像划分为一个 $S \times S$ 的网格。如果对象的中心落入一个网格单元格中,那么该网格单元格负责检测该对象。我们可以定义 $B$ 为每个单元格中要检测的最大对象数量。因此,每个网格单元格预测 $B$ 个边界框,包括每个框的置信度得分。

置信度

边界框的置信度得分应反映框预测的准确性。它应该接近真实框与预测框的IOU(Intersection over Union)。如果网格不应该预测框,则应为零。因此,这应该编码框中心在网格中出现的概率以及边界框的正确性。

正式地,confidence:=P(Object)×IOUpredtruth\text{confidence} := P(\text{Object}) \times \text{IOU}_{\text{pred}}^{\text{truth}}

坐标

边界框的坐标编码为4个数字 $(x, y, w, h)$。 $(x, y)$ 坐标表示框相对于网格单元边界的中心。宽度和高度归一化到图像尺寸。

类别

类别概率是一个长为C的向量,表示给定单元格中存在对象时每个类别的条件类别概率。每个网格单元格只预测一个向量,即每个网格单元格将分配一个单一类别,因此该网格单元格预测的所有B个边界框都将具有相同的类别。

正式地,Ci=P(classiObject)C_i = P(\text{class}_i \mid \text{Object})

在测试时,我们将条件类别概率和单个框置信度预测相乘,从而为每个框提供特定于类别的置信度得分。这些得分既编码了该类别出现在框中的概率,也编码了预测框与对象的匹配程度。Ci×confidence=P(classiObject)×P(Object)×IOUpredtruth=P(classi)×IOUpredtruth\begin{align} C_i \times \text{confidence} &= P(\text{class}_i \mid \text{Object}) \times P(\text{Object}) \times \text{IOU}_{\text{pred}}^{\text{truth}}\\ &=P(\text{class}_i) \times \text{IOU}_{\text{pred}}^{\text{truth}} \end{align}

总结一下,我们有一个图像,被划分为 $S \times S$ 的网格。每个网格单元包含 $B$ 个边界框,由5个值组成——置信度+4个坐标,以及一个长为 $C$ 的向量,包含每个类别的条件概率。因此,每个网格单元是一个长为 $B \times 5 + C$ 的向量。整个网格是 $S \times S \times (B \times 5 + C)$。

因此,如果我们有一个可学习的系统,能将图像转换为 $S \times S \times (B \times 5 + C)$ 特征图,我们就离任务更近一步了。

网络架构

在原始YOLOv1设计中,输入是一个大小为 $448 \times 448$ 的RGB图像。图像被划分为 $S \times S = 7 \times 7$ 的网格,其中每个网格单元负责检测 $B=2$ 个边界框和 $C=20$ 个类别。

网络架构是一个简单的卷积神经网络。输入图像通过一系列卷积层,然后是一个全连接层。最终层输出被重塑为 $7 \times 7 \times (2 \times 5 + 20) = 7 \times 7 \times 30$。

YOLOv1的设计从GoogLeNet中汲取灵感,GoogLeNet使用1x1卷积来减少特征图的深度。这样做是为了减少网络中的参数数量和计算量。该网络有24个卷积层,然后是2个全连接层。它对最后一层使用线性激活函数,所有其他层使用Leaky ReLU激活函数。LeakyReLU(x)={xif x>00.1xotherwise\text{LeakyReLU}(x) = \begin{cases} x & \text{if } x > 0\\ 0.1x & \text{otherwise} \end{cases}

YOLOv1的架构见下图。

v1_arch

训练

网络是端到端地在图像和真实边界框上训练的。损失函数是平方误差损失之和。损失函数旨在惩罚网络对边界框坐标、置信度和类别概率的错误预测。我们将在下一节讨论损失函数。

YOLO为每个网格单元预测多个边界框。在训练时,我们只希望一个边界框预测器负责每个对象。我们根据哪个预测与真实值具有最高的当前IOU来指定一个预测器“负责”预测一个对象。这导致了边界框预测器之间的专业化。每个预测器在预测特定大小、长宽比或类别的对象方面表现更好,从而提高了整体召回率。我们将在损失函数中编码此信息,对于网格单元 $i$ 和边界框 $b$,使用 $\mathbb{1}{ib}^{\text{obj}}$。 $\mathbb{1}{ib}^{\text{noobj}}$ 与 $\mathbb{1}_{ib}^{\text{obj}}$ 相反。

损失函数

既然我们有一个可学习的系统,可以将图像转换为 $S \times S \times (B\times5 + C)$ 的特征图,我们就需要对其进行训练。

训练这样一个系统的简单方法是使用平方误差损失之和。我们可以使用预测值和真实值之间的平方误差,即用于边界框坐标、置信度和类别概率。

每个网格单元 $(i)$ 的损失可以如下所示:Li=Lcoordi+Lconfi+Lclassi \mathcal{L}^{i} = \mathcal{L}^{i}_{\text{coord}} + \mathcal{L}^{i}_{\text{conf}} + \mathcal{L}^{i}_{\text{class}}\\ Lcoordi=b=0B1ibobj[(x^ibxib)2+(y^ibyib)2+(w^ibwib)2+(h^ibhib)2]Lconfi=b=0B(conf^iconfi)2Lclassi=1iobjc=0C(P^iPi)2\begin{align*} \mathcal{L}^{i}_{\text{coord}} &= \sum_{b=0}^{B} \mathbb{1}_{ib}^{\text{obj}} \left[ \left( \hat{x}_{ib} - x_{ib} \right)^2 + \left( \hat{y}_{ib} - y_{ib} \right)^2 + \left( \hat{w}_{ib} - w_{ib} \right)^2 + \left( \hat{h}_{ib} - h_{ib} \right)^2 \right]\\ \mathcal{L}^{i}_{\text{conf}} &= \sum_{b=0}^{B} (\hat{\text{conf}}_{i} - \text{conf}_{i})^2\\ \mathcal{L}^{i}_{\text{class}} &= \mathbb{1}_i^\text{obj}\sum_{c=0}^{C} (\hat{P}_{i} - P_{i})^2 \end{align*}

其中

  • 如果第 $i$ 个网格单元格中的第 $b$ 个边界框负责检测目标,则 $\mathbb{1}_{ib}^{\text{obj}}$ 为 1,否则为 0。
  • 如果第 $i$ 个网格单元格包含一个对象,则 $\mathbb{1}_i^\text{obj}$ 为 1,否则为 0。

但这个损失函数不一定与目标检测任务很好地对齐。两个任务(分类和定位)的损失简单相加,使得损失权重相等。

为了纠正这个问题,YOLOv1使用加权平方误差损失之和。首先,我们为定位误差分配一个单独的权重,称为 $\lambda_{\text{coord}}$。它通常设置为5。

因此,每个网格单元 $(i)$ 的损失可以如下所示:Li=λcoordLcoordi+Lconfi+Lclassi \mathcal{L}^{i} = \lambda_{\text{coord}} \mathcal{L}^{i}_{\text{coord}} + \mathcal{L}^{i}_{\text{conf}} + \mathcal{L}^{i}_{\text{class}}\\

此外,许多网格单元不包含对象。置信度接近于零,因此包含对象的网格单元通常会压倒梯度。这使得网络在训练期间不稳定。

为了纠正这个问题,我们还将不包含对象的网格单元中的置信度预测损失的权重设置为低于包含对象的网格单元。我们为置信度损失使用一个单独的权重,称为 $\lambda_{\text{noobj}}$,通常设置为 0.5。

因此,每个网格单元 $(i)$ 的置信度损失可以如下所示:Lconfi=b=0B[1ibobj(conf^iconfi)2+λnoobj1ibnoobj(conf^iconfi)2] \mathcal{L}^{i}_{\text{conf}} = \sum_{b=0}^{B} \left[ \mathbb{1}_{ib}^{\text{obj}} \left( \hat{\text{conf}}_{i} - \text{conf}_{i} \right)^2 + \lambda_{\text{noobj}} \mathbb{1}_{ib}^{\text{noobj}} \left( \hat{\text{conf}}_{i} - \text{conf}_{i} \right)^2 \right]

边界框坐标的平方误差和可能存在问题。它对大框和小框中的误差权重相同。大框中的小偏差不应像小框中的小偏差那样受到严厉惩罚。

为了修正,YOLOv1 对边界框宽度和高度的**平方根**使用平方误差损失。这使得损失函数具有尺度不变性。

因此,每个网格单元 (i) 的定位损失可以表示为:Lcoordi=b=0B1ibobj[(x^ibxib)2+(y^ibyib)2+(w^ibwib)2+(h^ibhib)2] \mathcal{L}^{i}_{\text{coord}} = \sum_{b=0}^{B} \mathbb{1}_{ib}^{\text{obj}} \left[ \left( \hat{x}_{ib} - x_{ib} \right)^2 + \left( \hat{y}_{ib} - y_{ib} \right)^2 + \left( \sqrt{\hat{w}_{ib}} - \sqrt{w_{ib}} \right)^2 + \left( \sqrt{\hat{h}_{ib}} - \sqrt{h_{ib}} \right)^2 \right]

推理

推理很简单。我们把图像通过网络,得到 $S \times S \times (B \times 5 + C)$ 的特征图。然后我们过滤掉置信度分数低于阈值的边界框。

非极大值抑制

在极少数情况下,对于大型物体,网络会从多个网格单元预测多个边界框。为了消除重复检测,我们使用一种称为非极大值抑制(NMS)的技术。NMS 的工作原理是选择置信度分数最高的边界框,并消除所有 IoU 大于某个阈值的其他边界框。这个过程是迭代进行的,直到没有重叠的边界框为止。

端到端流程如下所示:nms

YOLO 的演变

到目前为止,我们已经看到了 YOLO 的基本特性,以及它如何实现高精度和快速预测。这实际上是 YOLO 的第一个版本,称为 YOLOv1。YOLOv1 于 2015 年发布,自那以后,已经发布了多个版本。它在精度和速度方面都具有开创性,因为它引入了使用单个卷积神经网络 (CNN) 一次性处理整个图像,并将其划分为 S × S 网格的概念。每个网格单元直接预测边界框和类别概率。然而,它在小图像区域的定位和多目标检测方面表现不佳。在接下来的几年里,不同的团队发布了许多新版本,以逐步提高精度、速度和鲁棒性。

YOLOv2 (2016)

在第一个版本发布一年后,YOLOv2[5]问世了。改进的重点在于精度和速度,同时也解决了定位问题。首先,YOLOv2 用 Darknet-19 替代了 YOLOv1 的骨干网络架构,Darknet-19 是 Darknet 架构的一个变体。Darknet-19 比之前版本的骨干网络更轻量,它由 19 个卷积层和随后的最大池化层组成。这使得 YOLOv2 能够捕获更多信息。此外,它对所有卷积层应用了批量归一化,从而移除了 Dropout 层,解决了过拟合问题并提高了 mAP。它还引入了锚框(anchor boxes)的概念,为检测到的边界框的宽度和高度添加了先验知识(具体来说,它们使用了锚框)。此外,为了解决定位不佳的问题,YOLOv2 为每个锚框和网格单元(现在是 13x13)预测类别和物体。因此,我们最多有 13x13x5 = 845 个边界框(对于 5 个锚框)。

YOLOv3 (2018)

YOLOv3[6]通过用更复杂但高效的 Darknet-53 替换 Darknet-19 架构,再次显著提高了检测速度和准确性。此外,它通过使用三种不同尺度的对象检测(13x13、26x26 和 52x52 网格)更好地解决了定位问题。这有助于在同一区域找到不同大小的对象。它将边界框数量增加到:13 x 13 x 3 + 26 x 26 x 3 + 52 x 52 x 3 = 10,647。非极大值抑制(NMS)仍然用于过滤掉冗余的重叠框。

YOLOv4 (2020)

早在 2020 年,YOLOv4[7] 就成为了速度和精度方面最好的检测模型之一,在目标检测基准上取得了最先进的成果。作者再次改变了骨干网络架构,选择了更快更准确的 CSPDarknet53[8]。该版本的一个重要改进是优化了资源利用效率,使其适用于在各种硬件平台(包括边缘设备)上部署。此外,它在训练前还包含了一些增强功能,进一步提高了模型的泛化能力。作者将这些改进归纳为一套称为“免费赠品包”(bag-of-freebies)的方法。免费赠品包是指在训练过程中会产生开销,但旨在提高模型在实时检测中的准确性而不增加推理时间的优化方法。

YOLOv5 (2020)

YOLOv5[9] 将 Darknet 框架(用 C 语言编写)转换为更灵活易用的 PyTorch 框架。此版本自动化了之前的锚点检测机制,引入了自动锚点(auto-anchors)。自动锚点会自动训练模型锚点以匹配您的数据。在训练期间,YOLO 会自动首先使用 k-means,然后使用遗传算法来演化出新的、更好匹配的锚点,并将其放回 YOLO 模型中。此外,它还提供不同类型的模型,这些模型取决于硬件限制,其名称类似于今天的 YOLOv8 模型:YOLOv5s、YOLOv5m、YOLOv5l 和 YOLOv5x。

YOLOv6 (2022)

下一个版本 YOLOv6[10][11] 由美团视觉 AI 部门发布,文章标题为:“YOLOv6: A Single-Stage Object Detection Framework for Industry”(YOLOv6:一个面向工业的单阶段目标检测框架)。该团队通过关注五个方面,在速度和准确性方面取得了进一步的改进:1) 使用 RepVGG 技术进行重参数化,RepVGG 是带有跳跃连接的 VGG 的修改版本。在推理过程中,这些连接被融合以提高速度。2) 基于重参数化的检测器的量化。这增加了名为 Rep-PAN 的模块。3) 认识到考虑不同硬件成本和模型部署能力的重要性。具体来说,作者测试了低功耗 GPU(如 Tesla T4)与之前大多使用高成本机器(如 V100)相比的延迟。4) 引入了新的损失函数类型,如用于分类的 Varifocal Loss、用于边界框回归的 IoU Series Loss 和 Distribution Focal Loss。5) 使用知识蒸馏在训练期间提高准确性。2023 年,YOLOv6 v3[12] 发布,标题为“YOLOv6 v3.0: A Full-Scale Reload”,该版本对网络架构和训练方案进行了增强,与之前发布的版本相比,再次提高了速度和准确性(在 COCO 数据集上评估)。

YOLOv7 (2022)

YOLOv7 随论文《YOLOv7:可训练的免费赠品集实时目标检测器的新 SOTA》[13][14] 发布,该论文由 YOLOv4 的作者撰写。具体来说,此版本的“免费赠品包”包括一种新的标签分配方法,称为从粗到精的引导式标签分配(coarse-to-fine lead-guided label assignment),并使用梯度流传播路径来分析如何将重参数化卷积与不同的网络结合起来。他们还提出了针对实时目标检测的“扩展”(extend)和“复合缩放”(compound scaling)方法,可以有效利用参数和计算。所有这些改进再次将实时目标检测推向了新的最先进水平,超越了之前的版本。

YOLOv8 (2023)

YOLOv8[15] 由 Ultralytics 于 2023 年开发,再次成为了新的 SOTA。它在骨干网络和颈部结构上进行了改进,并采用了无锚点方法,消除了对预定义锚框的需求。取而代之的是直接进行预测。此版本支持广泛的视觉任务,包括分类、分割和姿态估计。此外,YOLOv8 具有可伸缩性,提供各种尺寸的预训练模型:nano、small、medium、large 和 extra-large,并且可以轻松地在自定义数据集上进行微调。

YOLOv9 (2024)

YOLOv9 随论文《YOLOv9:使用可编程梯度信息学习您想学习的内容》[16][17] 发布,该论文由 YOLOv7 和 YOLOv4 的同一批作者撰写。这篇论文强调了现有方法和架构在逐层特征提取和空间变换过程中存在信息丢失的问题。为了解决这个问题,作者提出了:

  • 可编程梯度信息(PGI)的概念,以应对深度网络实现多目标所需的各种变化。
  • 广义高效层聚合网络(GELAN),一种新的轻量级网络架构,在不牺牲计算效率的情况下,实现了比现有方法更好的参数利用率。

通过这些改变,YOLOv9 在 MS COCO 挑战赛中创造了新的基准。

考虑到时间线和模型的不同许可,我们可以创建下图:yolo_evolution

关于不同版本的说明

本简短章节以线性的方式介绍了 YOLO 的历史/演变。然而,实际情况并非如此——许多其他版本的 YOLO 是并行发布的。请注意 YOLOv4 和 YOLOv5 在同一年发布。我们未涵盖的其他版本包括 YOLOvX (2021),它基于 YOLOv3 (2018),以及 YOLOR (2021),它基于 YOLOv4 (2020),等等。此外,重要的是要理解,选择“最佳”模型版本取决于用户需求,例如速度、准确性、硬件限制和用户友好性。例如,YOLOv2 在速度方面表现出色。YOLOv3 在准确性和速度之间取得了平衡。YOLOv4 具有在不同硬件上适应或兼容的最佳能力。

参考

[1][用于精确目标检测和语义分割的丰富特征层次结构](https://arxiv.org/abs/1311.2524v5)
[2][快速 R-CNN](https://arxiv.org/abs/1504.08083)
[3][更快 R-CNN](https://arxiv.org/pdf/1506.01497.pdf)
[4][特征金字塔网络](https://arxiv.org/pdf/1612.03144.pdf)
[5][YOLO9000: 更好、更快、更强](https://arxiv.org/abs/1612.08242)
[6][YOLOv3: 增量改进](https://arxiv.org/abs/1804.02767)
[7][YOLOv4: 目标检测的最佳速度和精度](https://arxiv.org/abs/2004.10934)
[8][YOLOv4 GitHub 仓库](https://github.com/AlexeyAB/darknet)
[9][Ultralytics YOLOv5](https://docs.ultralytics.com/models/yolov5/)
[10][YOLOv6: 用于工业应用的单阶段目标检测框架](https://arxiv.org/abs/2209.02976)
[11][YOLOv6 GitHub 仓库](https://github.com/meituan/YOLOv6)
[12][YOLOv6 v3.0: 全面重载](https://arxiv.org/abs/2301.05586)
[13][YOLOv7: 可训练的免费赠品集实时目标检测器的新 SOTA](https://arxiv.org/abs/2207.02696)
[14][YOLOv7 GitHub 仓库](https://github.com/WongKinYiu/yolov7)
[15][Ultralytics YOLOv8](https://github.com/ultralytics/ultralytics)
[16][YOLOv9: 使用可编程梯度信息学习你想要学习的东西](https://arxiv.org/abs/2402.13616)
[17][YOLOv9 GitHub 仓库](https://github.com/WongKinYiu/yolov9)
[18][YOLOvX](https://yolovx.com/)
[19][你只学习一种表示:用于多任务的统一网络](https://arxiv.org/abs/2105.04206) [20][特征金字塔网络论文](https://arxiv.org/abs/1612.03144)

< > 在 GitHub 上更新