Windows 下复现 YOLO11 目标检测训练:数据准备、环境安装、训练验证与模型导出

文章摘要

本文以 Ultralytics 8.3.253 源码版本为基础,重新整理 YOLO11 自定义目标检测数据集训练流程。文章从版本固定、数据采集、标注规范、目录整理、Windows 环境安装、数据集 YAML 配置、CLI 与 Python 两种训练方式、预测验证、结果查看、模型导出和常见问题排查几个角度展开。重点不是介绍 YOLO11 的理论细节,而是让读者能够在自己的电脑上把数据集跑通,并为后续 YOLO11 改进、部署和项目实战文章打好统一代码基础。

CSDN 标签

  • YOLO11
  • Ultralytics
  • 目标检测
  • PyTorch
  • Windows
  • 深度学习
  • 自定义数据集
  • 模型训练

前言

很多 YOLO 教程写得比较早,里面使用的命令、源码路径和模型名称已经和现在的 Ultralytics 项目不完全一致。如果直接拿旧文章去套 YOLO11,经常会遇到两个问题:一个是读者找不到对应文件,另一个是后面写模型改进文章时,不同版本代码结构对不上。

所以这篇文章重新基于 ultralytics-8.3.253 版本来写。本文不追求把所有参数都讲完,而是先把目标检测训练最核心的一条线跑通:

准备图片 -> 标注目标 -> 整理数据集 -> 配置环境 -> 训练 YOLO11 -> 验证模型 -> 导出权重

后续如果要做 YOLO11 添加注意力机制、替换 Neck、导出 ONNX、TensorRT 部署等内容,都可以继续沿用这个版本,减少因为版本变化带来的复现问题。

一、先把版本固定住:为什么本文使用 Ultralytics 8.3.253

本文使用的是本地源码压缩包:

ultralytics-8.3.253.zip

解压后可以在 ultralytics/__init__.py 中看到版本号:

__version__ = "8.3.253"

这个版本已经包含 YOLO11 的模型配置,目标检测模型配置文件在:

ultralytics/cfg/models/11/yolo11.yaml

固定版本有三个好处:

  1. 后面修改源码时,文件位置不会变来变去。
  2. 写系列文章时,读者能使用同一套代码复现。
  3. 出现报错时,更容易判断是代码问题、环境问题还是数据集问题。

需要注意的是,直接执行 pip install ultralytics 可能会安装到更新版本。如果本文是为了后续改进 YOLO11 源码,建议使用源码安装方式,而不是只安装 PyPI 最新包。

二、先规划数据来源:别急着训练模型

训练目标检测模型之前,最容易被忽略的是数据质量。模型能不能学好,很多时候不是由训练命令决定的,而是由图片是否贴近真实应用场景决定的。

常见数据来源可以分成几类:

数据来源 适合情况 注意点
自己拍摄 工业检测、农业检测、安防监控等真实项目 场景最贴近实际,但采集成本高
开源数据集 类别常见、任务通用 类别定义和实际业务可能不完全一致
网络图片 快速补充样本 要注意版权、重复图片和低质量图片
视频抽帧 监控、车载、流水线检测 相邻帧重复度高,需要抽样筛选
合成图片 特殊目标难采集时 只能辅助,不能完全替代真实数据

如果是第一次训练,可以先准备一个小数据集试跑,例如每个类别几十到几百张图片。确认流程没问题后,再扩充数据量。

数据采集时建议提前想清楚这几个问题:

  • 要检测的类别有几个?
  • 每个类别是否都有足够样本?
  • 图片中目标大小是否接近真实使用场景?
  • 是否包含白天、夜晚、遮挡、不同角度等情况?
  • 是否有大量重复图片?

这些问题比盲目增加训练轮数更重要。

三、标注数据集:统一类别编号和框选规则

YOLO11 目标检测使用的标签格式仍然是 YOLO 检测格式。每张图片对应一个同名 .txt 文件,标签文件中每一行表示一个目标:

类别编号 目标中心点x 目标中心点y 目标宽度 目标高度

这里的坐标不是像素值,而是归一化后的比例值,范围一般在 0~1 之间。

例如:

0 0.5123 0.4382 0.1634 0.2851
1 0.3128 0.6610 0.0924 0.1375

含义是:

  • 第一列:类别编号,从 0 开始
  • 第二列:目标框中心点的 x 坐标
  • 第三列:目标框中心点的 y 坐标
  • 第四列:目标框宽度
  • 第五列:目标框高度

标注工具可以选择自己顺手的,例如:

  • LabelImg
  • CVAT
  • Roboflow
  • Make Sense
  • Label Studio

标注时重点检查这几件事:

  1. 同一个类别不要一会儿叫 helmet,一会儿叫 hardhat
  2. 类别编号必须从 0 开始,不能跳号。
  3. 图片和标签文件必须同名。
  4. 框不要明显偏离目标,也不要把目标框少一半。
  5. 没有目标的图片可以保留,但要确认训练逻辑是否需要空标签文件。

举个例子,图片和标签应该这样对应:

000001.jpg  ->  000001.txt
000002.jpg  ->  000002.txt
000003.jpg  ->  000003.txt

如果文件名对不上,后面训练时很容易出现标签读取异常,或者明明有图片却没有标签的情况。

四、整理数据集目录:推荐使用 images 和 labels 对称结构

为了让后续配置更清楚,建议把数据集整理成下面这种结构:

SafetyHelmet/
├── images/
│   ├── train/
│   ├── val/
│   └── test/
├── labels/
│   ├── train/
│   ├── val/
│   └── test/
└── helmet.yaml

这里以安全帽检测数据集举例,实际项目中可以换成自己的数据集名称。

各目录作用如下:

目录 作用
images/train 训练图片
labels/train 训练标签
images/val 验证图片
labels/val 验证标签
images/test 测试图片,可选
labels/test 测试标签,可选

如果你的图片和标签一开始都混在一个文件夹里,可以先写一个简单脚本划分。下面这个脚本会读取原始图片目录,然后按照比例复制到新目录中。

from pathlib import Path
import random
import shutil


def make_yolo_dataset(src_images, src_labels, dst_root, train=0.75, val=0.15):
    src_images = Path(src_images)
    src_labels = Path(src_labels)
    dst_root = Path(dst_root)

    image_files = []
    for ext in ("*.jpg", "*.jpeg", "*.png", "*.bmp"):
        image_files.extend(src_images.glob(ext))

    random.seed(2026)
    random.shuffle(image_files)

    train_num = int(len(image_files) * train)
    val_num = int(len(image_files) * val)

    split_map = {
        "train": image_files[:train_num],
        "val": image_files[train_num:train_num + val_num],
        "test": image_files[train_num + val_num:],
    }

    for split_name, files in split_map.items():
        image_out = dst_root / "images" / split_name
        label_out = dst_root / "labels" / split_name
        image_out.mkdir(parents=True, exist_ok=True)
        label_out.mkdir(parents=True, exist_ok=True)

        for image_path in files:
            label_path = src_labels / f"{image_path.stem}.txt"

            shutil.copy2(image_path, image_out / image_path.name)
            if label_path.exists():
                shutil.copy2(label_path, label_out / label_path.name)
            else:
                print(f"未找到标签文件:{label_path}")


make_yolo_dataset(
    src_images=r"D:/dataset_raw/helmet/images",
    src_labels=r"D:/dataset_raw/helmet/labels",
    dst_root=r"D:/datasets/SafetyHelmet",
)

这段脚本的重点不是复杂,而是保证图片和标签同步移动。实际使用时,只需要修改最后三行路径。

五、安装训练环境:使用源码方式更适合后续改进

本文默认在 Windows 环境下操作。先创建一个新的 conda 环境:

conda create -n yolo11_83253 python=3.10
conda activate yolo11_83253

然后进入解压后的源码目录:

cd D:\AIProjects\ultralytics-8.3.253

执行源码安装:

pip install -e .

-e 的意思是 editable,也就是可编辑安装。这样做的好处是:你后面修改源码文件后,不需要每次重新打包安装。

安装完成后,检查一下当前环境中的版本:

python -c "import ultralytics; print(ultralytics.__version__)"

如果输出:

8.3.253

说明当前环境已经指向本文使用的代码版本。

再检查 PyTorch 是否能识别 GPU:

import torch

print("PyTorch:", torch.__version__)
print("CUDA available:", torch.cuda.is_available())
print("CUDA version:", torch.version.cuda)

如果 torch.cuda.is_available() 输出 False,训练仍然可以用 CPU 跑通流程,但速度会慢很多。正式训练建议配置好 CUDA 版本的 PyTorch。

六、编写数据集配置 YAML:训练前最该仔细检查的文件

Ultralytics 训练时需要通过 YAML 文件告诉程序:训练图片在哪、验证图片在哪、类别有哪些。

以安全帽数据集为例,可以新建:

D:/datasets/SafetyHelmet/helmet.yaml

内容如下:

path: D:/datasets/SafetyHelmet
train: images/train
val: images/val
test: images/test

names:
  0: helmet
  1: no_helmet

这个文件很短,但很关键。

字段解释:

  • path:数据集根目录
  • train:训练集图片路径
  • val:验证集图片路径
  • test:测试集图片路径,没有测试集可以先不写
  • names:类别编号和类别名称

Windows 下建议路径使用 /,例如:

path: D:/datasets/SafetyHelmet

不要写成容易转义出错的形式:

path: D:\datasets\SafetyHelmet

另外,如果标签文件中出现类别编号 2,但是 names 只写到 1,训练时就会报类别越界相关错误。

七、第一次训练 YOLO11:先跑通,不要一开始就堆参数

YOLO11 检测模型可以直接使用预训练权重开始训练。第一次建议使用 yolo11n.pt,因为它比较轻,适合快速验证数据集和环境是否正常。

命令如下:

yolo detect train model=yolo11n.pt data=D:/datasets/SafetyHelmet/helmet.yaml epochs=100 imgsz=640 batch=16 device=0

这条命令可以拆开理解:

参数 说明
detect 目标检测任务
train 训练模式
model=yolo11n.pt 使用 YOLO11n 预训练权重
data=...helmet.yaml 数据集配置文件
epochs=100 训练 100 轮
imgsz=640 输入尺寸为 640
batch=16 每次训练读取 16 张图片
device=0 使用第 0 张 GPU

如果没有 NVIDIA GPU,可以先用 CPU 测试流程:

yolo detect train model=yolo11n.pt data=D:/datasets/SafetyHelmet/helmet.yaml epochs=5 imgsz=640 batch=4 device=cpu

CPU 训练很慢,但用来检查数据集格式是可以的。

如果显存不够,优先改这几个参数:

batch=8
imgsz=512
model=yolo11n.pt

不要一上来就用 yolo11x.pt。大模型更吃显存,数据集没检查好之前没有必要。

八、用 Python 脚本训练:更适合后续做实验对比

如果后续要写改进文章,建议准备一个 Python 训练脚本,方便切换模型和参数。

新建 train_helmet_yolo11.py

from ultralytics import YOLO


def main():
    model = YOLO("yolo11n.pt")

    model.train(
        data=r"D:/datasets/SafetyHelmet/helmet.yaml",
        epochs=100,
        imgsz=640,
        batch=16,
        device=0,
        workers=4,
        project="runs/helmet",
        name="yolo11n_baseline",
    )


if __name__ == "__main__":
    main()

运行:

python train_helmet_yolo11.py

这里额外设置了:

  • project="runs/helmet":把实验结果统一放到 runs/helmet 下面
  • name="yolo11n_baseline":给本次实验命名为 baseline

后面做模型改进时,可以继续使用类似命名:

yolo11n_baseline
yolo11n_cbam
yolo11n_bifpn
yolo11n_slimneck

这样不同实验结果会更清楚。

九、训练结果保存在哪里:重点看 best.pt 和 results.csv

如果使用上面的 Python 脚本,训练结果会保存在:

runs/helmet/yolo11n_baseline/

常用文件如下:

runs/helmet/yolo11n_baseline/
├── weights/
│   ├── best.pt
│   └── last.pt
├── results.csv
├── results.png
├── confusion_matrix.png
└── args.yaml

文件说明:

文件 作用
best.pt 验证集表现最好的权重,后续预测一般用它
last.pt 最后一轮训练保存的权重
results.csv 每轮训练和验证指标
results.png 损失和指标曲线图
confusion_matrix.png 混淆矩阵
args.yaml 本次训练使用的参数

如果要写实验结果,建议优先根据 results.csvresults.png 来整理,不要凭感觉写“效果很好”。

十、预测图片和视频:先用 best.pt 看实际效果

训练完成后,可以先找几张没有参与训练的图片做预测。

命令行预测:

yolo detect predict model=runs/helmet/yolo11n_baseline/weights/best.pt source=D:/datasets/demo_images save=True conf=0.25

参数说明:

  • model:训练得到的权重
  • source:图片、文件夹、视频或摄像头
  • save=True:保存预测结果
  • conf=0.25:置信度阈值

如果要预测视频:

yolo detect predict model=runs/helmet/yolo11n_baseline/weights/best.pt source=D:/videos/test.mp4 save=True

如果要调用摄像头:

yolo detect predict model=runs/helmet/yolo11n_baseline/weights/best.pt source=0 show=True

Python 预测写法:

from ultralytics import YOLO


model = YOLO("runs/helmet/yolo11n_baseline/weights/best.pt")
model.predict(
    source=r"D:/datasets/demo_images",
    save=True,
    conf=0.25,
)

预测结果通常会保存到 runs/detect/predict 或新的递增目录中。

十一、验证模型:mAP50 和 mAP50-95 要分清楚

验证命令如下:

yolo detect val model=runs/helmet/yolo11n_baseline/weights/best.pt data=D:/datasets/SafetyHelmet/helmet.yaml device=0

Python 方式:

from ultralytics import YOLO


model = YOLO("runs/helmet/yolo11n_baseline/weights/best.pt")
metrics = model.val(data=r"D:/datasets/SafetyHelmet/helmet.yaml", device=0)

print("mAP50-95:", metrics.box.map)
print("mAP50:", metrics.box.map50)
print("mAP75:", metrics.box.map75)

这里一定要注意:

  • metrics.box.map50 是 mAP50
  • metrics.box.map 是 mAP50-95

很多文章会把这两个指标混着写,这是不严谨的。一般情况下,mAP50 会比 mAP50-95 高,因为 mAP50 的 IoU 阈值更宽松。

本文不展示未经实际训练得到的指标数值。完成自己的训练后,可以结合 results.csvresults.png 和验证命令输出查看 mAP50、mAP50-95、Precision 与 Recall,所有结果均应以本机实际运行记录为准。

十二、导出模型:为部署提前准备 ONNX 等格式

训练得到的 .pt 权重适合在 PyTorch / Ultralytics 环境中使用。如果要部署到其他推理框架,通常需要导出。

导出 ONNX:

yolo export model=runs/helmet/yolo11n_baseline/weights/best.pt format=onnx imgsz=640

Python 写法:

from ultralytics import YOLO


model = YOLO("runs/helmet/yolo11n_baseline/weights/best.pt")
model.export(format="onnx", imgsz=640)

常见格式可以这样理解:

导出格式 适合场景
ONNX 通用部署,ONNX Runtime、OpenCV DNN 常用
TensorRT NVIDIA GPU 推理加速
OpenVINO Intel CPU / 核显部署
TorchScript PyTorch 生态部署
NCNN 移动端和边缘设备部署

如果只是训练和测试,暂时不导出也可以。导出主要是为了后续写部署、界面调用、端侧推理等内容。

十三、常见问题:先从路径、标签和显存查起

1. yolo 命令无法识别

现象:

'yolo' 不是内部或外部命令

原因: 没有激活正确环境,或者 ultralytics 没有安装成功。

解决方法:

conda activate yolo11_83253
cd D:\AIProjects\ultralytics-8.3.253
pip install -e .

然后重新执行:

yolo version

2. 训练时报数据集路径不存在

原因: helmet.yaml 中的 pathtrainval 路径拼接后找不到真实目录。

排查方式: 先手动打开路径,例如:

D:/datasets/SafetyHelmet/images/train
D:/datasets/SafetyHelmet/images/val

确认目录真实存在,并且里面有图片。

3. 标签类别编号越界

现象: 标签中出现了某个类别编号,但 YAML 中没有定义这个类别。

例子:

names:
  0: helmet
  1: no_helmet

但标签文件里出现:

2 0.5 0.5 0.2 0.2

这时类别 2 就是非法编号。需要重新检查标注类别。

4. 图片有标签,但训练时提示标签缺失

原因: 图片名和标签名没有完全对应。

例如:

images/train/001.jpg
labels/train/001.txt

这是正确的。

下面这种就容易出问题:

images/train/001.jpg
labels/train/001.xml

YOLO 检测训练需要 .txt 格式标签。

5. CUDA 显存不足

解决思路:

batch=8
imgsz=512
model=yolo11n.pt

如果还不够,就继续降低 batch,或者先使用 CPU 跑几轮检查流程。

6. Windows 下 dataloader 多进程报错

可以先把 workers 调小:

yolo detect train model=yolo11n.pt data=D:/datasets/SafetyHelmet/helmet.yaml workers=0

如果 workers=0 可以正常运行,再逐步调到 24

7. 预测结果保存目录找不到

Ultralytics 会自动创建递增目录,例如:

runs/detect/predict
runs/detect/predict2
runs/detect/predict3

如果不是第一次预测,结果可能不在 predict,而是在后面的递增目录。

十四、总结

本文围绕 Ultralytics 8.3.253 版本,把 YOLO11 自定义目标检测训练流程重新整理了一遍。整个流程的重点不是把命令堆在一起,而是先固定代码版本,再保证数据集格式、环境安装、训练命令和结果查看都能对应起来。

实际做项目时,建议先使用 yolo11n.pt 跑通小规模数据集,确认图片、标签、YAML 和环境没有问题。流程稳定后,再考虑换更大的模型、增加数据量、调整超参数或加入改进模块。

后续如果继续写 YOLO11 改进文章,可以把本篇作为基础环境篇。这样朋友们可以先跑通 baseline,再去看注意力机制、Neck 替换、损失函数修改、模型导出部署等内容,会更容易复现,也更容易判断改进是否真的有效。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐