第一部分:核心思想
YOLO 的全称是 You Only Look Once(你只需看一次)。这个名字完美地概括了它的核心思想。
在 YOLO 出现之前,主流的目标检测算法(如 R-CNN 系列)都遵循一个“两步走”策略:
-
区域提名 (Region Proposal):先在图片上找出成百上千个可能包含物体的候选区域。
-
分类与回归 (Classification & Regression):再对每一个候选区域,用一个分类器判断它是什么物体,并微调这个区域的边界。
这个过程就像你在找钥匙,先把所有看起来像钥匙的东西(银色的、金属的)都圈出来,然后再一个个仔细看,确认哪个才是真的钥匙。这样做虽然准,但速度很慢。
YOLO 则开创了单次检测的先河。它将目标检测视为一个单一的回归问题 (Regression Problem)。
YOLO 不像是在照片上找细节,而像是人眼看一张图片,“扫视一眼”,就能同时知道图里有什么东西、它们在哪里。这就是 “You Only Look Once”。
YOLO的处理图:

第二部分:核心机制 —— “深”入原理
现在我们来看看 YOLO 是如何实现“看一眼”就知道结果的。这里的数据流动是理解的关键。
步骤 1:网格划分 (Grid Division)
YOLO 的第一步,也是最核心的一步,就是将输入的图像划分成一个 S x S 的网格(Grid)。比如,一个 13 x 13 的网格。
数据流:一张 416 x 416 像素的图片输入网络,网络最终会输出一个对应 13 x 13 网格的特征图。这个特征图上的每一个点,都包含了其对应原始图像区域的信息。
如果一个物体的中心点落在了某个网格单元(Grid Cell)内,那么这个网格单元就负责预测这个物体。
步骤 2:每个网格单元的预测 (Prediction per Grid Cell)
每个网格单元都需要预测两样东西:
1.边界框 (Bounding Boxes)
2.类别概率 (Class Probabilities)
这最终会形成一个巨大的张量(Tensor)作为输出。让我们来分解这个张量。
假设我们将图片划分为 S x S 个网格,每个网格要预测 B 个边界框,并且我们要检测的物体总共有 C 个类别。
那么,每个网格单元需要预测的数据就是一个长度为 B * 5 + C 的向量。
为什么是 B * 5 + C?
因为对于 B 个边界框中的每一个,都需要 5 个值来描述:
x, y:边界框的中心点坐标。这个坐标是相对于其所在的网格单元的,值在 0 到 1 之间。
w, h:边界框的宽度和高度。这个值是相对于整张图片的,值在 0 到 1 之间。
置信度 (Confidence Score):这个值非常关键,它代表了这个边界框的“可信度”。它的计算公式是:
Confidence = P(Object) * IOU
P(Object) :是指“这个边界框内包含一个物体的概率”。
IOU (Intersection over Union) :是指“预测框与真实物体框的交并比”,大白话就是预测框和真实框的重合度,它衡量了预测框定位的准确性。
所以,这个公式的白话文解释就是: 一个边界框的可信度 = (它内部有物体的概率) × (它圈定物体位置的准确度)
一个高置信度的框,意味着它既很可能包含一个物体,也把这个物体的位置圈得很准。
对于 C 个类别:
这是一个长度为 C 的向量,例如 [P(class_1|Object), P(class_2|Object), ...]。它表示在“确认有物体”的前提下,这个物体属于各个类别的条件概率。
最终输出:整个网络的最终输出就是一个维度为 S x S x (B * 5 + C) 的张量。
第三部分:实例教学
我们的任务是让电脑看一张包含一只猫的图片,并用方框把猫圈出来,同时告诉我们“这是一只猫”。
第一步:网格划分
我们拿到一张图片,比如是 416x416 像素。如果让电脑一次性分析整张图(416*416 = 173,056个像素),任务十分庞大,非常耗时耗力。
所以,我们采用一种“分而治之”的策略。
1.做法: 我们在图片上画上格子,把它分成一个 13x13 的网格。
2.规则: 现在,我们看图片里那只猫的中心点(比如是它的鼻子)落在了哪个格子里。假设它落在了第7行第7列的那个格子,我们就把这个格子标记为格子(7,7)。
格子(7,7) 从现在起,全权负责检测“这只猫”。其他的格子,即便能看到猫的尾巴或者耳朵,它们也不是主要负责检测猫咪。
第二步:每个格子的预测
现在,我们聚焦到 格子(7,7) 身上。它需要提交一份详细的“向量”。这份向量就是一长串数字,包含了它对自己负责区域的分析结果。
这个向量需要回答两个问题:
-
“我这里有没有东西?如果在,它在哪?有多大?” —— 这通过 边界框 (Bounding Box) 来回答。
-
“如果我这里有东西,它最可能是什么?” —— 这通过 类别概率 (Class Probabilities) 来回答。
为了防止格子看走眼,我们不让格子(7,7)只给一个答案,而是让它给出多个(比如 3 个)候选答案,我们称之为锚框 (Anchor Boxes)。你可以理解为,它有3次机会去
格子输出向量详解:
格子(7,7) 需要输出一串很长的数字。我们来拆解这串数字的含义。
1. 关于边界框 (3个候选框,每个框5个数字):
候选框 1 (最靠谱的那个):
x, y:猫的中心点,在我这个格子的 (0.4, 0.5) 的位置。
这是什么意思? 这不是整张图的坐标,而是相对于 格子(7,7) 本身的。(0,0)是格子的左上角,(1,1)是右下角。这个相对坐标让模型学习起来更容易。
w, h:这个猫的框,宽度是整张图的 0.3 倍,高度是整张图的 0.4 倍,注意! 宽高是相对于整张大图的。这样才能知道物体到底有多大。
置信度 (Confidence):它会给出一个分数,比如 0.98 (98%)。这个分数代表:非常确定这个框里有东西
候选框 2 (不太靠谱的):可能也尝试圈了一下猫,但圈得比较偏,或者大小不合适。所以它的置信度可能只有 0.30 (30%)。
候选框 3 (基本是瞎猜的):可能圈到了旁边的草地,所以它的置信度极低,比如 0.05 (5%)。
2. 关于类别概率 (1份对所有类别的评估):
在给出边界框之后,格子(7,7) 还要提交一份对物体类别的评估报告。假设我们的模型能识别80种物体(猫、狗、车、人...)。
-
这份报告就是一个80维的列表,内容类似:
-
P(是人 | 有物体) = 0.01 -
P(是狗 | 有物体) = 0.03 -
P(是猫 | 有物体) = 0.95 -
P(是车 | 有物体) = 0.00 -
...等等
-
-
意思是:“首先确定这儿有东西(由高置信度的边界框保证),然后判断,这个东西有 95% 的可能性是猫。”
第三步:解码与筛选
到现在为止,我们13x13=169个区域,每个都提交了类似上面的报告。我们拿到了一大堆(169个格子 * 3个候选框/格子 = 507个)潜在的物体框。
这里面绝大多数都是置信度极低的垃圾信息(比如那些负责天空、草地的格子提交的报告)。我们需要一个严格的审查流程来去伪存真。
审查流程:
第1轮:计算最终得分,初步筛选
我们要把“框的质量”和“类别判断”结合起来,得到一个最终可信度。
计算公式(白话版):
一个框是“猫”的最终得分 = 这个框本身的置信度 × 框内物体是“猫”的概率
举例:
对于格子(7,7)的候选框1: 最终得分 = 0.98 (框的置信度) × 0.95 (是猫的概率) = 0.931 这是一个非常高的分数!
对于格子(7,7)的候选框2: 最终得分 = 0.30 (框的置信度) × 0.95 (是猫的概率) = 0.285 这个分数就不太行了。
我们设定一个门槛,比如0.5。所有最终得分低于0.5的框,我们认为它们是“胡说八道”,直接扔进垃圾桶。经过这一轮,507个候选框可能只剩下不到10个了。
第2轮:处理重复,非极大值抑制 NMS
现在我们手上可能还有几个分数比较高的框,但它们可能都指向了同一只猫。比如格子(7,6)可能也看到了猫的一部分,也提交了一个分数还不错的报告。
我们不希望最终结果在一只猫身上画三四个框。我们只需要最好的那一个。
NMS 的工作流程:
1.把所有通过第一轮筛选的框,按照最终得分从高到低排序。选出得分最高的那个框(比如我们0.931分的那个)。
2.然后,检查列表里剩下的其他框。任何一个框,如果和我们刚选出的最佳框重叠度非常高(比如IOU > 0.6),就说明它只是在重复描述同一个物体。我们把它抛弃掉。
3.处理完一轮后,再从剩下还没被处理的框里,选出得分最高的,重复上面的过程。
最终结果: 经过 NMS 的“末位淘汰”后,对于“猫”这个物体,理论上只会留下一个得分最高、位置最准的边界框。
第四部分:YOLO 的进化
YOLO 并没有停滞不前,它经历了很多代的发展,每一代都针对前代的弱点进行了关键改进。
YOLOv1 (2016)
奠基者:提出了上述的核心思想,即网格划分和端到端回归。
弱点:对小物体不友好,定位不准。
YOLOv2 / YOLO9000 (2017)
关键改进:引入锚框 (Anchor Boxes)
思想:不再让网络直接预测框的宽高,而是预测相对于预设“锚框”的偏移量。锚框是一些预设好、具有代表性的宽高比的框。
好处:这降低了网络学习的难度。网络只需微调,而不需要从零开始学习,从而大幅提升了定位的准确率和召回率。
其他改进:使用了更高分辨率的分类器、批归一化 (Batch Normalization) 等。
YOLOv3 (2018) - 一个里程碑
关键改进 1:多尺度预测
为了解决小物体检测难题,YOLOv3 不再只用一个 13x13 的网格,而是在 3 个不同尺度的特征图上进行预测(例如 13x13, 26x26, 52x52)。
数据流:13x13 的粗糙网格负责检测大物体。
26x26 的中等网格负责检测中等物体。
52x52 的精细网格负责检测小物体。
这极大地提升了对不同尺寸物体的检测能力。
关键改进 2:更好的主干网络 (Darknet-53)
引入了残差连接 (Residual Connections),让网络可以变得更深,特征提取能力更强。
YOLOv4, v5, 以及后续版本 (v6, v7, v8, v9, YOLO-World...)
这一时期的 YOLO 发展进入“集大成”阶段,引入了当时学术界各种先进的技术,可以归纳为两个
1.Bag of Freebies (免费包):指那些在不增加推理时间的前提下提升性能的技巧。主要用在训练阶段。例如:更复杂的数据增强 (Mosaic, MixUp)、更优的损失函数 (CIoU Loss) 等。
2.Bag of Specials (特价包):指那些会少量增加推理时间但能显著提升性能的模块。例如:注意力机制 (SE, CBAM)、路径聚合网络 (PANet)、新的激活函数 (Mish) 等。
近期的趋势:
无锚框 (Anchor-Free):一些新版本开始抛弃预设的锚框,让网络直接学习物体的中心点和宽高,进一步简化了模型。
解耦头 (Decoupled Head):将分类任务和定位任务的预测头分开,认为这两个任务有不同的侧重点,分开处理效果更好。
框架化和易用性:以 YOLOv5 和 YOLOv8 的开发者 Ultralytics 为代表,将算法封装得非常易用,几行代码就能完成训练和推理。
第五部分:关键技术细节和架构设计。
这部分我们将聚焦于现代YOLO(如YOLOv4/v5及以后版本)的内部构造,因为它们才是当今应用的主流。
我们将从三个层面深入:
宏观架构: 现代YOLO的三大核心组件是什么?
关键模块: 每个组件里最核心的设计思想是什么?
学习核心: 损失函数改进
一、 宏观架构:现代YOLO的三大件
我们可以将一个现代的YOLO网络拆开来看,它由三段组成:
输入图像 -> [Backbone (骨干网络)] -> [Neck (颈部)] -> [Head (头部)] -> 输出结果
1.Backbone (骨干网络): 这是整个网络的第一段。它的唯一任务就是对输入的图像进行“粗加工”,提取出各种层次的图像特征。就像我们的视觉神经,从最开始的边缘、颜色、纹理,到更深层次的轮廓和部件。
输入: 原始图片 (例如 640x640x3)
输出: 多个不同尺寸的“特征图 (Feature Map)”。例如,它可能会输出一个 80x80 (低阶、细节多)、一个 40x40 (中阶)、和一个 20x20 (高阶、语义信息强) 的特征图。
2.Neck (颈部): 这是最关键的第二段,也是现代YOLO相比早期版本最大的进化之一。它的任务是对Backbone产出的特征进行加工和融合。
为什么需要它 :Backbone输出的高阶特征图(如20x20)虽然知道“这里有个东西像猫”,但由于尺寸太小,位置信息已经很模糊了。而低阶特征图(如80x80)虽然保留了丰富的细节和位置信息,但“不知道自己看的是什么”。Neck的作用就是将这两者完美地结合起来。
输入: 来自Backbone的多个特征图。
输出: 经过充分融合的、同样是多个尺寸的特征图。这些新的特征图,既有丰富的语义信息,又有精准的位置信息。
3.Head (头部): 它利用Neck送来的融合后的特征图,进行最终的预测。
输入: 来自Neck的融合特征图。
输出: 我们熟悉的边界框坐标、置信度和类别概率。这部分的工作就和我们上次讨论的解码、NMS流程紧密相连。
二、 关键模块深入解析
1. Backbone的核心:CSPNet (Cross Stage Partial Network)
现代YOLO的Backbone(如YOLOv5的CSPDarknet)普遍采用了一种名为 CSPNet 的思想。
要解决什么问题? 传统的深度网络,信息在传递中容易“失真”或“遗忘”(梯度消失),而且计算量大。
CSPNet怎么做? 它将进入一个处理阶段的特征图一分为二。一部分直接“走捷径”,几乎不做处理。另一部分则进入一系列复杂的处理模块(例如残差模块)。
最后,将这两部分重新拼接 (Concatenate) 在一起。
这样做的好处:保留原始信息: “走捷径”的那部分保证了最原始的特征信息不会丢失。
减少计算量: 只有一半的数据需要经过复杂计算,效率大大提升。
梯度更丰富: 避免了信息在深层网络中传递时的损耗,让网络学习得更好。
如果基础好的读者应该知道我说的就是加入残差结构。
2. Neck的核心:FPN + PANet
这是现代YOLO的精髓。Neck部分通常由两种结构组合而成:FPN 和 PANet。
FPN (Feature Pyramid Network): 自顶向下的特征融合
路径: 从Backbone最高阶、最抽象的特征图(20x20)开始。操作: 将其上采样(放大尺寸,如20x20 -> 40x40),然后与Backbone中原始的同尺寸特征图(40x40)进行融合。
目的: 这个过程,高阶特征在指导低阶特征,告诉他:“注意这个区域,这里很可能有个东西。” 它将高层级的语义信息传递给了低层级。
PANet (Path Aggregation Network): 自底向上的路径增强路径
在FPN完成之后,再反过来,从最低阶、融合后的特征图(80x80)开始。
操作: 将其下采样(缩小尺寸),再与更高阶的融合特征图进行二次融合。目的: 这次反向操作,是为了将低层级中精准的位置信息再补充回高层级。确认物体的精确边缘在这里。
总结: 通过 FPN (自顶向下) + PANet (自底向上) 这一来一回的“双向融合”,Neck最终产出的特征图,完美地做到了“鱼与熊掌兼得”——既知道是什么(语义),又知道在哪里(定位)。这对于检测不同大小的物体,尤其是小物体,至关重要。
三、 损失函数 (Loss Function)
我们知道模型通过“犯错”来学习,而“损失函数”就是用来量化的工具。总的损失 Total Loss 通常由三部分加权构成:
Total Loss = α * Loss_box + β * Loss_obj + γ * Loss_cls
1.定位损失 (Loss_box): 如何惩罚“框画歪了”
早期方法的问题: 早期直接计算 (x-x')² + (y-y')² ...,但这样无法反映框与真实物体之间的相对关系。
现代方法 (CIoU Loss): 现在普遍使用 CIoU (Complete-IoU) Loss。它不只考虑预测框和真实框的重叠面积 (IoU),还额外惩罚两件事:
1.中心点距离: 两个框的中心点离得远不远?
2.长宽比: 两个框的形状像不像?
为什么CIoU好:即使两个框完全不重叠(传统IoU为0,模型学不到东西),CIoU依然能告诉模型“你应该往哪个方向移动你的框,以及如何调整形状,才能变得更好”。它提供了更全面的优化方向。
2.置信度/目标损失 (Loss_obj): 如何惩罚“有无颠倒”
这个损失的目标是让模型学会区分哪里有物体,哪里是背景。它惩罚两种错误:
False Positive: 把背景当成物体。
False Negative: 没能检测到存在的物体。
假如,一张图中绝大部分区域都是背景,这会导致正负样本极不均衡。
现代YOLO会采用一些策略(如Focal Loss的思想)来让模型更关注那些难分类的、有物体的区域。
3.分类损失 (Loss_cls): 如何惩罚“预测错误”
这个损失只在格子里确实有物体时才计算。
如果真实物体是“猫”,而你预测成“狗”,分类损失就会很高。
通常使用 BCE (Binary Cross-Entropy) Loss,它能很好地处理多标签分类问题(比如一个物体同时是“女人”和“人”)。
正是这些“深入”的细节,让YOLO从一个“快但不太准”的开创者,演变成了今天这样在速度和精度上都达到顶尖水平的算法架构。
24万+

被折叠的 条评论
为什么被折叠?



