YOLO11自定义数据集训练,保姆级教学
前言
你是不是也遇到过这样的问题:想用最新的YOLO11做实例分割,但卡在第一步——不知道从哪开始准备数据?标注完不会转格式?配置文件改到怀疑人生?训练脚本跑不起来?别急,这篇教程就是为你写的。
它不讲晦涩的原理,不堆砌参数表格,不假设你已经会Labelme、会配环境、会调参。我们从你打开电脑那一刻开始,手把手带你走完完整闭环:标注一张图 → 转成YOLO能读的格式 → 组织好数据目录 → 写对配置文件 → 运行一行命令开始训练 → 看到第一个loss下降 → 用自己训出来的模型跑出第一张分割效果图。
整个过程,你只需要会点鼠标、会改几行路径、会复制粘贴代码。哪怕你昨天才第一次听说“实例分割”,今天也能跑通整套流程。
1. 准备工作:先让YOLO11镜像跑起来
你拿到的是一个预装好的YOLO11镜像,这意味着——不用自己装Python、不用配CUDA、不用下ultralytics源码、不用解决依赖冲突。所有麻烦事,镜像已经替你干完了。
镜像里已经包含:
- Python 3.9 + PyTorch 1.13(GPU加速已启用)
- Ultralytics 8.3.9 完整代码库
- Jupyter Lab 和 SSH 两种访问方式(文档里有截图,这里不重复)
1.1 进入项目目录,确认环境就绪
打开终端(或Jupyter里的Terminal),执行:
cd ultralytics-8.3.9/然后检查是否能正常导入ultralytics:
python -c "from ultralytics import YOLO; print(' YOLO11环境就绪')"如果看到 YOLO11环境就绪,说明镜像运行正常,可以继续下一步。
注意:不要手动
pip install ultralytics!镜像里已预装,重装反而可能破坏环境。
2. 数据标注:用Labelme画出物体轮廓
实例分割不是框出物体,而是精准描出它的边缘。这一步决定模型上限,但操作其实很简单。
2.1 安装并启动Labelme(镜像内已预装)
直接在终端输入:
labelmeLabelme窗口会自动弹出(如果没反应,请检查是否在图形界面环境下运行)。
2.2 标注实操:三步完成一张图
- 点击【Open Dir】→ 选择你存放原始图片的文件夹(比如
datasets/seg_point_offer_20240930/images/) - 选中一张图→ 左侧工具栏点【Create Polygon】(多边形)
- 沿着物体边缘逐点点击→ 围成闭合区域 → 右键【Finish Object】→ 在弹窗里输入类别名(如
person、car)→ 点【OK】
小技巧:按住Ctrl可拖动画布;滚轮缩放;双击自动闭合;误点了可按Delete删除最后一点。
2.3 保存标注,生成JSON文件
标完一张图,点击【Save】。Labelme会自动生成一个同名.json文件,存放在和图片同一目录下。
比如你标了001.jpg,就会生成001.json。这个文件里存着:图片尺寸、所有多边形顶点坐标、每个区域的类别名。
关键提醒:类别名必须拼写完全一致(大小写、空格、符号都不能错),后续映射全靠它。
3. 格式转换:把Labelme的JSON变成YOLO11能读的TXT
YOLO11不认JSON,它只认一种特定格式的.txt文件:每行代表一个物体,开头是类别ID,后面跟着归一化的顶点坐标。
我们用一段极简、可直接运行的Python脚本完成转换。
3.1 创建转换脚本:convert_json_to_yolo.py
在镜像的任意位置(比如ultralytics-8.3.9/目录下),新建文件convert_json_to_yolo.py,粘贴以下代码:
import json import os import glob # ====== 请务必修改这三处 ====== label_to_class_id = { "person": 0, "car": 1, "bicycle": 2, # 👇 把这里改成你实际标注的类别名!一行一个,冒号后是数字ID(从0开始) } json_dir = "./datasets/seg_point_offer_20240930/json_labels" # 改成你存JSON的文件夹路径 img_dir = "./datasets/seg_point_offer_20240930/images" # 改成你存图片的文件夹路径 output_dir = "./datasets/seg_point_offer_20240930/labels" # 输出TXT的文件夹(会自动创建) # ============================== # 自动获取图片尺寸(读取第一张图) first_img = glob.glob(os.path.join(img_dir, "*.*"))[0] from PIL import Image w, h = Image.open(first_img).size print(f" 检测到图片尺寸:{w}x{h}") # 创建输出目录 os.makedirs(output_dir, exist_ok=True) # 批量转换 json_files = glob.glob(os.path.join(json_dir, "*.json")) print(f" 找到 {len(json_files)} 个JSON文件,开始转换...") for json_path in json_files: with open(json_path, 'r', encoding='utf-8') as f: data = json.load(f) # 构造输出TXT路径(与JSON同名) base_name = os.path.splitext(os.path.basename(json_path))[0] txt_path = os.path.join(output_dir, f"{base_name}.txt") with open(txt_path, 'w') as f_out: for shape in data.get("shapes", []): label = shape["label"] points = shape["points"] class_id = label_to_class_id.get(label) if class_id is None: print(f" 警告:JSON {base_name} 中存在未定义类别 '{label}',已跳过") continue # 归一化坐标:x/w, y/h normalized = [f"{x/w:.6f} {y/h:.6f}" for x, y in points] line = f"{class_id} {' '.join(normalized)}\n" f_out.write(line) print(f" 转换完成!TXT文件已保存至:{output_dir}")3.2 运行转换脚本
在终端执行:
python convert_json_to_yolo.py你会看到类似输出:
检测到图片尺寸:640x480 找到 300 个JSON文件,开始转换... 转换完成!TXT文件已保存至:./datasets/seg_point_offer_20240930/labels此时,labels/文件夹下会出现 300 个.txt文件,每个都和图片一一对应。打开一个看看,内容类似:
0 0.123456 0.234567 0.156789 0.267890 0.189012 0.290123 ... 1 0.456789 0.567890 0.489012 0.590123 ...这就是YOLO11要的格式。
为什么用归一化坐标?因为YOLO11训练时会把图片缩放到固定尺寸(如640×640),归一化后,无论原图多大,坐标都能正确映射。
4. 组织数据集:按YOLO11要求摆好文件夹
YOLO11对数据目录结构有严格约定。镜像里已经帮你建好了骨架,你只需填内容。
4.1 标准目录结构(必须这样)
datasets/ └── seg_point_offer_20240930/ ← 你的数据集根目录(名字可自定义) ├── images/ ← 存放所有原始图片(.jpg/.png) │ ├── 001.jpg │ ├── 002.jpg │ └── ... ├── labels/ ← 存放上一步生成的所有.txt标签 │ ├── 001.txt │ ├── 002.txt │ └── ... └── trainval_split.txt ← 可选:用于划分训练/验证集(见4.2)4.2 划分训练集和验证集(简单两行命令)
YOLO11默认用train/和val/子文件夹区分数据。我们用最傻瓜的方式生成:
# 进入数据集根目录 cd ./datasets/seg_point_offer_20240930/ # 创建train和val子文件夹 mkdir -p train/images val/images train/labels val/labels # 随机取90%图片进train,10%进val(Linux/macOS) shuf -n $(( $(ls images/*.jpg | wc -l) * 9 / 10 )) <(ls images/*.jpg) | xargs -I{} cp {} train/images/ shuf -n $(( $(ls images/*.jpg | wc -l) * 1 / 10 )) <(ls images/*.jpg) | xargs -I{} cp {} val/images/ # 同步复制对应labels(文件名一致即可) for img in train/images/*.jpg; do base=$(basename "$img" .jpg) cp "labels/${base}.txt" "train/labels/" done for img in val/images/*.jpg; do base=$(basename "$img" .jpg) cp "labels/${base}.txt" "val/labels/" done echo " train/val 划分完成!"Windows用户?用Python脚本或手动拖拽,确保
train/images/和train/labels/里文件名一一对应(001.jpg↔001.txt)。
5. 配置文件:告诉YOLO11“你的数据长啥样”
YOLO11通过一个.yaml文件认识你的数据集。我们新建一个,名字叫point-offer-seg.yaml。
5.1 创建YAML文件
在ultralytics-8.3.9/目录下,新建文件point-offer-seg.yaml,内容如下:
# 数据集根目录( 必须是相对路径,从ultralytics-8.3.9/开始算) path: ./datasets/seg_point_offer_20240930 # 训练和验证图片路径(相对于path) train: train/images val: val/images # 类别数量和名称(顺序必须和label_to_class_id完全一致!) nc: 3 names: ["person", "car", "bicycle"]5.2 关键点解析
path:指向你刚组织好的数据集根目录。不能写绝对路径,必须以./开头。train/val:是path下的子路径,YOLO11会自动拼接成./datasets/.../train/images。nc:类别总数,必须等于label_to_class_id字典的长度。names:类别名列表,索引必须和字典ID完全对应(names[0]就是person,对应ID 0)。
检查清单:
point-offer-seg.yaml的names、convert_json_to_yolo.py的label_to_class_id、你Labelme里实际标注的类别名——三者必须一字不差、顺序一致。
6. 训练脚本:一行代码启动训练
镜像里已经提供了train.py示例,我们把它精简成最易懂的版本。
6.1 编写train.py
在ultralytics-8.3.9/目录下,新建train.py,内容如下:
from ultralytics import YOLO # 加载模型配置 + 预训练权重(镜像自带,无需下载) model = YOLO("ultralytics/cfg/models/11/yolo11m-seg.yaml").load("weights/yolo11m-seg.pt") # 开始训练(参数已精简,只留最关键的5个) results = model.train( data="point-offer-seg.yaml", # 👈 指向你的yaml文件 epochs=30, # 训练30轮(足够入门) imgsz=640, # 输入图像尺寸(保持和标注时一致) batch=8, # 一次处理8张图(显存够就调大) name="train2", # 保存结果的文件夹名(避免覆盖) device=0, # 使用第0块GPU(镜像已识别) )6.2 运行训练
在终端执行:
python train.py你会看到实时训练日志:
Transferred 711/711 items from pretrained weights Ultralytics 8.3.9 Python-3.9.16 torch-1.13.1 CUDA:0 (NVIDIA A30, 24062MiB) Epoch GPU_mem box_loss seg_loss cls_loss dfl_loss Instances Size 1/30 5.26G 1.621 3.875 4.195 1.21 8 640: 100%|██████████| 38/38 [00:06<00:00, 6.12it/s] Class Images Instances Box(P R mAP50 mAP50-95) Mask(P R mAP50 mAP50-95): 100%|██████████| 19/19 [00:02<00:00, 7.81it/s] all 270 396 0.999 0.886 0.934 0.587 0.974 0.864 0.896 0.454第1轮结束,你就看到了mAP指标!
第30轮结束,你会看到类似Results saved to runs/segment/train2的提示。
7. 查看训练结果:不只是数字,还有图
训练完成后,所有成果都存放在runs/segment/train2/目录下:
weights/best.pt:效果最好的模型权重(推理就用它)weights/last.pt:最后一轮的权重results.csv:每轮的loss和指标,可用Excel打开results.png:自动生成的训练曲线图(loss下降、mAP上升)val_batch*.jpg:验证集上的预测效果图(带分割掩膜!)
打开results.png,你会看到三条线:
train/box_loss:边框损失(越低越好)train/seg_loss:分割损失(越低越好)metrics/mAP50-95(B):核心指标(越高越好,0.5~0.95 IoU阈值平均)
如果mAP50-95从0.4升到0.8,恭喜你,模型真的学会了!
小技巧:用Jupyter打开
runs/segment/train2/results.csv,用Pandas画图更直观。
8. 模型推理:用你训的模型,分割新图片
训练完不推理,就像做菜不尝味。我们用5行代码,让模型干活。
8.1 编写infer.py
在ultralytics-8.3.9/目录下,新建infer.py:
from ultralytics import YOLO # 加载你训好的模型 model = YOLO("runs/segment/train2/weights/best.pt") # 对单张图推理(替换为你自己的图片路径) results = model.predict( source="./datasets/seg_point_offer_20240930/images/001.jpg", conf=0.5, # 只显示置信度>0.5的结果 save=True, # 保存结果图到 runs/predict/ show=False, # 不弹窗(服务器环境友好) retina_masks=True, # 用高分辨率掩膜,边缘更精细 ) print(" 推理完成!结果图已保存至 runs/predict/")8.2 运行并查看效果
python infer.py几秒后,打开runs/predict/文件夹,找到001.jpg的结果图。你会看到:
- 彩色分割掩膜(每个物体一种颜色)
- 白色边框和类别标签
- 清晰的物体轮廓(不是粗糙方块,是像素级贴合)
这才是实例分割该有的样子。
进阶:把
source=改成文件夹路径(如"./datasets/.../val/images"),就能批量处理整批图。
9. 常见问题速查(新手90%卡点都在这)
| 问题现象 | 最可能原因 | 一句话解决 |
|---|---|---|
ModuleNotFoundError: No module named 'ultralytics' | 没进对目录 | 先cd ultralytics-8.3.9/,再python train.py |
FileNotFoundError: point-offer-seg.yaml | YAML路径写错 | 检查train.py里data=后面的路径,必须和文件名完全一致 |
KeyError: 'person' | Labelme标注名 vs YAML names不一致 | 打开001.json看"label"字段,和point-offer-seg.yaml的names对照 |
| 训练loss不下降,mAP一直是0 | 数据集没划分好 | 检查train/images/和train/labels/里文件名是否100%匹配 |
| 推理图没有分割掩膜,只有框 | 模型加载错了 | 确保YOLO("xxx.pt")加载的是best.pt,且该权重是用-seg.yaml训的 |
CUDA out of memory | batch设太大 | 把batch=8改成batch=4或batch=2 |
总结
恭喜你,已经完整走通了YOLO11自定义数据集训练的全流程。回顾一下,你亲手完成了:
- 用Labelme画出物体真实轮廓
- 把JSON一键转成YOLO11专用TXT格式
- 摆好标准数据目录,划分train/val
- 写对YAML配置,让模型认识你的数据
- 运行5行Python代码,启动GPU训练
- 看懂训练曲线,确认模型在进步
- 用自己训的模型,分割出第一张带彩色掩膜的图
这不是终点,而是起点。接下来你可以:
- 换自己的数据集(工业零件、医疗影像、农业作物)
- 调高
epochs训更久,或改lr0学习率微调 - 试试
yolo11n-seg.yaml(轻量版)或yolo11x-seg.yaml(高精度版) - 把
infer.py改成Web服务,用Flask提供API
YOLO11的强大,不在于它有多复杂,而在于它把前沿技术封装成了可触摸、可修改、可落地的工具。你已经拿到了钥匙。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。