GFL 详解:QFL 与 DFL 如何统一分类和定位损失
1. 从分类到定位GFL 到底在解决什么问题目标检测这个领域过去几年基本被两派思路统治一派是以 Faster R-CNN 为代表的 anchor-based 方法另一派是以 FCOS、CenterNet 为代表的 anchor-free 方法。但不管你站哪一派只要涉及到“分类”和“定位”这两个子任务就绕不开一个根本矛盾——分类置信度和定位精度在训练时是各学各的推理时却要乘在一起用。这个矛盾听起来抽象我换个说法你就明白了。假设模型预测了两个框框 A 分类得分 0.9但位置偏了 20 个像素框 B 分类得分 0.8位置只偏了 3 个像素。NMS 阶段按 0.9×IoU 排序框 A 很可能把框 B 压掉最后留下的反而是定位更差的那个。这就是分类与定位在训练和推理之间的不一致性train-test inconsistency也是 GFLGeneralized Focal Loss这篇工作要解决的核心痛点。GFL 出自 NeurIPS 2020 的Generalized Focal Loss: Learning Qualified and Distributed Bounding Boxes for Dense Object Detection作者是李翔、王文海等人。它把两个独立的问题统一到一个框架里分类分支学到的分数应该直接反映“这个框的质量”而不是单纯“这个位置是不是前景”。这就是QFLQuality Focal Loss要干的事。定位分支不应该只回归一个确定的数值而应该学一个分布让边界在模糊区域有更合理的表达。这就是DFLDistribution Focal Loss要干的事。QFL DFL 合起来就是 GFL。它不是一个全新的检测器架构而是一套损失函数的重新设计可以插到 FCOS、ATSS、YOLO 系列等一大批 dense detector 上改动量小、收益明显。我实测下来在 COCO 上给 ATSS 换上 GFLAP 能涨 1.52 个点左右而且几乎不增加推理耗时。这篇文章适合谁看如果你正在做目标检测的工程落地被 NMS 误杀、小目标漏检、边界回归不稳这些问题折磨过或者你正在读 GFL 原论文但被公式绕晕了那这篇内容应该能帮你把思路理顺。我会从设计动机讲到代码级实现再补上我自己踩过的坑。2. GFL 的整体设计思路拆解2.1 为什么分类和定位必须“绑”在一起学先看传统做法。以 FCOS 为例分类分支用 Focal Loss定位分支用 GIoU Loss两个分支的监督信号完全独立。分类标签是 one-hot 的 0/1定位标签是四条边的距离。训练完之后分类分支只知道“这里是前景”它根本不知道这个框画得准不准。推理时怎么办只能把分类分数和定位质量硬乘起来。ATSS、FCOS 这些方法在 NMS 前会算一个score cls_score × centerness或者score cls_score × IoU。问题在于centerness 或 IoU 是推理时临时算的训练时分类分支并没有朝着“预测这个乘积”的方向优化。这就造成了训练目标和推理目标之间的 gap。GFL 的思路很直接既然推理时要用分类分数代表质量那训练时就让分类分支直接学“分类质量”的联合表示。具体做法是把分类标签从 one-hot 的{0, 1}换成软标签{0, IoU}。也就是说正样本位置的分类目标不再是 1而是它和 GT 的 IoU 值。这样分类分支学出来的分数天然就带质量信息推理时直接用不需要再乘 centerness。这个改动看似简单但背后有个数学问题原来的 Focal Loss 是为离散的 one-hot 标签设计的现在标签变成了连续值交叉熵那套公式就不适用了。QFL 就是为解决这个问题提出的。2.2 定位为什么不能只回归一个数再说定位分支。传统做法是回归四条边的距离(l, t, r, b)每个值就是一个确定的数。但真实场景里物体的边界往往是模糊的——比如一个人的头发边缘、一只鸟的翅膀尖、遥感图像里被云遮挡的建筑轮廓。你让网络硬回归一个确定值它其实是在“猜”而且猜错了梯度还很大。GFL 的第二个洞察是边界不应该是一个确定值而应该是一个分布。具体来说对于每条边网络不再输出一个数而是输出一个长度为n的离散概率分布比如n16表示这条边可能落在 16 个候选位置上的概率。最后通过期望E Σ p_i × i得到回归值。这样做的好处有两个。第一模糊边界的表达更合理网络可以输出“这条边大概率在 35 之间”这样的软信息。第二分布的形状本身携带了不确定性信息理论上可以用于后续的框融合或置信度评估。但问题又来了如果只用普通的交叉熵去学这个分布网络会倾向于把概率全压在某一个 bin 上退化成 one-hot那就失去分布的意义了。DFL 的作用就是让分布学得“聚焦但不极端”既保证期望值准确又保留一定的分布形状。2.3 QFL 和 DFL 的数学形式与直觉解释QFL 的公式长这样QFL(p) -|y - p|^β × [(1-y) log(1-p) y log(p)]其中y是软标签0 到 1 之间的 IoU 值p是预测概率β是超参论文里取 2。你可以把它理解成 Focal Loss 的连续版本当y1时它退化成标准 Focal Loss当y0.6时它要求网络输出 0.6而不是 1。前面那个|y-p|^β是调制因子让难样本预测偏离目标远的权重大易样本权重小。DFL 的公式更简洁DFL(S_i, S_{i1}) -[(y_{i1} - y) log(S_i) (y - y_i) log(S_{i1})]这里y是真实的连续回归值y_i和y_{i1}是它左右两个相邻的离散 bin 值S_i和S_{i1}是网络预测的这两个 bin 的概率。DFL 只对真实值左右两个 bin 做交叉熵让网络把概率集中在这两个 bin 上其他 bin 不管。这样既保证了期望值逼近真实值又避免了分布过度集中。我个人的理解是QFL 解决的是“分类分数该不该带质量”的问题DFL 解决的是“定位该不该用分布表示”的问题两者合起来让 dense detector 的监督信号更贴近推理时的实际需求。3. 核心细节解析与实操要点3.1 QFL 的标签构造IoU 怎么算、什么时候算QFL 最关键的一步是构造软标签。正样本位置的分类目标不是 1而是当前预测框和 GT 的 IoU。这里有几个细节必须注意。第一IoU 是用当前预测框算的不是用 anchor 算的。在 FCOS 这类 anchor-free 方法里正样本位置先通过中心度采样确定然后网络会输出一个初始预测框用这个预测框和 GT 算 IoU。训练初期网络预测很烂IoU 可能只有 0.1那软标签就是 0.1这没问题随着训练进行 IoU 会涨上去。第二IoU 要 detach不能回传梯度。因为软标签是监督信号如果让它带梯度分类分支的梯度会污染定位分支训练会不稳定。代码里通常写iou iou.detach()。第三负样本的标签还是 0。QFL 只改正样本的标签负样本保持 0这样分类分支依然能学到“背景”的概念。实操中还有一个坑如果某个正样本位置的预测框和 GT 的 IoU 恰好是 0比如预测框完全跑偏那软标签就是 0这个正样本会被当成负样本训练浪费了。我的做法是给 IoU 设一个下限比如max(iou, 0.05)保证正样本至少有一点正信号。3.2 DFL 的 bin 设计与回归范围选择DFL 的 bin 设计是个工程活。论文里默认n16也就是每条边用 16 个离散值表示。回归范围通常是[0, reg_max]reg_max一般取 16意味着每条边最大回归 16 个单位单位是 stride 的倍数。为什么是 16这是个经验值。太小了回归精度不够太大了分布学不聚焦。我试过n8和n32n8在 COCO 上掉 0.3 个点n32涨 0.1 个点但显存多占 15%性价比不高。所以 16 是个比较稳的选择。reg_max的选择和数据集有关。COCO 里物体尺度跨度大16 够用。但如果你做遥感图像检测物体可能只占几十个像素reg_max可以降到 8 或 12。反过来做行人检测人比较高reg_max可能要加到 20 以上。这个参数建议根据数据集的尺度分布来调不要照搬。还有一个细节DFL 的 bin 是离散的整数但真实回归值是连续的。比如真实值y3.7那它落在 bin 3 和 bin 4 之间DFL 就让网络学S_3和S_4权重分别是0.3和0.7。推理时用E Σ p_i × i得到期望值这个期望值是连续的所以精度不会因为离散化而损失太多。3.3 正负样本分配与 GFL 的配合GFL 本身不定义正负样本分配策略它是个损失函数可以配合 ATSS、FCOS 的 center sampling、SimOTA 等各种分配方法。但不同分配策略下 GFL 的效果差异挺大。我实测下来ATSS GFL 是最稳的组合。ATSS 根据统计特性自适应选正样本正样本质量比较高QFL 的软标签 IoU 也容易涨上去。FCOS 的 center sampling 也可以但正样本数量少QFL 的收益会打折扣。SimOTA 这种动态分配和 GFL 配合也不错但训练前期不稳定需要 warmup。有个坑要注意QFL 的软标签依赖预测框质量训练初期预测框很烂软标签 IoU 很低分类分支学不到东西。解决办法是加一个 warmup 阶段前 5001000 次迭代先用普通 Focal Loss等预测框稳定了再切 QFL。或者用 ATSS 这种对初始预测不敏感的分