目标检测 / YOLO 实战

YOLOv8 训练自己的数据集:以 NEU-DET 钢材表面缺陷检测为例

常见的 YOLO 教程停在“开始训练”,结果只放一张 results.png。本页用东北大学 NEU-DET 数据集完整做一遍:从标签转换、划分、data.yaml、训练四个模型,到读懂 mAP50、mAP50-95、混淆矩阵和错例,所有数字来自同一次真实运行。

直接答案

用 YOLOv8 训练自己的数据集分四步:把标注转成每图一个 TXT 的 YOLO 格式,按图像划分 train/val/test,写 data.yaml 指明路径与类别,再用官方预训练权重运行 yolo detect train。在 NEU-DET 上,YOLOv8n 训练 200 轮约 29 分钟(T4),测试集 mAP50 为 77.1%,mAP50-95 为 42.1%,与公开论文的 74.8%–78.4% 一致。

本页说明

教程
这页解决什么
你手上有一个缺陷或目标检测数据集,想用 YOLOv8 或 YOLO11 训练,并判断训练出来的结果好不好、能不能写进报告。
适合谁
第一次用 YOLO 做课程设计、毕业设计或小论文的学生,以及做工业视觉检测的工程师。需要会用命令行和 Python。
读完你会得到
读完会得到一套可照做的训练流程,以及一份 NEU-DET 上四个模型的完整测试结果,可作为你自己实验的对照基线。
覆盖
  • VOC XML 转 YOLO TXT 的公式和目录结构
  • 按类别分层划分并处理重复图像
  • data.yaml 写法与服务器上的绝对路径
  • YOLOv8n/s、YOLO11n/s 在同一设置下的训练参数与真实结果
  • mAP50、mAP50-95 的含义,以及 NEU-DET 上多少算正常
  • 混淆矩阵、PR 曲线、逐类 AP 与错例的读法
不覆盖
  • 标注工具(LabelImg、Roboflow)的界面操作
  • 网络结构改进(注意力模块等)
  • 模型部署与 TensorRT 加速

主线:一步步做完

数据集

为什么做这一步先弄清数据规模和类别,后面的划分与指标都依赖这些数字。

NEU-DET 是东北大学宋克臣团队发布的热轧钢带表面缺陷检测数据集,属于 NEU surface defect database 的检测子集。数据集共 1,800 张 200×200 灰度图,6 类缺陷各 300 张,标注为 VOC XML 格式。

本次核对得到 4,189 个标注框。其中 3 处是同一张图里完全重复的标注行,Ultralytics 读取时自动去重,实际生效 4,186 个框。图像数、框数和类别数是三个不同的量,写报告时要分开写。

类别 ID英文名中文名测试集框数
0crazing龟裂107
1inclusion夹杂151
2patches斑块120
3pitted_surface麻点63
4rolled-in_scale压入氧化皮98
5scratches划痕86
类别 ID 从 0 开始,转换、训练、评估三处必须使用同一顺序。测试集 270 张图、625 个框。

第 1 步

为什么做这一步YOLO 不读 XML。每张图需要一个同名 TXT,每行一个框。

YOLO 检测标签一行五列:class_id x_center y_center width height。后四列都按原图宽高归一化到 0–1。VOC 的 bndbox 给出的是像素角点 xmin、ymin、xmax、ymax,需要换算。

例如 200×200 的图中有一个类别 0 的框 (20, 40, 100, 120),换算后的一行是 0 0.30 0.40 0.40 0.40。同一张图有两个缺陷就写两行。

目录结构(images 与 labels 一一对应)text
neu_det_yolo/
├── data.yaml
└── data/
    ├── images/{train,val,test}/crazing_103.jpg
    └── labels/{train,val,test}/crazing_103.txt
VOC 角点转 YOLO 中心点(W、H 为原图宽高)text
x_center = (xmin + xmax) / (2W)
y_center = (ymin + ymax) / (2H)
width    = (xmax - xmin) / W
height   = (ymax - ymin) / H

第 2 步

为什么做这一步train 用于更新权重,val 用于选模型和早停,test 只用于最后报告成绩。

本次按图像类别分层,固定随机种子,按 70%/15%/15% 划分为 1,260/270/270 张,每类 210/45/45 张。四个模型共用同一份划分清单。

划分前先计算每张图的 SHA256。本次发现 patches_101.jpg 与 patches_105.jpg 内容完全相同,两张图放在同一个集合;如果分到 train 和 test 两边,测试成绩会偏高。

测试集不能用来挑轮数、学习率或增强参数。看过测试集错误后再改模型,需要新的独立数据来验证。

比例优点代价
70/15/15(本次)验证集和测试集各类都有 45 张训练样本少于 80/10/10
80/10/10训练数据更多测试集每类只有 30 张,结果波动更大
工业数据按批次分组能检验换产线、换相机后的效果需要采集记录

第 3 步

为什么做这一步data.yaml 告诉 YOLO 三个集合的图片位置和类别名称。

train、val、test 指向图片目录,YOLO 会把路径中的 images 替换为 labels 去找标签。不同 Ultralytics 版本对相对 path 的解析不同,换到 GPU 服务器上训练时,在服务器上重新生成使用绝对路径的 data.yaml 最稳妥。

data.yamlyaml
path: /absolute/path/to/neu_det_yolo/data
train: images/train
val: images/val
test: images/test
names:
  0: crazing
  1: inclusion
  2: patches
  3: pitted_surface
  4: rolled-in_scale
  5: scratches

第 4 步

为什么做这一步四个模型使用完全相同的参数,结果才能比较。

先确认 GPU 与环境bash
nvidia-smi
python -c "import torch, ultralytics; print(torch.__version__, torch.cuda.is_available(), ultralytics.__version__)"
训练命令(本次正式参数)bash
yolo detect train data=data.yaml model=yolov8n.pt \
  epochs=200 patience=50 batch=16 imgsz=640 \
  optimizer=SGD lr0=0.01 seed=20261027 deterministic=True \
  workers=4 device=0
参数本次取值说明
epochs200最多训练轮数;早停时会提前结束
patience50验证指标连续 50 轮没有提升就停止
batch16T4 16 GB 显存足够
imgsz640原图 200×200 会被放大,放大不增加细节
optimizerSGD显式指定;optimizer=auto 会忽略 lr0
modelyolov8n/s.pt、yolo11n/s.pt都从官方 COCO 预训练权重开始
环境:Ultralytics 8.4.190,单块 Tesla T4。

第 5 步

为什么做这一步曲线用来判断模型是否收敛、是否过拟合,不用来报告最终成绩。

box_loss

预测框与真实框的位置误差。越低越好,但不同模型之间不能直接比数值。

cls_loss

类别判断误差。训练损失下降而验证损失持续上升,同时验证 mAP 下降,是过拟合信号。

前期剧烈波动

NEU-DET 验证集只有 270 张,单轮 mAP 波动很大。看趋势和最后 20 轮均值,不看单个峰值。

曲线停在 200 轮之前

可能是早停,也可能是中断。要看日志确认,不要把缺的轮数补上。

YOLO11n 在 NEU-DET 验证集上 mAP50 与 mAP50-95 随训练轮数变化的曲线
YOLO11n 验证集 mAP:前 75 轮剧烈波动,约 150 轮后稳定在 mAP50 75%、mAP50-95 42% 附近。
YOLO11n 训练与验证的 box loss 和 cls loss 曲线
YOLO11n 的训练(实线)与验证(虚线)损失。验证损失约 100 轮后走平,没有持续上升;最后 10 轮训练损失突然下降,是 close_mosaic=10 关闭了 Mosaic 增强。

第 6 步

为什么做这一步直接回答“我的 mAP 正常吗”:要和同一数据集、同一评估方式的基线比较。

IoU 是预测框与真实框交集面积除以并集面积。mAP50 是 IoU 阈值取 0.5 时各类 AP 的平均,只要求框大致对上。mAP50-95 是 IoU 从 0.50 到 0.95、每隔 0.05 取一次、共 10 个阈值的 AP 平均,要求框贴得更准,所以总是低于 mAP50。

网上常见“mAP50-95 大于 0.7 算良好”的说法没有数据集条件。NEU-DET 的缺陷边界模糊,四个模型的 mAP50-95 都在 41%–43%,五篇论文报告的 YOLOv8n mAP50 在 74.8%–78.4%。在这个数据集上,mAP50 约 75%、mAP50-95 约 42% 是正常基线水平。

模型测试集 mAP50测试集 mAP50-95PrecisionRecall
YOLOv8n77.06%42.14%74.7%71.6%
YOLO11n76.60%42.82%75.2%69.3%
YOLO11s75.76%42.62%74.2%71.2%
YOLOv8s74.63%41.12%72.5%69.0%
NEU-DET 测试集 270 张图,Ultralytics val 默认设置(conf=0.001,NMS IoU=0.7),单个随机种子。四个模型差距在 2.5 个百分点以内,单种子结果不足以判定谁显著更好。

第 7 步

为什么做这一步混淆矩阵告诉你错误是类别判错,还是漏检和误检。

先看坐标轴:这张图横轴是真实类别(True),纵轴是预测类别(Predicted)。对角线是判对的框数。

最下面的 background 行是漏检:真实存在、但模型没有报出来的框。龟裂一列有 53 个漏检,只判对 54 个,测试集 107 个龟裂框里漏了一半。最右边的 background 列是误检:模型报了框,但对应位置没有真实缺陷。龟裂行有 49 个误检,压入氧化皮行有 47 个。

六类缺陷之间几乎没有互相判错,只有 1 个斑块被判成麻点。NEU-DET 上的主要问题是缺陷和背景分不开,不是类别之间混淆。

YOLO11n 在 NEU-DET 测试集上的混淆矩阵,纵轴预测类别,横轴真实类别
YOLO11n 测试集混淆矩阵(计数)。横轴真实类别,纵轴预测类别。对角线外几乎全是 background 行和列。

第 8 步

为什么做这一步总 mAP 会掩盖最差类别。逐类 AP 能告诉你下一步该改哪里。

龟裂是细碎的网状纹理,分布在整片区域,标注框的边界很难统一;压入氧化皮与正常氧化层的纹理相近。这两类的 AP50-95 分别只有 14.6% 和 28.6%。想提高总 mAP,优先针对这两类:检查标注一致性,分析漏检样例,再考虑改结构。

类别YOLO11n AP50YOLO11n AP50-95三篇论文 YOLOv8n AP50
龟裂 crazing43.7%14.6%38.8%–47.9%
夹杂 inclusion85.1%41.1%82.0%–84.9%
斑块 patches93.9%64.4%88.9%–94.0%
麻点 pitted_surface85.3%57.7%83.3%–84.3%
压入氧化皮 rolled-in_scale62.7%28.6%55.9%–66.9%
划痕 scratches89.0%50.5%92.0%–97.1%
论文列为 YOLO-SDS、DDI-YOLO、Regularized YOLO 三篇报告完整六类 AP50 的范围。四个模型的最差两类一致:龟裂和压入氧化皮。
龟裂样例:绿色实线为真实框,红色虚线为预测框,左下角一处龟裂漏检
龟裂漏检样例(crazing_103.jpg)。绿色实线为真实框,红色虚线为预测框;左下角加粗的真实框没有被检出。
压入氧化皮样例:模型在没有真实缺陷的位置报出预测框
压入氧化皮背景误检样例。纹理与缺陷相似的区域被报为缺陷。

原理与判断

原理

为什么做这一步解释你的结果与论文、与别人对不上的常见原因。

本次训练写的是 imgsz=640,但 Ultralytics 的 val 默认使用矩形推理(rect=True),200×200 的图实际被处理成 672×672。用 predict 在 640×640 下保存预测、再计算 AP,得到的结果不同。

在 640 方式下:YOLO11n mAP50 为 74.29%,YOLO11s 74.03%,YOLOv8n 70.52%,YOLOv8s 69.53%。在 val 默认方式下 YOLOv8n 排第一,在 640 方式下 YOLO11n 排第一。同一批权重,评估方式不同,排名就会变化。

这个差异由独立审阅发现,报告中两套结果分开列出。和论文比较时,至少要对齐划分方式、输入尺寸、轮数、预训练权重、软件版本以及是 val 还是 test 上的结果。

论文划分YOLOv8n mAP50
FP-YOLOv8(Sensors 2024)训练/验证 7:374.8%
DDI-YOLO(Applied Sciences 2024)1440/180/18075.9%
YOLO-SDS(Sensors 2024)9:1,1620/18076.2%
DSL-YOLO(Sensors 2024)8:1:1,1440/180/18076.4%
Regularized YOLO(Sensors 2024)训练/验证 8:278.4%
本页(val 默认方式)1260/270/270,测试集77.1%
各论文划分、轮数与 batch 不同,只作范围参考,不排名。

按你的情况选择

选择

为什么做这一步按精度、速度和模型大小选模型。

在 NEU-DET 这种 1,800 张图的小数据集上,s 版本没有比 n 版本更准,CPU 推理却慢 2–3 倍。数据量小时先用 n 版本做基线;YOLO11n 参数更少,mAP50-95 略高。数据量更大或目标更小时,再试 s 及以上规模。

模型参数量GFLOPs权重大小T4 单图耗时CPU 单图耗时
YOLO11n2.61M6.65.5 MB9.7 ms166 ms
YOLOv8n3.14M8.86.5 MB8.0 ms166 ms
YOLO11s9.43M21.719.2 MB10.8 ms382 ms
YOLOv8s11.14M28.722.5 MB11.0 ms480 ms
FP32、batch=1、640 输入,含读图、预处理、推理和 NMS;10 次预热、100 次计时取平均。CPU 为 2 线程。

参考与附录

运行记录

为什么做这一步说明数据来源与运行条件,方便你复核。

本页的全部数字来自 2026 年 10 月 27 日在 Scientify 上的一次长周期研究任务。用户上传任务书后,Scientify 列出 5 条研究要求供确认,随后自行下载数据、核对重复图像、租用一块 T4 GPU 依次训练四个模型,训练结果同步回工作区后释放 GPU,再写出 35 页中文报告。

第一版报告完成后,独立审阅指出验证与测速使用的输入尺寸不一致(672 与 640)。Scientify 补做了 640 方式的完整复算,把结论从“YOLOv8n 最好”改为“排名取决于评估方式”,第二次审阅通过。全程约 5 小时,其中 GPU 使用约 3 小时。

Scientify 工作区中确认研究要求 R1 到 R5 的界面
开始前确认的 5 条研究要求:数据核对与划分、四模型训练、图表与错例、文献基线对照、交付与释放 GPU。
Scientify 根据独立审阅意见补做 640 评估并更正结论的界面
独立审阅后的修复:补算 640 方式的 AP,并在报告中分开标明两套结果。

常见报错与处理

按出现频率排序。

Dataset images not found / FileNotFoundError

原因:data.yaml 的 path 是相对路径或本机路径,到服务器上找不到;或大小写、扩展名不一致。

怎么解决:在训练机器上重新生成使用绝对路径的 data.yaml,并检查 images/train 等目录确实存在。

No labels found,或 background 数量异常多

原因:labels 目录与 images 不是镜像结构,或直接把 XML 交给了 YOLO。

怎么解决:确认每张图在 labels 下有同名 TXT 且非空;先完成 VOC 转 YOLO。

non-normalized or out of bounds coordinates

原因:TXT 里写了像素坐标,或把 COCO 的 xywh 当成 VOC 的 xyxy 计算。

怎么解决:按原图宽高重新归一化;不要全量裁剪越界框,先查出错的原始标注。

Label class exceeds dataset class count

原因:类别 ID 没有从 0 开始,或 names 顺序与转换时不一致。

怎么解决:统一一份类别映射表,转换和 data.yaml 都用它。

标签改过了,统计数字还是旧的

原因:YOLO 缓存了上次扫描结果。

怎么解决:删除 labels 旁边的 .cache 文件后重新训练。

CUDA out of memory

原因:batch 过大或有其他进程占用显存。

怎么解决:先用 nvidia-smi 查占用;仍不够时减小 batch,对比实验中所有模型一起改。

torch.cuda.is_available() 为 False

原因:装的是 CPU 版 PyTorch,或运行的不是装了 GPU 版的那个 Python。

怎么解决:用 which python 与 pip show torch 确认环境,再安装与驱动匹配的 GPU 版本。

loss 为 nan 或 mAP 一直为 0

原因:标签坐标或类别错误、没有加载预训练权重、学习率过大。

怎么解决:先抽图叠框检查标签,确认 model=*.pt,再看学习率与 AMP;增加轮数解决不了这类问题。

参考资料

常见问题

YOLOv8 训练自己的数据集需要多少轮?

本次在 NEU-DET 上设 200 轮、patience 50。验证 mAP 大约在 150 轮后稳定,YOLOv8s 在第 157 轮早停。小数据集可以设 200 轮配合早停,以验证曲线是否走平为准。

mAP50-95 多少算好?

没有跨数据集的统一标准。NEU-DET 上四个模型的 mAP50-95 在 41%–43%,mAP50 在 75% 左右,与公开论文一致。判断自己的结果时,先找同一数据集、同一划分和评估方式的基线。

YOLOv8 和 YOLO11 哪个好?

在 NEU-DET 上两者差距在 1 个百分点左右,排名随评估方式变化。YOLO11n 参数更少(2.61M 对 3.14M),mAP50-95 略高;YOLOv8n 在 T4 上略快。单种子结果不足以判定显著差异。

为什么我的 mAP 比论文低?

常见原因是划分方式、输入尺寸、训练轮数、软件版本和评估方式不同。本页中同一批权重换一种评估方式,YOLOv8n 的 mAP50 从 77.1% 变为 70.5%。比较前先把这些条件列在同一张表里。

NEU-DET 数据集哪一类最难检测?

龟裂(crazing)和压入氧化皮(rolled-in_scale)。四个模型上龟裂的 AP50 约 43%–49%,压入氧化皮约 56%–63%,主要错误是漏检和背景误检,不是类别之间判错。

没有 GPU 能训练吗?

可以在 CPU 上训练,但速度很慢。本次在 T4 上训练 YOLOv8n 200 轮约 29 分钟。没有本地 GPU 时,可以租用按小时计费的云 GPU,训练完成后立即释放。

把你自己的数据集交给 Scientify 训练

上传数据和任务说明,Scientify 会整理格式、租用 GPU 训练、出图表和报告,训练完成后自动释放 GPU。