0%

YOLO 浅析

YOLO 是目标检测里被使用得最多的单阶段方法。它的价值不在于某个模块的精巧,而在于把检测从一条由候选框、分类器、回归器拼成的多阶段流水线,压缩成一次前向传播就能出结果的统一网络:图像进来,网格化的密集预测出去。从 2016 年到现在,家族内部的骨干网络、特征融合、标签分配、损失函数与后处理几乎被逐项换过一轮,但单网络单次前向这个骨架没有变。本文将按自顶向下的顺序,从统一框架与评价指标出发,逐层讨论骨干、颈部、检测头与标签分配、损失函数、后处理,再给出范式对比、版本演进主线与工程落地要点。

前言

检测任务要回答两个问题:图里有什么,以及它们在哪里。前深度学习时代的做法是手工特征加滑动窗口,深度学习时代的第一代做法是把问题拆成两步,先由区域建议网络产生候选框,再对每个候选框做分类与回归。这种两阶段结构精度高,但每一步都要独立跑一遍卷积,推理速度与流程复杂度都很难压下来。

YOLO 换掉了这个结构。它把整张图切成网格,每个网格单元直接预测若干边界框及其类别概率,检测因而变成一个回归问题,一次前向就能拿到全图的预测结果。这个改变把速度提高了量级,代价也很明确:密集预测要在一张特征图上同时完成定位与分类,标签怎么分、正负样本怎么定、损失怎么配,全部变成了必须显式设计的环节,家族后续大部分版本的工作都是在替换这些环节里的手工假设。

本文的范围覆盖从任务定义到部署的完整链条。我们先把 YOLO 抽象成四个组件的组合,再逐个讨论每个组件的设计动机与数学形式,然后看这些组件在版本演进中如何被替换,最后讨论训练与部署的工程要点,以及它与多目标跟踪的衔接方式。文中公式保持推导链条完整,凡是涉及取舍的地方都给出原因。

一个常见的前向流程可以用下面的结构概括:

输入图像
→
骨干网络 Backbone
→
颈部 Neck 多尺度融合
→
检测头 Head 密集预测
→
解码与后处理

YOLO 的统一框架

我们更倾向把 YOLO 看成一个由四个组件构成的整体,而不是一系列版本的堆叠:

组件 承担职责 输出形态
骨干网络 从图像中提取多层级特征,逐级降低分辨率、提升通道数 若干尺度的特征图
颈部 把不同尺度的特征自顶向下与自下而上地融合,兼顾语义与细节 与检测头对齐的多尺度特征
检测头 在特征图的每个位置上预测框参数与类别分数 密集预测张量
分配与后处理 训练时决定哪些预测对哪个真值负责,推理时把冗余框收敛成结果 正负样本标签、最终检测框

这四个组件各自解决一个问题,缺一不可:去掉骨干就没有可用的特征表示,去掉颈部小目标与多尺度场景会明显退化,去掉检测头的密集预测就回到了两阶段结构,去掉分配与后处理则训练无法收敛、推理输出大量重复框。理解这套分工之后,版本之间的差异就可以精确定位到某个组件上。

一个统一的观察角度
YOLO 家族每一次重要迭代,几乎都是在替换一个手工假设:先用聚类得到的先验框替换人工设计的长宽比,再用解耦头替换共享参数的耦合头,再用动态标签分配替换固定 IoU 阈值,最后用一对一分支与一致性约束替换 NMS。判断某个版本改动的分量,可以看它消除的是哪一类人工先验。

前置知识:检测任务的评价与约束

在进入结构细节之前,先把评价指标与固有约束讲清楚,后面讨论取舍时都要回到它们。

检测的评价以交并比为基础。对预测框 BpB_p 与真值框 BgB_g,交并比定义为交集面积与并集面积之比:

IoU(Bp,Bg)=Area(Bp∩Bg)Area(Bp∪Bg)\text{IoU}(B_p, B_g) = \frac{\text{Area}\left(B_p \cap B_g\right)}{\text{Area}\left(B_p \cup B_g\right)}

它同时是判定预测是否正确的阈值判据,也是后面所有定位损失的起点。有了它就可以定义精确率与召回率:

Precision=TPTP+FP,Recall=TPTP+FN\text{Precision} = \frac{TP}{TP + FP}, \qquad \text{Recall} = \frac{TP}{TP + FN}

其中 TPTP、FPFP、FNFN 分别是真正例、假正例与假负例,判定依据就是预测框与真值框的 IoU 是否超过阈值。把置信度从高到低排序,逐点计算精确率与召回率,得到一条曲线,曲线下的面积就是平均精度:

AP=∫01p(r) dr\text{AP} = \int_{0}^{1} p(r)\, dr

对所有类别取平均得到 mAP\text{mAP},它是跨类别、跨置信度阈值的综合指标。理解这一点很关键:AP 是一个与排序相关的积分指标,因此置信度的校准质量、以及后处理对框排序的影响,都会直接体现在最终数值上。

除了指标,检测还有三条内在约束,它们共同决定了 YOLO 的形态:

  • 速度与精度的平衡:单阶段结构省掉了候选框阶段,速度优势明显,但密集预测要同时承担定位与分类,早期版本在这两项上都弱于两阶段方法。
  • 多尺度目标:同一张图里可能同时存在占几十个像素的小目标与跨越半张图的大目标,单一尺度的特征图无法兼顾,这是颈部存在的理由。
  • 密集预测的标签分配:一张特征图上有成千上万个预测位置,而真值只有几十个,哪些位置算正样本、哪些算负样本、正样本之间如何分工,直接决定训练信号的质量,这也是家族演进中改动最频繁的一环。

从两阶段到单阶段

两阶段的流水线结构

两阶段检测器的思路是显式地先找候选区域再精细判别:第一步用区域建议网络在特征图上产生若干候选框,第二步对每个候选框做一次池化并送入分类与回归分支。它的优势是把定位与分类解耦,每一步都可以单独优化,精度上限较高。代价是每个候选框都要独立跑一次头部计算,候选框数量通常在千级别,因此推理时间与候选框数量成正比,难以做到实时。

YOLO 的回归式建模

YOLO 的做法是把检测直接写成回归。设图像被划分为 S×SS \times S 个网格单元,每个单元负责预测落在其内部的物体,每个单元的预测向量包含若干边界框的坐标与置信度,以及该单元的类别分布:

y^ij=[ tx, ty, tw, th, pobj, c1, …, cC ]\hat{y}_{ij} = \left[\, t_x,\ t_y,\ t_w,\ t_h,\ p_{\text{obj}},\ c_1,\ \ldots,\ c_C \,\right]

其中 pobjp_{\text{obj}} 是目标置信度,ckc_k 是类别条件概率,坐标参数为相对网格单元的偏移量。整张网络的输出张量形状为

Y^∈RS×S×(B⋅5+C)\hat{Y} \in \mathbb{R}^{S \times S \times \left(B \cdot 5 + C\right)}

BB 是每个网格预测的框数量,CC 是类别数。推理时把坐标参数还原为绝对坐标,置信度与类别概率相乘得到每个框的类别分数,再做阈值过滤与去重,就得到最终结果。全过程只经过一次前向传播,这是 YOLO 速度优势的来源。

这种建模也带来两个内生的困难。第一,坐标回归是在每个单元格内部进行的,当多个物体的中心落在同一个单元格时,该单元格只能指派给其中一个,召回率受网格分辨率限制。第二,定位精度依赖回归,早期的直接回归在 IoU 上明显低于两阶段的精细回归。后续版本引入的先验框、多尺度预测、解耦头与更精细的定位损失,都是围绕这两个困难展开的。

直接回归的坐标形式

在引入先验框之后,坐标不再直接回归绝对位置,而是回归相对先验框的偏移量,这样回归目标被压缩到较小的数值范围,训练更稳定。设先验框的宽高为 pw,php_w, p_h,网格左上角坐标为 (cx,cy)(c_x, c_y),则解码公式为

bx=σ(tx)+cx,by=σ(ty)+cyb_x = \sigma(t_x) + c_x, \qquad b_y = \sigma(t_y) + c_y

bw=pw⋅etw,bh=ph⋅ethb_w = p_w \cdot e^{t_w}, \qquad b_h = p_h \cdot e^{t_h}

其中 σ(⋅)\sigma(\cdot) 是 Sigmoid 函数,把中心偏移限制在当前网格内部,避免预测中心跳到很远的网格导致训练不稳定;宽高用指数形式表达缩放倍数,保证预测值恒为正。这个编码形式是 anchor-based 时代的标准写法,理解它就能理解后来 anchor-free 方案在解码上的改动意图。

骨干网络

骨干网络的职责是把图像逐级转换成多层级的特征表示。YOLO 家族的骨干经历过几次明显的结构替换,主线是从直接堆叠卷积,走向带残差与跨阶段连接的复合结构,再走向更高效的多分支聚合。

残差连接

深层骨干首先要解决梯度传播问题。残差连接把子层的输出与输入相加:

xl+1=xl+F(xl)x_{l+1} = x_l + F(x_l)

它保证反向传播时存在一条系数为 1 的恒等通路,梯度不会在几十层堆叠下指数衰减。这一改动由 ResNet 引入,YOLOv3 的 Darknet-53 首次把它作为骨干的主体结构,此前 YOLOv1 与 YOLOv2 使用的还是纯卷积堆叠的 Darknet-19。

跨阶段部分连接

跨阶段部分连接(CSP)解决的是另一个问题:梯度信息在多个残差块之间反复回流,造成计算冗余。它的做法是把输入特征沿通道维度一分为二,一半直接短路,另一半经过多个残差块处理,最后把两路拼接:

x=[ x1, x2 ],y=[ x1, F(x2) ]x = \left[\, x_1,\ x_2 \,\right], \qquad y = \left[\, x_1,\ \mathcal{F}\left(x_2\right) \,\right]

其中 F\mathcal{F} 是若干残差块的复合,[⋅,⋅][\cdot,\cdot] 表示通道拼接。由于只有一半通道进入重复的残差计算,计算量下降,同时梯度沿两条路径传播,减弱了重复梯度带来的干扰。CSPDarknet 从 YOLOv4 开始成为主干,此后的 ELAN、C2f、C3k2 都是在这一思想上的效率改进:ELAN 用多分支的短路径与长路径组合提升特征复用效率,C2f 把分支聚合简化为更少的算子组合,C3k2 则允许对分支的卷积核大小做选择。

批归一化

批归一化在 YOLOv2 中被引入,是当时提升收敛速度与精度最直接的改动。它对一个批次内的通道维度做标准化,再施加可学习的缩放与平移:

x^=x−μBσB2+ϵ,y=γx^+β\hat{x} = \frac{x - \mu_{\mathcal{B}}}{\sqrt{\sigma_{\mathcal{B}}^2 + \epsilon}}, \qquad y = \gamma \hat{x} + \beta

其中 μB\mu_{\mathcal{B}} 与 σB2\sigma_{\mathcal{B}}^2 是批次统计量,γ\gamma 与 β\beta 是可学习参数。它的作用有两层:一是把每层输入的分布拉回稳定范围,允许更大的学习率;二是批次统计量引入的噪声起到轻微正则化作用,因此在卷积网络里常常可以替代 Dropout。需要注意的是它与 Transformer 中逐位置归一化的方向相反:批归一化统计的是跨样本的同一通道,因此对批次大小敏感,推理时需要固定统计量。

注意力模块

较新的版本开始在主干的末端或颈部引入注意力,用来扩大感受野并增强通道间的选择性。基础形式是标准的缩放点积注意力:

Attention(Q,K,V)=Softmax(QK⊤dk)V\text{Attention}(Q, K, V) = \text{Softmax}\left(\frac{QK^\top}{\sqrt{d_k}}\right) V

把它直接用在检测骨干上有成本问题:高分辨率特征图上的全局注意力代价随空间位置数量的平方增长,对实时检测器不可接受。因此实践中的做法是限制注意力的作用范围,例如把特征图划分成若干区域,在区域内做注意力,或者在通道维度做全局池化后再做注意力,把复杂度从 O(n2)\mathcal{O}(n^2) 降到与区域数量相关的量级。这类模块通常只放在骨干的末端与颈部的高层特征上,因为那里的分辨率已经降低,代价可控。

四代骨干的主要结构差别可以对照下表理解:

骨干结构演进
阶段 代表结构 关键改动
纯卷积Darknet-193×3 与 1×1 交替,配合全局平均池化
残差堆叠Darknet-53引入残差连接,浅层细节与深层语义分层输出
跨阶段部分连接CSPDarknet通道分裂与拼接,降低重复梯度与计算量
高效多分支与注意力ELAN、C2f、C3k2多分支聚合、算子精简、末端加入轻量注意力

多尺度颈部

特征金字塔与自顶向下路径

骨干输出的特征图存在一个固有矛盾:深层特征分辨率低但语义强,浅层特征分辨率高但语义弱。检测既需要语义来判断是什么,也需要分辨率来定位在哪里。颈部的作用就是把两者融合起来。

自顶向下的路径把深层的语义信息向上传递,逐级与浅层特征相加后再做卷积平滑:

Pl=Conv(Cl+Up(Pl+1))P_l = \text{Conv}\left(C_l + \text{Up}\left(P_{l+1}\right)\right)

其中 ClC_l 是骨干在第 ll 级输出的特征,Up(⋅)\text{Up}(\cdot) 是上采样,通常用最近邻插值或转置卷积。相加之前一般会先用 1×11 \times 1 卷积把通道数对齐,这是实现上容易被忽略但必须做的一步。

自下而上的第二条路径

只有自顶向下时,浅层的高分辨率特征无法把定位细节反馈给深层。PANet 增加了自下而上的路径,把已经融合过低层信息的特征再向下传递一次:

Nl=Conv(Pl+Down(Nl−1))N_l = \text{Conv}\left(P_l + \text{Down}\left(N_{l-1}\right)\right)

其中 Down(⋅)\text{Down}(\cdot) 是步长为 2 的下采样。两条路径组合之后,每一级特征都同时包含来自更深层的语义与来自更浅层的细节,这是 YOLOv4 之后颈部的基本形态,通常记作 FPN 加 PAN 结构。

感受野扩展

在颈部与骨干之间,还有一个把不同尺度的上下文聚合起来的模块。空间金字塔池化用不同尺寸的池化核并行处理同一张特征图,再拼接输出:

SPP(x)=[ MaxPoolk1(x), MaxPoolk2(x), MaxPoolk3(x), x ]\text{SPP}(x) = \left[\, \text{MaxPool}_{k_1}(x),\ \text{MaxPool}_{k_2}(x),\ \text{MaxPool}_{k_3}(x),\ x \,\right]

其中 k1<k2<k3k_1 < k_2 < k_3 是不同尺寸的池化核。它的作用是让同一位置的表示同时包含多个尺度的邻域信息,等价于在不增加参数的前提下扩大有效感受野。工程上常见的简化版本把多个池化核改为串联复用同一个 5×55 \times 5 池化,感受野等效而并行度更好,推理速度更高。

多尺度特征的职责划分

颈部输出多个尺度的特征图,每个真值框应该由哪一级负责,需要一个分配规则。常见做法是按目标的最大边或面积落在预设区间来分配:小目标交给高分辨率特征图,大目标交给低分辨率特征图。这个规则的依据很直接:高分辨率特征图上的采样点密集,小目标能被多个位置覆盖,而低分辨率特征图上小目标可能连一个采样点都占不到。因此颈部输出的尺度数量与分配区间构成了检测器对小目标的处理能力上限,这也是密集小目标场景中往往需要额外增加高分辨率层与相应分配策略的原因。

检测头与标签分配

anchor-based:先验框与匹配规则

引入先验框后,检测头不再直接回归绝对坐标,而是预测相对先验框的偏移,前面给出的解码公式就是这一阶段的标准形式。先验框的来源是用聚类从数据集里统计得到,距离度量用交并比而非欧氏距离:

d(box,centroid)=1−IoU(box,centroid)d\left(\text{box}, \text{centroid}\right) = 1 - \text{IoU}\left(\text{box}, \text{centroid}\right)

聚类得到的先验框尺寸比人工设定更贴合数据分布,这是 YOLOv2 引入这项改动的主要收益。匹配规则通常是两个条件之一:与真值框交并比最大的先验框,以及交并比超过固定阈值的先验框,一起作为正样本。

anchor-based 方案的问题集中在三点:阈值需要针对数据集人工调整,阈值设高会导致正样本过少,设低会引入大量定位质量差的样本;正负样本比例严重失衡,需要额外的采样或损失加权;先验框的尺寸分布与类别强相关,跨数据集迁移时需要重新聚类。

anchor-free:从先验框到采样点

anchor-free 方案把预测单位从先验框改成特征图上的采样点,每个点直接回归它到目标四边的距离,也就是分别回归左、上、右、下四个方向的偏移:

prediction=( l, t, r, b, c1,…,cC )\text{prediction} = \left(\, l,\ t,\ r,\ b,\ c_1, \ldots, c_C \,\right)

其中 l,t,r,bl, t, r, b 是采样点到框四边的距离。这样每个位置只需要一个预测分支,输出通道数从 B⋅5+CB \cdot 5 + C 降到与框数量无关的形式,参数量与解码逻辑都得到简化。为了避免远离目标中心的采样点产生质量较低的框,这类方法会引入一个中心度分支,衡量当前点距离目标中心的程度:

centerness=min⁡(l,r)max⁡(l,r)⋅min⁡(t,b)max⁡(t,b)\text{centerness} = \sqrt{\frac{\min(l, r)}{\max(l, r)} \cdot \frac{\min(t, b)}{\max(t, b)}}

中心度在训练时作为回归目标参与计算,在推理时与分类分数相乘,用来压低边缘位置产生的框。它的作用是让分类分数与定位质量对齐,这一思想后来被标签分配方案直接吸收。

标签分配:从静态到动态

标签分配决定特征图上每个位置是正样本还是负样本,是家族演进中改动最频繁的一环。早期做法是静态的:固定交并比阈值,超过即判正。它的缺陷在于评价标准单一,一个分类分数很低但定位很准的预测仍可能被选为正样本,从而给出相互矛盾的训练信号。

动态分配用统一的度量把定位质量与分类质量结合,再按度量排序取前若干个位置。一种常见形式把两者的乘积作为对齐度量:

t=sα⋅uβt = s^{\alpha} \cdot u^{\beta}

其中 ss 是分类分数,uu 是预测框与真值框的交并比,α\alpha 与 β\beta 控制两项的相对权重。对每个真值框,按 tt 对所有候选位置排序,取前 KK 个作为正样本。KK 本身也可以是动态的,例如按候选位置的度量总和与全部真值框的度量总和之比分配配额,让质量高的真值框获得更多正样本。

另一种形式构造代价矩阵再求解分配,代价由分类损失与定位损失加权构成:

cij=λcls⋅Lcls(i,j)+λreg⋅Lreg(i,j)c_{ij} = \lambda_{\text{cls}} \cdot \mathcal{L}_{\text{cls}}\left(i, j\right) + \lambda_{\text{reg}} \cdot \mathcal{L}_{\text{reg}}\left(i, j\right)

其中 ii 是预测位置、jj 是真值框,再按行或按列取前若干个候选后确定最终匹配。与静态阈值相比,动态分配的共同点是:正样本的判定同时看两次预测的质量,并且配额可以随目标难度变化,因此训练信号更一致。

解耦头

早期的检测头把分类与回归放在同一个卷积分支上,共享同一组特征。这种耦合有一个内在冲突:分类更关注语义与类别间的判别性,感受野偏大更有帮助;回归更关注边界附近的细节,对位置精度更敏感。两者使用同一份特征时,梯度方向不一致,容易互相牵制。

解耦头把两条分支分开:分类分支负责类别分数,回归分支负责框的参数与质量分数,各自连接独立的卷积与损失。这样两条分支可以在同一份输入特征上学习不同的变换,同时避免了共享参数带来的梯度冲突。解耦头从 YOLOX 开始成为主流,此后的版本基本都沿用这一结构,差别只在分支内部的算子组合。

损失函数

三项损失的组成

密集预测的训练信号来自三类损失:定位损失衡量框的准度,分类损失衡量类别的判别,质量损失衡量预测的可靠性。它们按权重相加构成总损失:

L=λboxLbox+λclsLcls+λdflLdfl\mathcal{L} = \lambda_{\text{box}} \mathcal{L}_{\text{box}} + \lambda_{\text{cls}} \mathcal{L}_{\text{cls}} + \lambda_{\text{dfl}} \mathcal{L}_{\text{dfl}}

早期版本的写法更朴素,直接对不同项做加权求和,并且只对被判定为包含目标的网格单元计算定位损失,以抑制大量背景位置的干扰:

Lv1=λcoord∑i∈obj[(xi−x^i)2+(yi−y^i)2]+λcoord∑i∈obj[(wi−w^i)2+(hi−h^i)2]+⋯\mathcal{L}_{\text{v1}} = \lambda_{\text{coord}} \sum_{i \in \text{obj}} \left[ \left(x_i - \hat{x}_i\right)^2 + \left(y_i - \hat{y}_i\right)^2 \right] + \lambda_{\text{coord}} \sum_{i \in \text{obj}} \left[ \left(\sqrt{w_i} - \sqrt{\hat{w}_i}\right)^2 + \left(\sqrt{h_i} - \sqrt{\hat{h}_i}\right)^2 \right] + \cdots

其中宽高上开根号是为了压低大框的误差权重,让同样比例的偏差在大小目标之间获得相近的惩罚。这个细节说明一个贯穿全家族的问题:定位损失的形式直接决定大目标与小目标的训练是否均衡。

定位损失:从 IoU 到 CIoU

最直接的定位损失直接用交并比构造:

LIoU=1−IoU\mathcal{L}_{\text{IoU}} = 1 - \text{IoU}

它有一个明显缺陷:当两个框不相交时交并比恒为 0,梯度消失,模型得不到任何指向正确方向的信息。广义交并比引入了最小外接矩形作为惩罚项:

LGIoU=1−IoU+∣C∖(Bp∪Bg)∣∣C∣\mathcal{L}_{\text{GIoU}} = 1 - \text{IoU} + \frac{\left| C \setminus \left(B_p \cup B_g\right) \right|}{\left| C \right|}

其中 CC 是同时包含预测框与真值框的最小闭包矩形。不相交时第二项为正,损失仍然提供梯度,把预测框往真值框的方向拉。它的不足是惩罚项只反映面积关系,对两个框的相对位置不敏感。

距离交并比把中心点距离直接写进损失:

LDIoU=1−IoU+ρ2(bp,bg)c2\mathcal{L}_{\text{DIoU}} = 1 - \text{IoU} + \frac{\rho^2\left(b_p, b_g\right)}{c^2}

其中 ρ(⋅)\rho(\cdot) 是两个中心点的欧氏距离,cc 是外接矩形的对角线长度。这样收敛过程会优先对齐中心位置,实测收敛更快。完整交并比在此之上再补一项长宽比一致性:

LCIoU=1−IoU+ρ2(bp,bg)c2+αv\mathcal{L}_{\text{CIoU}} = 1 - \text{IoU} + \frac{\rho^2\left(b_p, b_g\right)}{c^2} + \alpha v

其中长宽比差异项与其权重为

v=4π2(arctan⁡wghg−arctan⁡wphp)2,α=v1−IoU+vv = \frac{4}{\pi^2}\left(\arctan\frac{w_g}{h_g} - \arctan\frac{w_p}{h_p}\right)^2, \qquad \alpha = \frac{v}{1 - \text{IoU} + v}

三项分别管重叠面积、中心距离与形状一致性,这也是当前 anchor-based 方案里最常用的定位损失形式。

分布焦点损失

直接用回归的方式预测坐标,等价于假设坐标服从单点分布,而真实标注本身存在模糊。较新的做法把连续坐标离散成若干个区间,让网络预测落在各区间的概率分布,再用期望恢复出连续值:

y^=∑i=0npi⋅i\hat{y} = \sum_{i=0}^{n} p_i \cdot i

训练时只对真值两侧最近的两个区间施加交叉熵,损失形式为

LDFL=−[(i+1−y)log⁡pi+(y−i)log⁡pi+1],i≤y<i+1\mathcal{L}_{\text{DFL}} = -\left[ \left(i+1 - y\right) \log p_i + \left(y - i\right) \log p_{i+1} \right], \qquad i \le y < i+1

它的好处是把定位从点回归变成分布学习,网络对边界模糊的样本不再被迫给出一个精确数值,而是给出一个合理的分布,同时为后面的质量估计提供了额外信息。

分类损失与类别不互斥

检测器的分类分支通常使用二元交叉熵而非 Softmax 交叉熵:

LBCE=−[ylog⁡p+(1−y)log⁡(1−p)]\mathcal{L}_{\text{BCE}} = -\left[ y \log p + \left(1 - y\right) \log \left(1 - p\right) \right]

原因是检测场景中类别并不天然互斥,同一位置可能同时属于多个标签,例如人与骑行者、容器与其中的物体。用 Softmax 会强制类别概率和为 1,把这种共存关系压掉,用逐个类别的二元交叉熵则可以独立判定。后续版本进一步对正负样本做非对称加权,让质量高的正样本获得更高权重、大量简单的负样本被降权,这类设计在形式上与焦点损失同源:

LVFL={−q(qlog⁡p+(1−q)log⁡(1−p)),正样本−αpγlog⁡(1−p),负样本\mathcal{L}_{\text{VFL}} = \begin{cases} -q \left(q \log p + \left(1 - q\right) \log \left(1 - p\right)\right), & \text{正样本} \\ -\alpha p^{\gamma} \log \left(1 - p\right), & \text{负样本} \end{cases}

其中 qq 是预测框与真值框的交并比,作为软标签使用;正样本项按 qq 加权,定位越准的样本贡献越大,负样本项用 pγp^{\gamma} 压低易分样本的权重。

后处理:NMS 与端到端

非极大值抑制

密集预测会在同一目标周围产生大量重叠框,需要收敛成一个结果。非极大值抑制的做法是按分数排序后逐个判定:保留当前最高分的框,把与它交并比超过阈值的其他框抑制掉,循环直到没有剩余。形式化地,框 bib_i 被保留的条件是

∀j, 若 scorej>scorei 则 IoU(bi,bj)<θ\forall j,\ \text{若}\ \text{score}_j > \text{score}_i\ \text{则}\ \text{IoU}\left(b_i, b_j\right) < \theta

其中 θ\theta 是抑制阈值。它的两个变体在细节上做了改进:软抑制不再直接删除重叠框,而是按重叠程度衰减其分数:

scorei←scorei⋅e−IoU(bi,bm)2σ\text{score}_i \leftarrow \text{score}_i \cdot e^{-\frac{\text{IoU}\left(b_i, b_m\right)^2}{\sigma}}

这样紧邻目标在被抑制的同时仍有机会在后续轮次中胜出,对拥挤场景更友好。另一类变体把判据从交并比换成距离交并比,使抑制判断同时考虑中心距离,减少对密集同类目标的误抑制。

NMS 的三个代价

后处理看似只是一个筛选步骤,但它给整个系统带来了三方面约束。第一,密集场景下存在不可调和的矛盾:抑制阈值高则相邻目标被误删,阈值低则同一目标出现多个结果,且不同类别、不同尺度的最优阈值并不一致。第二,它把最终结果对排序与阈值高度耦合,导致召回率与精度之间需要人工权衡。第三,也是最根本的一点,抑制过程不可微,训练时无法感知推理时的这一步骤,训练目标与推理行为之间存在不一致,模型不能通过训练学会避免生成会被抑制的框。

端到端与免抑制路线

针对上述问题,出现了两类免抑制方案。一类在检测头内部构造一对一分支:训练时同时使用一对多分支与一对一分支,推理时只用一对一分支,让一对多分支以一致性约束的方式把知识传递给一对一分支。一致性损失衡量两个分支输出的差异:

Lcons=∣po−pm∣\mathcal{L}_{\text{cons}} = \left| p^{o} - p^{m} \right|

其中 pop^{o} 与 pmp^{m} 分别是一对一与一对多分支的预测。一对一分支在训练时被强制输出更稀疏、更接近最终结果的预测,因此推理阶段可以直接取每个位置的最高分预测作为结果,不再需要抑制步骤。另一类方案源于集合预测:把检测视为集合生成问题,用匈牙利算法在预测集合与真值集合之间求一个二分图匹配,匹配代价同时包含分类与定位:

σ^=arg⁡min⁡σ∈SN∑iNLmatch(yi,y^σ(i))\hat{\sigma} = \arg\min_{\sigma \in \mathfrak{S}_N} \sum_{i}^{N} \mathcal{L}_{\text{match}}\left(y_i, \hat{y}_{\sigma(i)}\right)

由于匹配是一对一的,每个真值只对应一个预测,冗余自然消失。这类方案的代价是收敛速度慢,需要较长的训练周期与更充分的查询初始化设计,因此在实时检测中主要作为端到端特性使用,而非默认路线。

检测范式对比

把前面讨论的结构组合起来,可以得到四类被广泛使用的检测范式,它们的差异集中在正样本定义与后处理两处:

四类检测范式对比
范式 正样本定义 后处理 主要瓶颈
两阶段候选框与真值框的匹配逐候选框抑制候选数量决定推理开销
单阶段有锚先验框与真值的交并比阈值非极大值抑制阈值与先验框需要按数据调
单阶段无锚动态分配,按分类与定位一致性排序非极大值抑制分配策略与质量估计的设计成本
集合预测二分图匹配,一对一无需抑制收敛慢,训练成本高

版本演进主线

YOLO 家族的版本更替可以从三条主线看待:结构线负责特征提取与融合的效率,训练线负责标签分配与损失设计,推理线负责后处理与部署形态。三条线在不同版本中交替推进,可以概括为下表:

版本 结构线 训练线 推理线
v1 纯卷积主干与末端全连接 网格化回归,加权平方损失 阈值过滤加抑制
v2 批归一化,高分辨率分类预训练 聚类先验框,多尺度预测 抑制流程不变
v3 残差主干,三级特征金字塔 多尺度分配,二元交叉熵分类 抑制流程不变
v4 与 v5 跨阶段部分连接,空间金字塔池化,双路径颈部 Mosaic 增强,标签平滑,自适应先验框 抑制流程不变
v6 与 v7 高效多分支聚合,重参数化 动态分配,解耦头 抑制流程不变
v8 C2f 结构,轻量注意力 对齐度量分配,分布焦点损失 抑制流程不变
v9 与 v11 可编程梯度信息,区域注意力 分配与损失延续上代 抑制流程不变
v10 与 v12 结构效率优化 一对一分支与一致性约束 推理阶段免抑制

这张表可以解释一个常见疑问:为什么在骨干与颈部已经趋于稳定之后,检测器的精度仍在持续提升。答案在于训练线的改动,标签分配与损失函数的每一次调整都在改善正样本的质量,而正样本质量对密集预测的影响往往大于骨干结构的变化。

看版本号不如看它替换了什么
判断一个 YOLO 版本是否值得关注,可以问三个问题:它是否去掉了某个人工先验(先验框、固定阈值、手工融合路径),它是否改变了训练与推理的一致性(分配的复杂度、后处理是否可微),它是否改变了部署形态(端到端、量化友好度)。这三个问题比版本号本身更有区分度。

工程落地

数据增强

检测对数据分布敏感,增强手段的效果往往比结构改动更直接。Mosaic 把四张图拼接成一张作为训练样本:

I=⋃k=14crop(Ik,Rk),B={shift(b,Δk)∣b∈Bk}I = \bigcup_{k=1}^{4} \text{crop}\left(I_k, \mathcal{R}_k\right), \qquad \mathcal{B} = \left\{ \text{shift}\left(b, \Delta_k\right) \mid b \in \mathcal{B}_k \right\}

其中 Rk\mathcal{R}_k 是四张图各自的裁剪区域,Δk\Delta_k 是相应的坐标平移量,标注框随图像一起裁剪与平移,落在裁剪区域外的框被丢弃。它的作用是让单张训练图包含更多目标、更多尺度,并天然引入遮挡与截断样本,对小目标训练尤其有效。与之配套的还有 MixUp,把两张图按比例线性混合:

I=λI1+(1−λ)I2I = \lambda I_1 + \left(1 - \lambda\right) I_2

标注则直接取并集。两两组合使用可以让模型在同样的标注量下看到远为丰富的场景。

训练技巧

指数滑动平均(EMA)是检测训练里通用的一步,它维护一份参数的滑动副本用于最终评估:

θema←decay⋅θema+(1−decay)⋅θ\theta_{\text{ema}} \leftarrow \text{decay} \cdot \theta_{\text{ema}} + \left(1 - \text{decay}\right) \cdot \theta

滑动平均抑制了参数在训练末期的震荡,通常能带来稳定的增益。此外还有多尺度训练(每个批次随机缩放输入尺寸)、学习率预热与余弦退火、以及按正样本数量归一化的损失缩放。这些技巧的共同目的是让密集预测的梯度尺度在训练全程保持稳定。

部署

推理部署的第一步是算子融合。卷积与批归一化在训练时是两步,推理时因为是线性运算可以折叠成一个卷积:

W′=W⋅γσ2+ϵ,b′=(b−μ)⋅γσ2+ϵ+βW' = W \cdot \frac{\gamma}{\sqrt{\sigma^2 + \epsilon}}, \qquad b' = \left(b - \mu\right) \cdot \frac{\gamma}{\sqrt{\sigma^2 + \epsilon}} + \beta

融合后减少一次逐通道运算与一次内存往返,这在实际吞吐上的收益往往超过多数结构改动。第二步是量化,把浮点映射到整数域:

q=round(xs)+zq = \text{round}\left(\frac{x}{s}\right) + z

其中 ss 是缩放因子、zz 是零点偏移,校准阶段用少量样本统计激活分布以确定逐层参数。第三步是把后处理也放进推理图,避免检测结果在框架与后处理库之间来回搬运,这是端到端方案在部署上更简洁的原因之一。

与多目标跟踪的衔接

检测是多目标跟踪的上游,跟踪器的表现上限由检测质量决定,关联环节只能弥补而不能创造信息。以使用最广的跟踪流程为例,它先对每个轨迹维护一个运动状态并用卡尔曼滤波预测当前位置,再与当前帧的检测框做匹配:

d(z,x)=(z−Hx)⊤S−1(z−Hx)d\left(z, x\right) = \left(z - Hx\right)^\top S^{-1} \left(z - Hx\right)

其中 zz 是检测框观测、xx 是轨迹状态、HH 是观测矩阵、SS 是创新协方差,这个距离就是马氏距离。再把它与外观特征的余弦距离按权重合成匹配代价,用匈牙利算法求解最优关联:

cij=λmotiondmotion(i,j)+λappearancedappear(i,j)c_{ij} = \lambda_{\text{motion}} d_{\text{motion}}\left(i, j\right) + \lambda_{\text{appearance}} d_{\text{appear}}\left(i, j\right)

这条流程里有一个关键设计值得单独提出:当目标被遮挡时,检测器输出的置信度会下降,如果直接用置信度阈值过滤,被遮挡的目标会整段丢失,轨迹随之断开。因此现代跟踪流程会把检测框按分数分成两组,先用高分框完成主关联,再用低分框与尚未匹配的轨迹做第二次关联,把遮挡期间的低质量检测利用起来。这就要求检测头在低分区间也能给出位置合理的框,而不是全部分数坍缩到零。我在多摄像头多目标跟踪的研究中使用的就是这一组合:以 YOLOX 这类无锚解耦头作为检测器,配合 BYTE 式两次关联与重识别特征完成跨摄像头匹配。从这个角度看,检测头是否无锚、是否解耦、低分区间的输出是否稳定,都会直接影响下游跟踪的连续性,这也是评估检测器时不能只看高阈值指标的原因。

参考

[1] Redmon J, Divvala S, Girshick R, Farhadi A, You Only Look Once: Unified, Real-Time Object Detection. CVPR, 2016.
[2] Redmon J, Farhadi A, YOLO9000: Better, Faster, Stronger. CVPR, 2017.
[3] Redmon J, Farhadi A, YOLOv3: An Incremental Improvement. arXiv, 2018.
[4] Bochkovskiy A, Wang C Y, Liao H Y M, YOLOv4: Optimal Speed and Accuracy of Object Detection. arXiv, 2020.
[5] Jocher G, et al., YOLOv5. Ultralytics, 2020.
[6] Li C, et al., YOLOv6: A Single-Stage Object Detection Framework for Industrial Applications. arXiv, 2022.
[7] Wang C Y, Bochkovskiy A, Liao H Y M, YOLOv7: Trainable Bag-of-Freebies Sets New State-of-the-Art for Real-Time Object Detectors. CVPR, 2023.
[8] Ge Z, Liu S, Wang F, Li Z, Sun J, YOLOX: Exceeding YOLO Series in 2021. arXiv, 2021.
[9] Jocher G, Chaurasia A, Qiu J, YOLOv8. Ultralytics, 2023.
[10] Wang C Y, Yeh I H, Liao H Y M, YOLOv9: Learning What You Want to Learn Using Programmable Gradient Information. ECCV, 2024.
[11] Wang A, Chen H, Liu L, et al., YOLOv10: Real-Time End-to-End Object Detection. NeurIPS, 2024.
[12] Khanam R, Hussain M, YOLOv11: An Overview of the Key Architectural Enhancements. arXiv, 2024.
[13] Tian Z, Shen C, Chen H, He T, FCOS: Fully Convolutional One-Stage Object Detection. ICCV, 2019.
[14] Ge Z, Liu S, Li Z, et al., OTA: Optimal Transport Assignment for Object Detection. CVPR, 2021.
[15] Feng C, Zhong Y, Gao Y, Scott M R, Huang W, TOOD: Task-aligned One-stage Object Detection. ICCV, 2021.
[16] Rezatofighi H, Tsoi N, Gwak J, et al., Generalized Intersection over Union: A Metric and A Loss for Bounding Box Regression. CVPR, 2019.
[17] Zheng Z, Wang P, Liu W, et al., Distance-IoU Loss: Faster and Better Learning for Bounding Box Regression. AAAI, 2020.
[18] Li X, Wang W, Wu L, et al., Generalized Focal Loss: Learning Qualified and Distributed Bounding Boxes for Dense Object Detection. NeurIPS, 2020.
[19] Zhang H, Wang Y, Dayoub F, Sunderhauf N, VarifocalNet: An IoU-aware Dense Object Detector. CVPR, 2021.
[20] Bodla N, Singh B, Chellappa R, Davis L S, Soft-NMS: Improving Object Detection With One Line of Code. ICCV, 2017.
[21] Carion N, Massa F, Synnaeve G, et al., End-to-End Object Detection with Transformers. ECCV, 2020.
[22] Lin T Y, Dollar P, Girshick R, et al., Feature Pyramid Networks for Object Detection. CVPR, 2017.
[23] Liu S, Qi L, Qin H, Shi J, Jia J, Path Aggregation Network for Instance Segmentation. CVPR, 2018.
[24] Wang C Y, Liao H Y M, Wu Y H, et al., CSPNet: A New Backbone that can Enhance Learning Capability of CNN. CVPR Workshops, 2020.
[25] Wang C Y, Liao H Y M, Yeh I H, Designing Network Design Strategies Through Gradient Path Analysis. arXiv, 2022.
[26] He K, Zhang X, Ren S, Sun J, Deep Residual Learning for Image Recognition. CVPR, 2016.
[27] Ioffe S, Szegedy C, Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift. ICML, 2015.
[28] Zhang H, Cisse M, Dauphin Y N, Lopez-Paz D, mixup: Beyond Empirical Risk Minimization. ICLR, 2018.
[29] Loshchilov I, Hutter F, SGDR: Stochastic Gradient Descent with Warm Restarts. ICLR, 2017.
[30] Bewley A, Ge Z, Ott L, Ramos F, Upcroft B, Simple Online and Realtime Tracking. ICIP, 2016.
[31] Zhang Y, Sun P, Jiang Y, et al., ByteTrack: Multi-Object Tracking by Associating Every Detection Box. ECCV, 2022.
[32] Wojke N, Bewley A, Paulus D, Simple Online and Realtime Tracking with a Deep Association Metric. ICIP, 2017.
[33] Jacob B, Kligys S, Chen B, et al., Quantization and Training of Neural Networks for Efficient Integer-Arithmetic-Only Inference. CVPR, 2018.

🌙