YOLO 深入验证:IOU/mAP/ 混淆矩阵,看懂训练时的数字
YOLO 深入验证
- 前言
- 0. 验证就是给模型打分
- 1. IOU:判断预测框对不对的标准
- 2. TP / FP / FN 三个统计量
- 3. P / R / F1 核心指标
- 4. 后处理三连(conf / iou / max_det)
- 更深入一点推理过程:  后处理三连: 
- 5. conf 对 P / R / F1 的影响
- 6. P 曲线 / R 曲线 / F1 曲线
- 7. PR 曲线与 AP(平均精度)
- 8. mAP50 与 mAP50-95
- 9. fitness 与 best.pt vs last.pt
- 10. 手动验证 myval.py
- 11. 三个集的指标规律
- 12. 坑点速查表
- 13. 代码速查
- 14. 学完深入验证能干什么?
前言
基于 B 站 UP 主「林亿饼」《YOLO深入验证》整理。
前置:你已经训练好了自己的模型,想知道怎么评价它到底有多准。
视频任意门:【YOLO深入验证】 https://www.bilibili.com/video/BV1D74JzdEjd/?share_source=copy_web&vd_source=febc13c39cb98e4d1541c783e3161cab
读完你会知道:训练时那一堆数字和曲线都是什么意思,怎么手动验证,怎么用 IOU/TP/FP/FN/P/R/F1/mAP 给模型打分。
0. 验证就是给模型打分
玩 YOLO 的终极目标就是训练出一个又快又准的模型。本期重点关注:什么是准?
验证就是在给模型的准度打分。回忆当初训练的时候,每一轮是不是都会打印出一堆数字?训练结束是不是也会看到一堆曲线?这些大部分都是自动验证产生的。
主播原话:“打分就是验证,验证就是打分。”
1. IOU:判断预测框对不对的标准
第一个问题,如何判断一个预测结果是不是对的?
目标检测领域通常使用 IOU 算法评价两个框的接近程度。
IOU 全称Intersection over Union,意思就是交集在并集上面。
- 框完全重叠 → IOU = 1;
- 框完全不重叠 → IOU = 0;
- 最常用的阈值是 0.5:IOU > 0.5 才算预测对了。
主播原话:“预测结果和真实结果偏差过大,就会变成错误的预测。”
2. TP / FP / FN 三个统计量
知道怎么判断一个预测结果是不是正确了,接下来做统计。
| 指标 | 全称 | 通俗理解 | 怎么算 |
|---|---|---|---|
| TP | True Positive | 预测对的框 | IOU>0.5 的预测 |
| FP | False Positive | 预测错的框 | IOU<0.5 的预测 |
| FN | False Negative | 没找到的真实框 | 真实框 - TP |
两个恒等式:
TP + FP = 预测总数(所有预测分为对的和错的);TP + FN = 真实总数(所有真实框分为找到的和没找到的)。
主播原话:“再优秀的 COOK 第一次看到 False Negative 这个翻译也得思考半天。通俗一点就是没找到的真实结果。”
注意:
- 一个真实框只能匹配一个预测框,反之亦然;
- 一个目标被多个预测框命中,不是好事。
3. P / R / F1 核心指标
TP、FP、FN 知道了,接下来算三个核心指标。
| 指标 | 全称 | 公式 | 通俗理解 |
|---|---|---|---|
| P | Precision 精确率 | TP / (TP+FP) | 预测里有多少是对的 |
| R | Recall 召回率 | TP / (TP+FN) | 真实里有多少被找到 |
| F1 | F1-score | 2PR/(P+R) | P 和 R 的综合分 |
理想状态:P=1,R=1,代表一个也没错,一个也没漏。
主播原话:“P 和 R 是评价模型预测能力最基础的两个指标,后续各种复杂的指标都来源于此。”
4. 后处理三连(conf / iou / max_det)
推理后你会得到一大堆预测结果,每个都带着类型和概率。后处理就是去掉大部分多余的框。
| 选项 | 默认值 | 作用 | 关掉怎么写 |
|---|---|---|---|
conf | 0.25 | 去弱:去掉概率低于阈值的框 | conf=0.0 |
iou | 0.7 | 去重:NMS 合并同一目标的多个框 | iou=1.0 |
max_det | 300 | 限量:最多保留多少个框 | max_det=9999 |
记忆口诀:去弱、去重、限量。
主播原话:“这三个操作总结一下就是:去弱、去重、限量。”
更深入一点推理过程:
![]()
后处理三连:
![]()
5. conf 对 P / R / F1 的影响
- conf=0 → 跳过"去弱",框巨多,P 很低,R 很高;
- conf 调高 → 去掉垃圾预测,P 上升,R 下降;
- F1 曲线先升后降,最高点对应的 conf 就是最优阈值。
主播原话:“随着你使用的 conf 越来越高,所有类型的精确率 P 都会有上升的趋势,召回率 R 都会有下降的趋势。”
6. P 曲线 / R 曲线 / F1 曲线
随着 conf 从 0 到 1 变化,每个类型的 P、R、F1 都会变,把它们画出来就是三条曲线。
- conf 很低时:R 高、P 低;
- conf 很高时:P 高、R 低;
- F1 曲线先升后降;
- 好模型的曲线整体靠外(随便选个 conf 效果都不错);
- 差模型的曲线整体靠内(怎么调都不行)。
平均之后:
对应训练结果里的报告:
使用最优秀的conf
7. PR 曲线与 AP(平均精度)
把 P 作为纵坐标,R 作为横坐标,conf 一动就出一个点,连起来就是PR 曲线。
PR 曲线下面的面积就是 AP。
理解 AP 的关键:PR 曲线是否靠外,主要取决于 P 和 R 交点的高度。
主播原话:“能找到一个 conf 使得 P 和 R 都很高,AP 就大。”
8. mAP50 与 mAP50-95
| 指标 | 是什么 | 难度 |
|---|---|---|
| mAP50 | IOU=0.5 时的 mAP | 最常用 |
| mAP50-95 | IOU 从 0.5 到 0.95 步长 0.05 的 mAP 平均 | 最严格,最常用 |
IOU 阈值越高,指标越差(考试变难了)。
主播原话:“如果你第一次看到这里就全懂了,那我得问问你,伯,哥们,咋这么强?”
9. fitness 与 best.pt vs last.pt
每一轮验证完得到四个指标(P、R、mAP50、mAP50-95),再做一次加权平均,得到fitness(适应度)。
fitness = 0.0*P + 0.0*R + 0.1*mAP50 + 0.9*mAP50-95默认权重极度看重 mAP50-95。
| 文件 | 什么时候更新 |
|---|---|
last.pt | 每一轮都覆盖更新 |
best.pt | 只有当本轮 fitness 历史最优时才更新 |
主播比喻:“last.pt 是现任对象,best.pt 是历任最佳。”
10. 手动验证 myval.py
除了训练时的自动验证,你也可以手动验证。
fromultralyticsimportYOLO model=YOLO("results/你的模型/weights/best.pt")model.val(split="val")# 验证集# split="test" 测试集# split="train" 训练集注意:
- 不用写 data,best.pt 自己记得数据集;
- 验证其他数据集才加
data="xxx.yaml"; - 输出包含:指标表、4 条曲线、混淆矩阵、pred/labels 对比图。
混淆矩阵:看模型把哪两类搞混了(比如可口 vs 百事)。
11. 三个集的指标规律
| 数据集 | 指标通常 |
|---|---|
| 训练集 | 最好(模型背过答案) |
| 验证集 | 稍差 |
| 测试集 | 最差或和验证集接近 |
坑:把测试集图片混进训练集 = 自欺欺人,指标虚高,实际部署翻车。
主播原话:“如果你是搞应用的 COOK,发现测试效果还不错,直接把模型拿来用就行。如果你是追求极致的 COOK,不得不给模型打个分。”
12. 坑点速查表
| # | 坑 | 解决办法 |
|---|---|---|
| 1 | IOU 必须 ≥0.5 才算预测对 | 低于 0.5 就是 FP |
| 2 | 一个真实框只能匹配一个预测框 | 反之亦然 |
| 3 | TP+FP = 预测总数,TP+FN = 真实总数 | 记住这两个恒等式 |
| 4 | conf=0 不是没预测 | 是跳过了"去弱",框巨多 |
| 5 | max_det 默认 300 大部分是摆设 | 前两关就过滤完了 |
| 6 | conf 越低 P 越低 R 越高 | conf 越高 P 越高 R 越低 |
| 7 | F1 最高点对应的 conf 就是推荐阈值 | 实际部署时用这个值 |
| 8 | PR 曲线下面积 = AP | 所有类 AP 平均 = mAP |
| 9 | mAP50 是 IOU=0.5 时的 mAP | mAP50-95 是 IOU 从 0.5 到 0.95 的平均 |
| 10 | IOU 阈值越高指标越差 | 考试变难了 |
| 11 | 默认 fitness 权重 0.0/0.0/0.1/0.9 | 极度偏向 mAP50-95 |
| 12 | best.pt 不是最后一轮 | 是 fitness 最高的那一轮 |
| 13 | last.pt 每轮都覆盖 | 别拿它当最终模型 |
| 14 | 手动验证不用写 data | best.pt 自带数据集路径 |
| 15 | 测试集指标才是用来攀比的 | 验证集只是训练时参考 |
| 16 | 别把测试集图片混进训练集 | 会导致指标虚高 |
| 17 | 混淆矩阵看模型把哪两类搞混了 | 比如可口 vs 百事 |
| 18 | labels.jpg 是真实框,pred.jpg 是预测框 | 对比着看 |
| 19 | 指标可靠的前提 | 人工标注可靠 + 验证图片符合实际场景 |
| 20 | 加数据比调任何超参数都有效 | 效果差就补数据 |
13. 代码速查
# 手动验证fromultralyticsimportYOLO model=YOLO("runs/detect/train/weights/best.pt")model.val(split="test")# val / test / train# 预测时调 confmodel.predict(source="xxx.jpg",conf=0.45,iou=0.7,max_det=300)14. 学完深入验证能干什么?
- 你能看懂训练日志里的每一个数字和每一条曲线;
- 你知道 IOU、TP、FP、FN、P、R、F1、AP、mAP 都是什么意思;
- 你会用手动验证脚本,分别看训练集/验证集/测试集的指标;
- 你能根据混淆矩阵发现模型把哪两类搞混了;
- 你知道怎么选最优 conf,怎么评价一个模型到底有多准。