YOLOv12 作为 Ultralytics 推出的最新一代目标检测模型,在骨干网络、Neck 结构和损失函数上都做了针对性优化,兼顾了检测精度与推理速度,尤其在小目标和遮挡场景下的表现提升明显。
不少同学拿到新版本后,卡在环境配置、数据集格式、训练参数调优等环节,反复踩坑却找不到清晰的可复现流程。本文以自定义目标检测数据集为例,完整走通从环境搭建、数据标注、配置编写、模型训练、参数调优到推理测试的全流程,同时整理了实际训练中高频出现的问题和解决方案,全程可复现,新手也能跟着一步步跑通。
整体训练流程概览
先给大家梳理完整的训练链路,避免走一步看一步,做到心中有数:
一、环境搭建:先把基础跑通
很多人训练失败的根源,从环境安装阶段就埋下了。这里给出最稳妥的安装方案,避开90%的环境坑。
1.1 基础环境要求
- Python:3.10 ~ 3.12(兼容性最好,不建议用3.8以下或3.13以上版本)
- PyTorch:2.4.0 及以上
- CUDA:11.8 / 12.1 / 12.4(对应PyTorch版本,无GPU可直接用CPU版本)
- 显存:至少4GB(跑yolov12n,batch=8),8GB以上可正常训练s/m版本
1.2 分步安装
第一步:创建并激活虚拟环境(强烈建议用conda或venv隔离环境,避免依赖冲突)
conda create -n yolov12 python=3.10 conda activate yolov12第二步:安装PyTorch 根据你的CUDA版本选择对应命令,这里以CUDA 12.1为例:
pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121如果是CPU版本,直接运行:
pip3 install torch torchvision torchaudio踩坑提示:不要直接
pip install torch,默认会安装CPU版本,导致训练速度慢几十倍。安装完成后验证CUDA是否可用:import torch print(torch.cuda.is_available()) # 输出True则GPU可用 print(torch.version.cuda) # 查看对应CUDA版本
第三步:安装Ultralytics YOLOv12 已经集成在Ultralytics库中,直接安装即可:
pip install ultralytics -i https://pypi.tuna.tsinghua.edu.cn/simple国内用户建议加上清华源,下载速度更快。
第四步:验证安装
yolo checks如果正常输出环境信息、GPU显存信息,说明安装成功。
二、自定义数据集准备与格式转换
数据集质量直接决定模型上限,比模型大小、参数调优重要得多。
2.1 数据集采集与清洗
- 图片数量:单类别建议至少200张以上,多类别每个类别不少于100张;小目标、遮挡场景要单独补充样本
- 图片分辨率:尽量和训练分辨率(640/1280)接近,避免过度拉伸
- 场景多样性:覆盖不同光照、角度、背景、遮挡情况,避免数据集单一
- 清洗:删除模糊、重复、标注错误的图片,剔除无目标的负样本(或单独作为负样本集)
2.2 数据标注
常用标注工具推荐LabelImg或LabelMe,也可以用在线平台Roboflow。标注时注意:
- 标注框要紧贴目标边缘,不要过大或过小
- 类别ID从0开始,和后续配置文件严格对应
- 遮挡目标也要完整标注,不要只标可见部分
- 小目标不要漏标,这是YOLOv12优化的重点场景
2.3 YOLO标注格式说明
YOLO使用归一化的txt标签文件,每张图片对应一个同名txt文件,每一行格式为:
class_id x_center y_center width heightclass_id:类别编号,从0开始x_center y_center:目标框中心点坐标,相对于图片宽高归一化到0~1width height:目标框的宽和高,同样归一化到0~1
踩坑提示:标注格式错误是新手最常见的问题,比如坐标没有归一化、类别ID从1开始、标签和图片数量不对应,都会导致训练报错或mAP为0。
2.4 数据集划分与目录结构
按照7:2:1的比例划分为训练集、验证集、测试集,目录结构必须严格遵循以下格式:
datasets/ └── custom_dataset/ ├── images/ │ ├── train/ # 训练集图片 │ ├── val/ # 验证集图片 │ └── test/ # 测试集图片(可选) └── labels/ ├── train/ # 训练集标签,和图片同名 ├── val/ # 验证集标签 └── test/ # 测试集标签这里给一个快速划分数据集的Python脚本,把图片和标签按比例自动分配:
import os import random import shutil # 配置路径 img_dir = "./all_images" label_dir = "./all_labels" output_dir = "./datasets/custom_dataset" split_ratio = [0.7, 0.2, 0.1] # train:val:test # 创建目录 for split in ['train', 'val', 'test']: os.makedirs(os.path.join(output_dir, 'images', split), exist_ok=True) os.makedirs(os.path.join(output_dir, 'labels', split), exist_ok=True) # 获取所有图片 img_list = [f for f in os.listdir(img_dir) if f.endswith(('.jpg', '.png', '.jpeg'))] random.shuffle(img_list) # 划分 total = len(img_list) train_end = int(total * split_ratio[0]) val_end = train_end + int(total * split_ratio[1]) for i, img_name in enumerate(img_list): label_name = os.path.splitext(img_name)[0] + '.txt' if i < train_end: split = 'train' elif i < val_end: split = 'val' else: split = 'test' shutil.copy(os.path.join(img_dir, img_name), os.path.join(output_dir, 'images', split, img_name)) if os.path.exists(os.path.join(label_dir, label_name)): shutil.copy(os.path.join(label_dir, label_name), os.path.join(output_dir, 'labels', split, label_name)) print(f"划分完成:train={train_end}, val={val_end-train_end}, test={total-val_end}")三、数据集配置文件编写
YOLO通过YAML文件读取数据集信息,这一步写错,后面训练大概率报错。
在项目根目录新建custom.yaml,内容如下:
# 数据集根目录(绝对路径/相对路径都可以,建议用绝对路径避免歧义) path: ./datasets/custom_dataset # 训练集、验证集、测试集图片路径,相对于path的相对路径 train: images/train val: images/val test: images/test # 类别数量 nc: 3 # 类别名称,顺序必须和标注的class_id严格对应 names: ['cat', 'dog', 'person']关键坑点提醒
- 路径不要有中文和空格:Windows下中文路径极易导致读取失败,全部用英文命名
- nc和类别数必须一致:多一个少一个都会导致训练异常
- names顺序和标注ID严格对应:标注里的0号类别,必须是names列表的第一个元素,这是mAP为0的头号元凶
- path是根目录:train/val路径是相对于path的,不要写成完整绝对路径拼接
四、模型训练:参数配置与启动
4.1 预训练模型选择
YOLOv12 提供了n/s/m/l/x五个版本,根据显存和精度需求选择:
| 模型 | 参数量 | 推荐显存 | 适用场景 |
|---|---|---|---|
| yolov12n | 2.6M | 4GB+ | 移动端、边缘部署、快速验证 |
| yolov12s | 9.4M | 6GB+ | 平衡精度速度,工业场景首选 |
| yolov12m | 20.1M | 8GB+ | 高精度需求,服务器训练 |
| yolov12l | 26.3M | 12GB+ | 更高精度,大数据集 |
| yolov12x | 58.1M | 24GB+ | 极致精度,科研/大型项目 |
新手建议:先用yolov12n跑通完整流程,确认数据集和配置没问题,再换大模型调优。
4.2 启动训练
直接用命令行启动训练,这是最稳定的方式:
yolo detect train \ model=yolov12n.pt \ data=custom.yaml \ epochs=100 \ imgsz=640 \ batch=16 \ device=0 \ workers=4 \ patience=20 \ project=runs/detect \ name=train_exp14.3 核心参数详解
model:预训练权重,首次运行会自动下载data:数据集配置文件路径epochs:训练轮数,小数据集50-100轮足够,大数据集可以到200-300轮imgsz:训练图片分辨率,默认640,小目标可以设为1280batch:批次大小,根据显存调整,显存不够就调小,一般是2的倍数device:GPU设备,单卡填0,多卡填0,1,CPU填cpuworkers:数据加载线程数,Windows下建议设为0,否则容易报错patience:早停轮数,验证集mAP连续多少轮不提升就停止训练,防止过拟合project/name:训练结果保存路径
4.4 进阶训练技巧
- 断点续训:训练中断后,不用从头开始,直接加载权重继续训练:
yolo detect train resume=True model=runs/detect/train_exp1/weights/last.pt- 冻结骨干网络:小数据集建议先冻结骨干网络训练,避免过拟合:
yolo detect train model=yolov12n.pt data=custom.yaml freeze=10 epochs=30先冻结前10层训练30轮,再解冻全部层训练,效果会更好。 3.关闭数据增强:数据集很小的时候,过度增强反而会破坏特征,可以关闭mosaic和mixup:
yolo detect train model=yolov12n.pt data=custom.yaml mosaic=0.0 mixup=0.0五、训练监控与调优策略
训练结果会保存在runs/detect/train_exp1/目录下,重点关注这几个文件:
weights/best.pt:验证集mAP最高的权重,推理用这个weights/last.pt:最后一轮的权重,断点续训用这个results.png:训练曲线,包含loss、mAP、precision、recall等指标PR_curve.png:精确率-召回率曲线confusion_matrix.png:混淆矩阵,看类别间的误检情况
5.1 指标怎么看
- mAP50:IOU阈值0.5下的平均精度,是最常用的指标,工业场景一般要求0.8以上
- mAP50-95:IOU从0.5到0.95的平均精度,更能反映模型的定位精度
- train loss / val loss:训练集和验证集损失,正常情况下两者同步下降
- Precision / Recall:精确率和召回率,根据业务需求平衡
5.2 常见问题与调优
- 过拟合:train loss持续下降,val loss先降后升
- 增加训练数据,补充不同场景的样本
- 开启更强的数据增强(mosaic、mixup、hsv增强)
- 降低学习率,增加权重衰减
- 减少训练轮数,启用早停
- 冻结骨干网络,使用更小的模型
- 欠拟合:train loss和val loss都很高,mAP上不去
- 增加训练轮数
- 换更大的模型
- 调大学习率,减少冻结层数
- 检查数据集标注是否正确,是否有大量错误标注
- 适当提高训练分辨率
- 小目标检测效果差
- 提高训练分辨率到1280
- 增加小目标样本数量
- 开启Copy-Paste、随机裁剪等针对小目标的增强
- 调整anchor,适配小目标尺寸
六、推理测试与模型导出
训练完成后,用测试集验证模型效果,再导出部署格式。
6.1 命令行推理
单张图片推理:
yolo detect predict \ model=runs/detect/train_exp1/weights/best.pt \ source=test.jpg \ conf=0.25 \ iou=0.45 \ save=True视频/文件夹批量推理:
# 视频推理 yolo detect predict model=best.pt source=test.mp4 save=True # 批量推理文件夹 yolo detect predict model=best.pt source=./test_images save=True6.2 Python代码推理
适合集成到自己的项目中:
from ultralytics import YOLO # 加载模型 model = YOLO('runs/detect/train_exp1/weights/best.pt') # 推理 results = model.predict( source='test.jpg', conf=0.25, # 置信度阈值,根据业务调整 iou=0.45, # NMS的IOU阈值 save=True, # 保存结果图片 device=0 ) # 解析结果 for result in results: boxes = result.boxes print(f"检测到{len(boxes)}个目标") for box in boxes: cls_id = int(box.cls[0]) conf = float(box.conf[0]) x1, y1, x2, y2 = box.xyxy[0].tolist() print(f"类别:{model.names[cls_id]},置信度:{conf:.2f},坐标:[{x1:.1f}, {y1:.1f}, {x2:.1f}, {y2:.1f}]")6.3 模型导出
训练好的模型可以导出为不同格式,方便部署:
# 导出ONNX格式(通用部署) yolo export model=best.pt format=onnx opset=12 # 导出TensorRT格式(GPU加速,速度最快) yolo export model=best.pt format=engine half=True # 导出TorchScript格式 yolo export model=best.pt format=torchscript踩坑提示:导出ONNX时建议指定opset=12,避免部署时出现算子不兼容;TensorRT导出需要和部署环境的CUDA、TensorRT版本一致。
七、高频踩坑问题与解决方案
1. CUDA out of memory 显存溢出
- 调小batch size,比如从16改成8、4
- 降低训练分辨率imgsz,比如从640改成512
- 换更小的模型(nano→small)
- 关闭
cache=ram,改用cache=disk或关闭缓存 - 减少workers线程数
2. 训练报错 Dataset not found / 找不到数据集
- 检查yaml文件中的path和train/val路径是否正确
- 路径不要有中文、空格、特殊字符
- 确认图片和标签的目录结构完全匹配
- 标签文件和图片必须同名,后缀为.txt
3. mAP始终为0 / 精度极低
- 检查nc类别数和实际类别数是否一致
- 确认names顺序和标注的class_id完全对应
- 检查标签格式是否正确,坐标是否归一化
- 确认训练集和验证集都有对应标签
- 检查是否所有图片都没有标注目标
4. 训练不收敛,loss不下降
- 检查数据集标注是否正确,是否存在大量错误标注
- 调整学习率,默认lr0=0.01,小数据集可以调小到0.001
- 增大batch size,batch太小会导致梯度不稳定
- 检查是否冻结了太多层,导致模型无法学习
- 确认预训练权重下载完整,没有损坏
5. Windows下workers参数报错
Windows系统下数据加载多线程容易出问题,直接把workers设为0即可:
yolo detect train ... workers=06. 验证集mAP很高,实际推理效果差
- 过拟合:验证集和测试集分布不一致,补充真实场景样本
- 置信度阈值设置过高,适当调低conf参数
- 数据增强过度,训练时的增强和实际场景差异太大
- 测试图片分辨率和训练分辨率差异过大
7. 预训练权重下载失败
网络问题导致权重下载慢或失败,可以手动从Ultralytics官网下载对应权重,放到当前目录,再执行训练命令即可。
写在最后
YOLOv12 的训练流程整体和前代保持一致,但在模型结构和默认参数上做了优化,上手门槛并不高。对于新手来说,最关键的是先跑通最小流程:用少量数据、小模型、默认参数跑通一次完整的训练-推理链路,再逐步优化数据集和调参。
训练目标检测模型,数据集质量永远是第一位的。与其反复调参数、换大模型,不如先把数据集标注做扎实,补充足够的场景多样性,往往能带来更明显的效果提升。
如果需要进一步优化部署速度,还可以基于导出的ONNX/TensorRT模型做量化、剪枝,或者结合DeepStream、TensorRT做端到端的推理加速。