把目标检测变成“一次回归“,它凭什么快 10 倍?|YOLOv1 精读(上) 2015 年之前让计算机在一张图片里找出所有物体需要超过 40 秒。一个叫做 YOLO 的网络把这个时间压到了 1/45 秒——而且它只看一眼。You Only Look Once这既是它的名字也是它的全部野心。从这篇开始我们会用一个系列精读 YOLO 系列论文。第一站回到一切的起点YOLOv1。论文You Only Look Once: Unified, Real-Time Object Detection作者Joseph Redmon 等华盛顿大学 / Allen Institute for AI / Facebook AI Research发表CVPR 2016难度⭐⭐⭐需要一点 CNN 基础本篇阅读时长约 10 分钟本篇你能读到为什么 R-CNN 家族快不起来YOLO 如何用网格 回归一步完成检测置信度一个数字如何同时回答有没有和准不准一、检测曾是一道流水线工序在 YOLO 之前目标检测的主流做法有两条路线但骨子里是同一种思路把检测拆成一串独立工序。第一条路线以 DPM 为代表用滑动窗口在图上不同位置、不同尺度逐个扫描每个窗口单独跑一个分类器。第二条是 R-CNN 家族先用 Selective Search 在图上找出约 2000 个可能是物体的候选框再对每个框提取特征、分类、微调位置、去重。Fast R-CNN 和 Faster R-CNN 加速了其中几环但流水线的骨架没变。每一道工序都可以单独优化但没有一道为最终的检测结果负责。慢是最直观的。R-CNN 处理一张图超过 40 秒Fast R-CNN 只有 0.5 FPS最快的 Faster R-CNN 也只有 7 FPS——而实时的门槛是 30 FPS。误检也奇怪地高。因为分类器只能看到候选框里的一小块局部区域看不到全局上下文很容易把背景当成物体。Fast R-CNN 的头部检测结果里13.6% 是背景误检。更深一层的问题是各工序分别训练、分别调参损失函数和最终的检测指标mAP根本对不齐。YOLO 的判断很干脆与其逐环优化流水线不如把整个流水线扔掉。二、YOLO 的答案只看一次YOLO 把检测彻底重构为一个回归问题一个卷积网络看整张图一次性输出所有边界框的位置和类别。没有候选框没有滑窗没有多阶段后处理。训练和推理都是端到端。图 1YOLO 的检测只有三步缩放、过一次网络、去重。R-CNN 问的是这里像不像一个物体YOLO 问的是这张图里有什么、分别在哪里。这套设计带来的成绩单是这样的YOLO45 FPS63.4% mAPVOC 2007Fast YOLO155 FPS52.7% mAP同期最快的其他实时检测器mAP 不到它的一半因为推理时看到的是整张图YOLO 天然利用全局上下文背景误检大幅下降——这个优势我们会在下篇用实验数据详细展开。网络结构本身反而朴素24 层卷积加 2 层全连接借鉴 GoogLeNet 的思路但没有用 Inception 模块输入缩放到 448×448最终输出一个 7×7×30 的张量。真正精妙的地方不在网络深度而在如何解读这个输出张量。这就是网格模型。三、把画面切成 7×7 的网格YOLO 把输入图像划分成 S×S 个格子VOC 数据集上 S7。规则只有一条物体中心落在哪个格子就由哪个格子负责检测它。图 2物体中心落在哪个格子就由哪个格子负责检测。每个格子要预测两样东西B 个边界框每格预测 2 个覆盖不同的尺寸和宽高比。比如同一个位置一个框可能更适合瘦高的人另一个更适合趴着的狗。C 个类别概率每格只预测一组VOC 上 C20因为同一个小格子里通常只有一类物体。算一笔账7×7 个格子每格 2 个框、每个框 5 个数再加 20 个类别概率——正好拼成那个 7×7×30 的输出张量。每个数字都有明确的含义没有一处是黑箱。责任到格物体中心落在哪个格子哪个格子就全权负责——不重复检测也不互相推诿。四、一个数字同时回答两个问题每个边界框除了坐标还带一个置信度confidence。这个数是 YOLO 里最容易被误读、也最聪明的设计。直觉上它同时编码了两件事这个框里有物体的可能性以及这个框画得有多准。用文字写出它的定义就是置信度 有物体的概率 × 预测框与真值的 IOU测试时再乘上格子的类别概率就得到每个框最终的类别置信度。这个分数一路参与排序和去重直接决定哪些框能留下来。置信度不是一个普通的概率而是一句完整的承诺这里有物体而且我的框很准。但你可能注意到一个微妙的问题训练的时候有物体的概率和框有多准是怎么拧成一个回归目标的答案藏在损失函数里——这是下篇的重头戏。五、整个检测其实只有三步把前面所有设计串起来YOLO 的完整推理流程用伪代码写出来只有七行def detect(image, net): img resize(image, (448, 448)) # 1. 统一尺寸 tensor net.forward(img) # 2. 一次前向输出 7×7×30 boxes decode_boxes(tensor) # 解码出 98 个候选框 scores conf * class_prob # 计算类别置信度 keep scores 0.2 # 3a. 阈值过滤 return non_max_suppression(boxes) # 3b. NMS 去重看不懂代码也没关系记住三件事就行缩放图片、过一次网络、去掉重复的框。对比之下R-CNN 每张图要处理约 2000 个候选框YOLO 只产生 98 个计算量从源头上就小了一个数量级。到这里你已经知道 YOLO 长什么样、怎么想问题。但一个网络不可能天生就会检测——它是怎么学会给框打分的损失函数里为什么要给宽高开平方为什么它在艺术品上能碾压 R-CNN却数不清一群鸟下篇我们拆开 YOLO 的损失函数和实验数据也聊聊它暴露的短板如何定义了之后十年的 YOLO 系列。本文基于 arXiv:1506.02640v5 全文整理数据与公式均对照原文。