很多刚接触目标检测的朋友,都会在“找教程、配环境、跑模型、训练自己的数据集”这条路上连续踩坑:环境装到一半报错,跑官方权重时不知道参数是什么意思,等到想训练自己的图片数据时,又卡在标注格式和 YAML 配置上。网上的资料虽然多,但往往只讲其中一段,缺少一条能从零走到训练的完整链路。
这篇文章的目标,就是帮你把这条链路完整走通:从 YOLO 是什么、目标检测解决什么问题开始,再到环境安装、用官方权重做图片和视频推理,然后手把手标注自己的数据集、划分文件、写配置、跑训练,最后用训练好的模型做验证和推理。文章尽量用通俗语言解释原理,不堆术语,所有命令和代码都按可复制的标准给出。如果你是零基础初学者,或者之前只跑通过程序但对完整流程还不熟悉,建议先跟着顺序过一遍;如果你已经有一定基础,也可以直接跳到第 4 节以后查看训练自定义数据集的细节。
1. YOLO 目标检测到底在做什么
1.1 目标检测的本质
目标检测要解决的问题是:给定一张图片,找出图片里所有感兴趣的物体位置,并判断它们属于哪个类别。输出结果通常由两部分组成:一个是物体周围的矩形框坐标,另一个是框内物体的类别标签和置信度。
以一张马路上汽车和行人的图片为例,目标检测模型的输出可能是:
car 0.92 (x1=120, y1=80, x2=360, y2=240) person 0.87 (x1=400, y1=200, x2=520, y2=420)其中0.92表示模型认为这个框里有 92% 的把握是一辆车。这个任务和图像分类最大的区别在于:分类只回答“图片里有什么”,而检测还要回答“这些东西分别在哪里”。
YOLO 的全称是 You Only Look Once,中文可以理解为“只看一次”。它把整张图片作为输入,用一个神经网络直接回归出所有目标框的位置和类别,不需要像早期两阶段检测算法那样先生成候选区域,再对每个区域分别分类。这种“单阶段”设计让它在速度和精度之间取得了很好的平衡,也是它在工业界和学术界都非常流行的原因。
1.2 YOLO 适合哪些场景
YOLO 覆盖的场景很广,常见的包括:
- 安防监控领域的人体检测、跌倒检测、区域入侵检测。
- 自动驾驶和车路协同中的车辆、行人、交通标志检测。
- 工厂质检中的零件缺陷检测、产品计数。
- 新零售场景中的商品识别与货架巡检。
- 体育分析中的球员追踪,以及各种“小目标”检测任务。
简单来说,只要任务是“找物体并知道它在哪”,目标检测都能介入。这也是很多零基础读者选择 YOLO 作为入门方向的原因:它可以快速落地,并且生态非常完善。
1.3 为什么入门首选 YOLO
目前目标检测领域有大量优秀算法,比如 Faster R-CNN、SSD、CenterNet、DETR 等。但 YOLO 系列经过多个版本的迭代,已经把“模型结构”“训练策略”“部署工具链”整合得比较成熟,尤其是 Ultralytics 团队维护的开源版本,安装和使用都做得非常友好。
作为初学者,选择 YOLO 的好处在这里非常明显:官方文档齐全,只需要安装一个ultralytics包就能同时完成推理、训练、验证和导出;社区资料多,遇到报错基本都能搜到解决方案;代码抽象程度高,很多底层细节不需要刚入门就消化。你可以在掌握完整流程后,再去研究结构细节或尝试更复杂的检测框架。
2. 环境准备与安装
2.1 硬件与系统说明
环境准备是零基础用户最常见的一道坎。先说明结论:YOLO 模型训练和推理可以使用 CPU,也可以使用 GPU。如果只是测试官方权重、跑几张图片推理,CPU 完全够用。如果要训练自定义数据集,尤其是图片数量大、训练轮数多的情况,GPU 能节省大量时间。
本文的示例将在 Windows 11 + Python 3.10 + NVIDIA GPU 环境下运行。如果你的电脑没有 NVIDIA 显卡,或者使用的是 macOS / Linux,命令也基本一样,只是“是否启用 GPU”这个环节会有差异。版本方面,请以你实际安装的版本为准,避免不同版本之间 API 不一致导致报错。
2.2 安装 Python 与虚拟环境
我的建议是不要直接把包装到系统全局 Python 里,而是使用虚拟环境管理依赖。这里推荐使用 Anaconda 或 Miniconda,它对新手相对友好,切换环境也很方便。
去 Anaconda 官网下载并安装之后,打开终端(Windows 下为 Anaconda Prompt),先创建一个干净的虚拟环境:
conda create -n yolo python=3.10 -y conda activate yolo在命令行前出现(yolo)就表示已经进入了虚拟环境。之后在这个环境里安装的 Python 包都不会污染系统环境。
如果电脑里有多个 Python 版本,建议在创建环境后先核实一下当前解释器路径:
python --version which python正常情况应该显示出刚才创建的虚拟环境路径。这一步虽然简单,但能避免后面“明明装了包却无法 import”的问题。
2.3 安装 PyTorch
YOLO 的底层计算是基于 PyTorch 的,所以需要先安装 PyTorch。到 PyTorch 官网,根据你的 CUDA 版本选择对应的安装命令。如果不确定自己的显卡驱动支持哪个 CUDA 版本,可以在命令行输入:
nvidia-smi查看右上角的 “CUDA Version”。例如显示CUDA Version: 12.1,就可以安装对应 CUDA 12.1 的 PyTorch 版本。
CPU 版本安装命令为:
pip install torch torchvision如果你的网络环境正常,也可以直接用官网给出的命令安装。国内用户一般建议使用国内镜像源加速。下面是使用清华 PyPI 镜像安装 CPU 版 PyTorch 的示例:
pip install torch torchvision -i https://pypi.tuna.tsinghua.edu.cn/simple安装完成后,务必验证一下是否能正常导入:
import torch print(torch.__version__) print("CUDA available:", torch.cuda.is_available())如果输出CUDA available: True,说明 PyTorch 能调用 GPU。如果为False,说明当前是 CPU 状态,可以继续后面流程,但训练速度会比较慢。
2.4 安装 ultralytics
ultralytics是目前 YOLOv8 和 YOLO11 等官方实现的核心安装包。它把训练、推理、验证、导出都封装成了简洁的 API。安装命令:
pip install ultralytics -i https://pypi.tuna.tsinghua.edu.cn/simple建议同时确认一下安装版本:
pip show ultralytics后续如果遇到文档描述接口不一致的问题,优先查看当前版本的官方文档。不同小版本的默认参数可能有调整,这属于正常现象。
2.5 基础目录规划
建议单独建一个工作目录,把项目、数据集、输出结果都放在同一个地方,方便管理。
D:\yolo_project │ ├── datasets # 存放自定义数据集 ├── images # 存放测试图片 ├── runs # 训练和推理输出 ├── train.py # 训练代码 ├── detect.py # 推理代码 └── data.yaml # 数据集配置文件创建目录后,后续代码中的路径都以此为基础。路径中尽量不要包含中文,否则容易出现编码或兼容性问题。
3. 使用官方权重完成推理
3.1 推理的原理简述
在使用别人训练好的权重之前,需要想清楚一件事:推理时输入给模型的到底是什么,模型输出的又是什么。
YOLO 模型的输入是一张经过尺寸调整和归一化处理的图片。模型内部把图片划分成网格,每个网格负责预测目标中心是否落在自己区域,以及物体的宽高和类别。输出经过后处理后,就会得到最终的目标框、类别和置信度。
这些细节目前不需要全部掌握,但了解后对理解参数很有帮助。比如后面会频繁遇到的conf_thres置信度阈值,意思是低于这个分数的框会被过滤掉;iou_thres则是用于 NMS 非极大值抑制的参数,用来去掉重叠度过高的重复框。
3.2 使用命令行完成图片推理
先下载一张测试图片放到D:\yolo_project\images目录下,然后在命令行中执行:
cd D:\yolo_project yolo predict model=yolov8n.pt source=images/test.jpg第一次执行时,程序会自动下载yolov8n.pt权重文件。如果下载速度较慢,可以从官方 GitHub Release 或第三方镜像手动下载权重后放到当前目录,再执行相同的命令。
命令中的几个参数含义如下:
model:指定权重文件路径,这里使用 YOLOv8n 作为轻量级演示模型。source:推理输入,可以是图片、视频、文件夹、摄像头设备号或 URL。conf_thres:置信度阈值,默认 0.25。iou_thres:NMS 的 IoU 阈值,默认 0.45。
执行成功后,输出图片会保存到runs/detect/predict目录下。你可以在结果图片中看到每个检测目标被画上了边框和标签。
如果想指定输出目录,或者手动调节置信度阈值,可以扩展命令:
yolo predict model=yolov8n.pt source=images/test.jpg conf_thres=0.5 project=runs name=predict_test3.3 使用 Python 脚本完成推理
对于初学者,我更推荐从 Python 脚本方式理解推理流程。新建一个detect.py:
# 文件路径:D:\yolo_project\detect.py from ultralytics import YOLO # 1. 初始化模型 model = YOLO("yolov8n.pt") # 2. 执行推理 results = model.predict( source="images/test.jpg", conf_thres=0.25, iou_thres=0.45, save=True, # 保存结果图片 project="runs", # 输出目录 name="detect_demo" # 子目录名称 )在虚拟环境中运行:
python detect.py代码中YOLO("yolov8n.pt")会加载权重并构建模型。如果传入的路径不存在,程序会尝试自动下载。results是一个列表,每个元素对应一张输入图片或一帧视频的检测结果。可以在脚本中增加一段输出坐标信息的代码:
for result in results: boxes = result.boxes if boxes is not None: for box in boxes: x1, y1, x2, y2 = box.xyxy[0].tolist() cls = int(box.cls[0]) conf = float(box.conf[0]) print(f"类别索引: {cls}, 置信度: {conf:.4f}, 坐标: ({x1:.1f}, {y1:.1f}, {x2:.1f}, {y2:.1f})")如果你想做摄像头实时检测,只需要把source参数改成摄像头设备号:
results = model.predict(source=0, show=True)代码中的参数解释我放在后面第 5 节再详细展开,这里先跑通即可。
3.4 常见推理场景:视频与批量图片
视频推理是实际项目里非常常用的能力。执行方式与图片推理类似:
yolo predict model=yolov8n.pt source=test.mp4程序会逐帧读取视频,对每一帧执行目标检测,并输出一份带框的视频文件。如果你的视频比较大,或者需要实时播放,可以在 Python 中这样写:
# 文件路径:D:\yolo_project\video_detect.py from ultralytics import YOLO model = YOLO("yolov8n.pt") model.predict( source="test.mp4", save=True, project="runs", name="video_detect", show=True # 实时显示画面 )批量图片推理也很自然。假设images目录下有 10 张图片,执行:
yolo predict model=yolov8n.pt source=images程序会遍历文件夹中所有支持的图片格式,并在结果目录中一一保存检测结果。对于做“批量测试”和“模型效果对比”的场景,这个功能相当实用。
4. 制作自定义数据集
4.1 目标检测数据集的组成
使用官方权重跑通推理后,大多数人的下一个需求是从“检测通用物体”转向“训练自己的任务”。在动手采集图片前,你需要先理解 YOLO 训练格式的数据集是什么样子。
一个标准的 YOLO 数据集通常包含三部分:
- 图片文件,例如
.jpg或.png。 - 与每张图片同名的标签文件,例如
image1.jpg对应image1.txt。 - 一个描述类别名称和数据集路径的 YAML 配置。
标签文件中每一行表示一个目标,格式为:
class_id x_center y_center width height注意,YOLO 格式中存储的坐标是归一化后的相对坐标,值范围在 0 到 1 之间。假设一张图片宽度为 1000,某个目标的中心点位于 x=200,那么 x_center 应该记录为 0.2。宽高同理,除以图片原始宽高。这种归一化方式让模型不依赖图片原始尺寸,也方便在训练时统一尺寸。
4.2 图片采集与标注工具
数据是训练模型的核心。如果是在校学生或自己做实验,可以从相关公开数据集下载;如果是企业项目,建议使用现场真实图片,因为模型效果上限取决于训练数据与真实场景的分布是否一致。
对于零基础入门,我的建议是自己采集一个小型数据集,先跑通全流程,再回去扩大数据规模。
标注工具常用的有 LabelImg 和 Labelme。LabelImg 操作简单,适合输出 YOLO 格式的 txt 标签。安装方式:
pip install labelimg启动标注工具:
labelimg在软件界面中:
- 点击 “Open Dir” 选择存放图片的文件夹。
- 点击 “Change Save Dir” 选择标签输出目录。
- 点击 “Create RectBox” 或者使用快捷键
w,在图片上拖动画框。 - 输入类别名称,比如
cat、dog。 - 保存后会自动生成同名 txt 文件。
- 使用
d和a切换上一张/下一张图片。
需要注意,标注时一定不要随意,框要紧贴目标边缘且不要漏标。类别名称也要统一大小写,后面 YAML 中的类别列表和标注时使用的类别名称必须完全一致。如果类别名字写错了,轻则训练报错,重则模型效果完全混乱。
4.3 图片整理与标签文件检查
标注完成后,建议把数据整理成 YOLO 官方推荐的标准目录结构:
D:\yolo_project\datasets\mydata │ ├── images │ ├── train │ │ ├── img001.jpg │ │ └── img002.jpg │ └── val │ ├── img045.jpg │ └── img046.jpg └── labels ├── train │ ├── img001.txt │ └── img002.txt └── val ├── img045.txt └── img046.txt建议训练集和验证集按大约 8:2 或 9:1 划分。划分的原则是随机抽取,避免把同一个场景的连续帧都分到训练集,导致验证集失去代表性。
我们写一个简单的划分脚本:
# 文件路径:D:\yolo_project\split_dataset.py import os import random import shutil random.seed(42) source_images = "D:/yolo_project/images_all" train_img_dir = "D:/yolo_project/datasets/mydata/images/train" val_img_dir = "D:/yolo_project/datasets/mydata/images/val" train_label_dir = "D:/yolo_project/datasets/mydata/labels/train" val_label_dir = "D:/yolo_project/datasets/mydata/labels/val" for d in [train_img_dir, val_img_dir, train_label_dir, val_label_dir]: os.makedirs(d, exist_ok=True) all_images = [f for f in os.listdir(source_images) if f.lower().endswith((".jpg", ".jpeg", ".png"))] random.shuffle(all_images) val_count = int(len(all_images) * 0.2) val_files = all_images[:val_count] train_files = all_images[val_count:] def move_file(image_name, img_dst, label_dst): src_img = os.path.join(source_images, image_name) shutil.copy(src_img, os.path.join(img_dst, image_name)) stem = os.path.splitext(image_name)[0] src_label = os.path.join(source_images, stem + ".txt") dst_label = os.path.join(label_dst, stem + ".txt") if os.path.exists(src_label): shutil.copy(src_label, dst_label) else: print(f"警告: 图片 {image_name} 缺少标签文件") for name in train_files: move_file(name, train_img_dir, train_label_dir) for name in val_files: move_file(name, val_img_dir, val_label_dir) print(f"训练集图片数量: {len(train_files)}") print(f"验证集图片数量: {len(val_files)}")这里把原始图片和标签放在images_all文件夹中,脚本会按 8:2 比例随机复制到datasets/mydata的对应目录。
4.4 创建 data.yaml
训练之前需要告诉 YOLO:类别名称有哪些,图片目录在哪里。在D:\yolo_project\datasets\mydata\data.yaml中新建:
# 文件路径:D:\yolo_project\datasets\mydata\data.yaml train: D:/yolo_project/datasets/mydata/images/train val: D:/yolo_project/datasets/mydata/images/val nc: 2 names: ["cat", "dog"]参数说明:
train和val必须是实际的图片目录路径。nc表示类别数量 total number of classes。names是类别名称列表,顺序要和标注时保持一致,索引从 0 开始。
需要特别强调的是,YAML 文件中缩进不能混用 Tab 和空格,建议统一使用两个空格。路径分隔符可以使用正斜杠/,避免反斜杠转义带来的问题。
初学者在配置data.yaml时最常见的错误就是names列表顺序和标注文件里的class_id对不上。例如标注时第一个类别名是cat,它在data.yaml的names中索引为 0,那么所有标签文件中的 0 就代表猫。如果训练时调整了names顺序,标签里的 0 可能就变成狗了。所以在训练前务必检查。
4.5 标签内容检查工具
在训练前,强烈建议先写一个检查脚本,遍历所有标签文件,看看有没有异常数据。常见的异常包括:标签文件为空、坐标大于 1、坐标等于 0、类别索引超出范围等。下面给出一个简单检查示例:
# 文件路径:D:\yolo_project/check_labels.py import os label_dir = "D:/yolo_project/datasets/mydata/labels/train" for filename in os.listdir(label_dir): if not filename.endswith(".txt"): continue filepath = os.path.join(label_dir, filename) with open(filepath, "r", encoding="utf-8") as f: lines = f.readlines() if len(lines) == 0: print(f"警告: {filename} 是空文件") continue for line in lines: parts = line.strip().split() if len(parts) != 5: print(f"异常: {filename} 中的行格式不正确: {line.strip()}") continue class_id = int(parts[0]) x_center = float(parts[1]) y_center = float(parts[2]) width = float(parts[3]) height = float(parts[4]) if class_id < 0 or class_id >= 2: print(f"异常: {filename} 类别索引越界: {class_id}") if x_center < 0 or x_center > 1 or y_center < 0 or y_center > 1: print(f"异常: {filename} 中心点坐标超出范围") if width <= 0 or height <= 0: print(f"异常: {filename} 宽高小于等于0") print("检查完成")上面的类别数量请结合你自己的数据集调整。检查数据这一步虽然不产生直接收益,但能让你在训练报错时节省大量排查时间。
5. 训练自定义数据集
5.1 训练核心参数详解
准备完数据集后,训练命令并不复杂。但为了能正确排错和调优,最好先理解参数的作用。
yolo train model=yolov8n.pt data=D:/yolo_project/datasets/mydata/data.yaml epochs=50 imgsz=640 batch=8 device=0各个参数含义:
model:指定基础权重。可以使用官方在 COCO 上预训练好的yolov8n.pt,这种方式称为微调 fine-tuning,适用于中小数据集,收敛更快。也可以写成yolov8n.yaml,表示不加载预训练权重,从头训练。data:数据集配置文件的路径。epochs:训练轮数。轮数不代表越多越好,过拟合时模型在训练集上效果很好,但在验证集上反而变差。imgsz:训练时输入图片尺寸。默认 640,如果你图片本身是大尺寸且目标较小,可以调大;但显存占用会明显上升。batch:每次迭代送入 GPU 的图片数量。显存不足时优先调小这个值。device:指定训练设备,0表示第一块 GPU,cpu表示使用 CPU。多卡训练可以写0,1。
模型规模方面,YOLOv8n、YOLOv8s、YOLOv8m、YOLOv8l、YOLOv8x 是不同复杂度版本,n 最轻量但精度相对低,x 精度高但速度慢。入门阶段建议从yolov8n.pt起步,跑通后再根据需要换更大的模型。
5.2 使用 Python 脚本训练
新建train.py:
# 文件路径:D:\yolo_project\train.py from ultralytics import YOLO model = YOLO("yolov8n.pt") results = model.train( data="D:/yolo_project/datasets/mydata/data.yaml", epochs=50, imgsz=640, batch=8, device=0, workers=4, name="mydata_yolov8n", project="runs/train" )训练开始后,终端会打印模型结构、参数量、每轮训练损失和验证指标。常见的输出包括box_loss、cls_loss、dfl_loss以及验证集的precision、recall、mAP50、mAP50-95。
box_loss:边界框回归损失,衡量预测框与真实框的差距。cls_loss:分类损失,衡量类别预测准确程度。mAP50:当预测框与真实框的 IoU 大于 0.5 时视为检测成功,计算平均精度。mAP50-95:在 0.5 到 0.95 的 IoU 阈值范围内计算平均精度后取均值,是更严格的指标。
如果epochs设置为 50,训练结束后会得到best.pt和last.pt两个权重文件。best.pt是在验证集上指标最好的模型,last.pt是最后一轮的模型。实际使用时优先用best.pt。
5.3 验证模型效果
训练时val目录会在每轮结束后自动参与验证。如果只想加载已经训练好的权重单独验证:
yolo val model=runs/train/mydata_yolov8n/weights/best.pt data=D:/yolo_project/datasets/mydata/data.yaml输出会展示最终 mAP 等指标。对我们刚训练的小数据集,mAP 不高是正常的,因为数据量和多样性都有限。更重要的是流程是否完整、指标是否能随着训练轮数提升。
5.4 使用自定义模型进行推理
训练结束后,用自定义模型做推理和之前使用官方权重的方式完全一致。
yolo predict model=runs/train/mydata_yolov8n/weights/best.pt source=images/test.jpg或者写 Python 脚本:
# 文件路径:D:\yolo_project\predict_custom.py from ultralytics import YOLO model = YOLO("runs/train/mydata_yolov8n/weights/best.pt") results = model.predict( source="images/test.jpg", conf_thres=0.25, save=True, project="runs", name="predict_custom" )你就会在runs/predict_custom下看到模型输出的检测结果图。
5.5 增量训练与继续训练
很多项目不是一步到位,通常先训练一批数据上线,再不断补充新图片。如果新数据是在已有训练结果基础上继续迭代,建议加载上次的best.pt或last.pt继续训练:
yolo train model=runs/train/mydata_yolov8n/weights/last.pt data=D:/yolo_project/datasets/mydata/data.yaml epochs=30增量训练的好处是能保留之前学习到的特征。但要注意,如果新老数据的类别集合不一致,一定要检查data.yaml的names和nc,同时仍然建议保留一定比例的原始数据,防止灾难性遗忘。增量训练在生产环境中十分常见,掌握这个方法是工程能力进步的重要一步。
6. 常见报错与排查思路
6.1 典型报错速查表
训练和推理过程中的报错有很多,下面整理一份零基础友好的速查表:
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
torch.cuda.is_available()返回 False | PyTorch 版本与 CUDA 不匹配 | 根据显卡驱动版本重新安装对应 PyTorch |
| 训练时报 CUDA out of memory | batch 太大或图片尺寸太大 | 调小 batch,调小 imgsz,或切换更小模型 |
| 下载权重超时或失败 | 网络访问不稳定 | 手动下载权重文件放到当前目录 |
| 训练时提示 labels not found | 图片目录和标签目录不匹配 | 检查data.yaml的路径,确认同名文件一一对应 |
| 训练跑不起来,提示类别数不匹配 | nc或names配置错误 | 打开一个标签文件核对类别索引,再检查 YAML |
| loss 为 nan 或 inf | 学习率过大或数据异常 | 检查标签中是否存在超过 1 的坐标或极端宽高数据 |
| 推理结果框全部为空 | 置信度阈值太高或模型不识别该类目标 | 调低conf_thres,确认类别名称一致 |
6.2 数据相关报错的深层排查
数据类报错在自定义数据集训练中占比最高。最常见的是:
ERROR: Dataset not found, missing paths这个提示说明 YOLO 没有在data.yaml指定的路径中找到图片。排查顺序是:
- 打开
data.yaml,用绝对路径替换相对路径,检查目录是否存在。 - 检查图片目录和标签目录是否在同一个父级目录下。
- 检查验证集目录是否为空。训练集中图片数量不能为 0,验证集最好也不要为空。
- 确认图片没有损坏。YOLO 在读取图片失败时可能会报 decode 相关错误。
另一个常见报错是标签文件内容为空。部分标注工具在画框后没有正确保存,或者保存到了错误目录。这时打开对应 txt 文件看一眼,如果为空,回到标注工具重新补标。
6.3 训练显存不足的解决路径
显存不足在 Windows 本地训练时经常出现,尤其是在 batch 和 imgsz 没有按硬件调整的情况下。
优先按顺序尝试以下方法:
- 把
batch从 8 调小到 4,再不行调到 2。 - 把
imgsz从 640 调到 512。 - 把模型从
yolov8s.pt换成yolov8n.pt。 - 关闭电脑上其他占用 GPU 的程序,例如浏览器硬件加速。
如果单张显卡显存实在有限,还可以考虑使用云服务器训练。很多云平台都提供带 GPU 的实例,这时只需要把项目代码和数据集上传,再在云端按同样命令执行训练即可。对于大模型或大规模数据集,云端 GPU 几乎是必经之路。需要注意的是,无论在哪里训练,数据安全与授权都是首要考虑,不要把生产环境的敏感数据随意上传到未授权平台。
7. 训练效果评估与模型选择
7.1 看懂训练曲线
使用 Python 脚本训练时,产生的曲线保存在runs/train/mydata_yolov8n目录下。打开results.png可以看到训练损失和验证指标的曲线图。
你需要重点关注两个问题:
- 训练损失是否持续下降并趋于平稳。如果 loss 不降反升,通常说明学习率过高或数据存在较大问题。
- 验证集指标是否和训练集同步提升。如果训练集 loss 一直在下降,但验证集 mAP 不再提升甚至下降,说明模型开始过拟合,此时应该停止训练,或者增加数据量、加入数据增强。
7.2 PR 曲线和混淆矩阵
在runs/train/mydata_yolov8n目录下还有PR_curve.png和confusion_matrix.png。PR 曲线展示了精确率与召回率之间的权衡,曲线越靠近右上角表示模型越好。混淆矩阵则能帮助你看清模型把哪些类别混淆了。
这类工具在二分类或简单实验中可能没有太大感觉,但在正式项目中,它们能帮助你判断:是某些类别样本太少,还是两个类别目标视觉上太像,还是标注本身存在问题。比如猫和狗如果没有太多外形差异,模型就容易混淆。这种情况下优先补充难例样本,而不是盲目堆参数量。
7.3 如何选择模型规模
模型规模的选择本质上是在推理速度和精度之间找平衡点。你的任务如果对实时性要求高,比如视频流监控,建议选择yolov8n或yolov8s;如果精度优先,对速度不敏感,可以尝试yolov8m或更大模型。
在项目启动阶段,哪怕最终目标是大模型,也建议先用nano模型把数据链路、代码脚本、评估逻辑全部跑通。这能快速验证数据是否能支撑训练,避免每次都在换模型时重复排查数据问题。
7.4 导出为 ONNX 或其他格式
训练完成后,很多项目还需要把模型部署到服务端或其他推理框架。YOLO 官方提供了模型导出功能。导出 ONNX 格式的命令:
yolo export model=runs/train/mydata_yolov8n/weights/best.pt format=onnx导出后的.onnx文件可以用于跨平台部署。不过,不同推理框架对 ONNX 算子的支持有差异,实际部署前建议用目标框架做一次完整的验证,不要默认“导出成功就等于部署成功”。部署到边缘设备或嵌入式设备时,通常还会涉及精度量化、算子融合等优化,这部分已经超出基础教程范围,可以作为后续深入学习方向。
8. 最佳实践与工程建议
8.1 从项目一开始就做好数据管理
数据是目标检测项目里最重要的资产。很多初学者为了省事,把图片和标签堆在一个文件夹里,文件名随意命名,到后面训练验证时才发现问题。
建议在项目一开始就按统一规则管理:
- 图片命名要有序且能追溯到来源,例如
20240501_logistics_001.jpg这类带日期和业务标识的形式。 - 图片不要重复复制到多份目录,尽量只保留一份原始素材,训练目录通过脚本生成。
- 标注人员、标注时间、类别版本都应有记录。YOLO 训练格式本身没有存储这些信息,但工程管理中可以使用一个额外的
annotation_meta.csv记录。 - 每次训练前保存当前
data.yaml和标签文件的快照,方便复现训练结果。
8.2 数据标注中的关键原则
标注质量直接影响模型上限。同一个目标,如果一些人框到身体边缘,一些人框到背景,模型就会学习到混乱的边界。建议标注完成后抽检关键图片,观察框是否紧贴目标。
类别定义要保持互斥。比如一个任务既定义了“人”又定义了“工作人员”,同一目标同时被标成两个类别,模型就会困惑。如果类别之间有包含关系,例如“车辆”和“小轿车”,训练时会引入严重的标签噪声。
8.3 训练参数的工程化选择
训练不能总是用默认参数。建议按以下方式迭代参数:
- 第一轮训练使用小模型、小图片尺寸,跑全流程并观察曲线。
- 确认数据和脚本无误后,再根据硬件能力提升模型规模或训练轮数。
- 对于数据量较小的自定义数据集,不建议一开始设置过大的
epochs,可以先设 50 轮观察验证指标是否趋于平缓。 - 是否使用预训练权重,一般根据数据量大小决定。数据量大时从头训练或微调都能得到较好效果;数据量小时使用预训练权重微调通常更稳定。
8.4 训练结果的可复现性
深度学习训练中存在随机性,即使使用相同数据和代码,也可能得到略有差异的结果。在工程交付或写技术报告时,建议固定随机种子:
model = YOLO("yolov8n.pt") model.train( data="D:/yolo_project/datasets/mydata/data.yaml", epochs=50, imgsz=640, batch=8, seed=42, deterministic=True )seed参数可以设置随机种子。虽然完全复现仍然不能保证,但能在调优和排查问题时减少随机因素干扰。
8.5 如何继续提升项目精度
当自定义数据集训练完成后,如果发现 mAP 不满意,优先按顺序尝试:
- 增加训练数据量,尤其是目标形态、角度、光照条件多样的图片。
- 清理低质量标注,修正框偏移和漏标。
- 检查训练集和验证集分布是否一致。验证集应尽量模拟真实使用场景。
- 适当增加训练轮数,但要注意过拟合。
- 使用数据增强,YOLO 默认集成了多种增广策略,可以通过
augment参数控制,hsv_h、hsv_s、degrees、translate、scale等参数可以按任务需要调整。 - 考虑更换更大的基础模型。
- 使用测试时增强 TTA,推理时对图片多尺度、翻转后融合结果,能小幅提升精度但会增加推理时长。
8.6 关于模型上线前的验证
模型的线下指标不能完全代表线上表现。无论是做安防检测、工位统计还是商品识别,上线前都要在各种真实场景下做充分测试,尤其要关注模型在逆光、遮挡、运动模糊等情况下的表现。生产环境的模型版本、配置参数、回滚方案都要提前规划。如果在自己的电脑上完成了训练和推理,后续走向真实项目时,应该把版权合规、数据隐私、模型偏见等非技术问题也纳入考虑。
9. 总结
从零开始接触 YOLO 目标检测,并不需要一开始理解所有网络结构细节。更高效的学习路径是:先装好环境,跑通官方权重,然后尽快进入“制作自己的数据集 → 训练 → 验证 → 推理”的闭环。这个过程会让数据格式、模型输入输出、训练指标等核心概念自然落地。
本文开头提到的困扰,说到底是因为缺少一条完整的链路。当你完成一次自定义数据集训练后,至少应该能清楚回答以下几个问题:一张图片在训练时要经过哪些处理?标签文件里的坐标代表什么?训练日志中的 mAP50 数值说明什么问题?为什么有时候调低conf_thres会看到更多框?如果你能带着这些问题复现一遍本文的流程,说明你已经迈入了目标检测实战的门槛。
本文以yolov8n.pt作为示例跑通了全部流程。虽然你搜到的网络教程中也有yolov11或更新版本,但核心流程是相通的:安装ultralytics、准备 YOLO 格式数据集、配置 YAML、调用train和predict,换版本后主要差异体现在模型配置和个别参数变化上。后续学习建议重点关注数据增强策略、模型剪枝与量化、TensorRT 等推理优化,以及更复杂的多类别场景工程落地。如果你在安装或训练过程中遇到报错,欢迎把错误信息整理后发在评论区,大家一起排查讨论。希望这篇教程能帮你在 YOLO 学习路上减少一些不必要的弯路。