YOLO 入门实战(二):用自定义数据训练你的第一个检测模型

YOLO 入门实战(二):用自定义数据训练你的第一个检测模型

上一篇中,我们从零开始,完成了目标检测项目的第一步:构建并标注了自己的小规模数据集 。通过 Conda 创建独立环境,使用 Label Studio 进行高效标注,并成功导出为 YOLO 可读的格式------现在,我们的硬盘里已经躺着一个结构清晰、标签准确的数据集了。 数据是"燃料",而模型就是"引擎"。今天,我们将点燃这台引擎,使用 Ultralytics YOLOv8,训练属于你自己的第一个目标检测模型

1.构建YOLO开发环境

首先依旧使用conda创建一个用于开发YOLO的虚拟环境,然后激活这个虚拟环境并下载所需要的依赖。

bash 复制代码
conda create -n yolo python=3.11 -y
conda activate yolo
# 下载依赖
pip install ultralytics
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu126

2.将导出的数据集添加到项目

我们需要按照下面的结构来建立目录

kotlin 复制代码
yolo-project/ 
├── dataset/ 
│ ├── images/ 
│ ├── labels/ 
│ └── data.yaml 
└── runs/

将原先数据集中按照1:4的比例划分验证集和训练集,然后将图片和标签分别对应放入images文件夹和labels文件夹的train以及val文件夹集合中。然后我们可以开始编写我们的data.yaml,这个文件相当于是告诉YOLO我们的训练集、验证集、测试集(可选)的位置以及我们进行目标检测的一些配置参数,这个是我简单构造的一个data.ymal文件

yaml 复制代码
path: ./boxing
train: images/train
val: images/val
augment: true
mosaic: true
mixup: true
degrees: 5.0  # 随机旋转角度
translate: 0.1  # 平移比例
scale: 0.5  # 缩放比例
flipud: 0.0  # 上下翻转概率
fliplr: 0.5  
names: 
  0: Tissue box

其中参数

  • path标识了数据集路径,比如我们的项目中肯呢个有多个数据集
  • train标识了训练图片的位置
  • val标识了验证图片的位置
  • mosaic指的是使用马赛克数据增强,具体在训练中的体现是将4 张训练图像拼接成一张大图,作为一次输入送入网络进行训练。- 模型在一张图上看到更多场景和目标组合,增加了背景多样性
  • mixup同样也是属于数据增强,具体的体现是将 两张图像按权重线性混合,生成一张新的"虚拟"训练图像。
  • 其他几个参数也是用于在小数据集中为了防止过拟合增加图像的复杂度

3.开始训练和验证

我们创建一个python文件命名为boxing.py

python 复制代码
from ultralytics import YOLO

CONFIG = {
   'data'  : 'datasets/boxing/dataset.yaml',
   'model' : 'yolov8n.pt',
   'epochs': 20,
   'imgsz': 640,
   'batch': -1,
   'device': 0,
   'name': 'boxing',
   'exist_ok': True,
   'lr0': 0.01,
}

def train_model():
    print('Training model...')

    #加载模型
    model = YOLO(CONFIG['model'])

    model.train(
        data = CONFIG['data'],
        epochs = CONFIG['epochs'],
        imgsz = CONFIG['imgsz'],
        batch = CONFIG['batch'],
        device = CONFIG['device'],
        name = CONFIG['name'],
        lr0 = CONFIG['lr0'],
        mosaic = 0.8,
        mixup = 0.2
    )

    print('Training completed.')

    return model

def val_model(model):
    print('Validating model...')

    metrics = model.val()
    
    return metrics

def test_model(model,test_image):
    print('Testing model...')

    results = model(test_image)

    results[0].show()

    results[0].save(filename='test_result.jpg')

    print('Testing completed.')

def main():
    model = train_model()

    val_model(model)

    test_model(model,test_image='datasets/boxing/images/test/微信图片_20250828122329.jpg')

if __name__ == '__main__':
   
    main()

这里我们先声明了一个常量来定义了模型训练中需要的参数。这里我们指定了模型使用了"yolov8n.pt",首次运行时框架会自动下载这个模型,一般在项目的根目录会出现一个yolov8n.pt的文件。然后我们对其他几个参数做个介绍

  • epochs 训练的总轮数。每个epoch代表对整个数据集的一次完整遍历。调整此值会影响训练时长和模型性能。我的数据集非常小,所以设置了一个较小的值
  • imgsz 用于训练的目标图像大小。图像被调整为边长等于指定值的正方形
  • batch 批次大小,具有三种模式:设置为整数(例如, batch=16),自动模式,GPU 内存利用率为 60%(batch=-1),或具有指定利用率分数的自动模式(batch=0.70
  • device 0 代表指定单个GPU
  • name 训练运行的名称。用于在项目文件夹中创建一个子目录,训练日志和输出存储在该子目录中
python 复制代码
model = YOLO(CONFIG['model'])

model.train(
    data = CONFIG['data'],
    epochs = CONFIG['epochs'],
    imgsz = CONFIG['imgsz'],
    batch = CONFIG['batch'],
    device = CONFIG['device'],
    name = CONFIG['name'],
    lr0 = CONFIG['lr0'],
    mosaic = 0.8,
    mixup = 0.2
)

通过两行代码即可完成训练,第一步加载模型,第二步开始训练

这里我们可以看到有输出一些日志,日志大概会经历一下过程 首先打印了模型所使用的参数

txt 复制代码
Ultralytics 8.3.186  Python-3.11.13 torch-2.6.0+cu126 CUDA:0 (NVIDIA GeForce RTX 4060, 8188MiB)
engine\trainer: agnostic_nms=False, amp=True, augment=False, auto_augment=randaugment, batch=-1, bgr=0.0, box=7.5, cache=False, cfg=None, classes=None, close_mosaic=10, cls=0.5, conf=None, copy_paste=0.0, copy_paste_mode=flip, cos_lr=False, cutmix=0.0, data=datasets/boxing/dataset.yaml, degrees=0.0, deterministic=True, device=0, dfl=1.5, dnn=False, dropout=0.0, dynamic=False, embed=None, epochs=10, erasing=0.4, exist_ok=False, fliplr=0.5, flipud=0.0, format=torchscript, fraction=1.0, freeze=None, half=False, hsv_h=0.015, hsv_s=0.7, hsv_v=0.4, imgsz=640, int8=False, iou=0.7, keras=False, kobj=1.0, line_width=None, lr0=0.01, lrf=0.01, mask_ratio=4, max_det=300, mixup=0.2, mode=train, model=yolov8n.pt, momentum=0.937, mosaic=0.8, multi_scale=False, name=boxing4, nbs=64, nms=False, opset=None, optimize=False, optimizer=auto, overlap_mask=True, patience=100, perspective=0.0, plots=True, pose=12.0, pretrained=True, profile=False, project=None, rect=False, resume=False, retina_masks=False, save=True, save_conf=False, save_crop=False, save_dir=runs\detect\boxing4, save_frames=False, save_json=False, save_period=-1, save_txt=False, scale=0.5, seed=0, shear=0.0, show=False, show_boxes=True, show_conf=True, show_labels=True, simplify=True, single_cls=False, source=None, split=val, stream_buffer=False, task=detect, time=None, tracker=botsort.yaml, translate=0.1, val=True, verbose=True, vid_stride=1, visualize=False, warmup_bias_lr=0.1, warmup_epochs=3.0, warmup_momentum=0.8, weight_decay=0.0005, workers=8, workspace=None
Overriding model.yaml nc=80 with nc=1

然后加载训练集的数据

txt 复制代码
Transferred 319/355 items from pretrained weights
Freezing layer 'model.22.dfl.conv.weight'
AMP: running Automatic Mixed Precision (AMP) checks...
AMP: checks passed 
train: Fast image access  (ping: 0.10.0 ms, read: 2580.4884.8 MB/s, size: 938.8 KB)
train: Scanning G:\Personal\智能零售\yolo\datasets\boxing\labels\train.cache... 14 images, 0 backgrounds, 0 corrupt: 100% ━━━━━━━━━━━━ 14/14  0.0s
train: G:\Personal\\yolo\datasets\boxing\images\train\04584b67__e261c101-%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20250828144509.jpg: corrupt JPEG restored and saved
train: G:\Personal\\yolo\datasets\boxing\images\train\1692c175__228f9682-%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_202508281445095.jpg: corrupt JPEG restored and saved
train: G:\Personal\\yolo\datasets\boxing\images\train\1dbe9524__1c51d3d3-%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20250828144508.jpg: corrupt JPEG restored and saved
train: G:\Personal\\yolo\datasets\boxing\images\train\77e7630e__5ccc8767-%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_202508281445092.jpg: corrupt JPEG restored and saved
train: G:\Personal\\yolo\datasets\boxing\images\train\8ae9f90a__5de81dc2-%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20250828132718.jpg: corrupt JPEG restored and saved
train: G:\Personal\\yolo\datasets\boxing\images\train\9aed3697__44aaa78b-%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20250828144447.jpg: corrupt JPEG restored and saved
train: G:\Personal\\yolo\datasets\boxing\images\train\a3fbc99b__fcf8750d-%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20250828134930.jpg: corrupt JPEG restored and saved
train: G:\Personal\\yolo\datasets\boxing\images\train\bba171f6__5697ba4c-%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20250828122329.jpg: corrupt JPEG restored and saved
train: G:\Personal\\yolo\datasets\boxing\images\train\c34187c9__02c69289-%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20250828144510.jpg: corrupt JPEG restored and saved
train: G:\Personal\\yolo\datasets\boxing\images\train\e391b2d3__048eabe1-%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_202508281445096.jpg: corrupt JPEG restored and saved
train: G:\Personal\\yolo\datasets\boxing\images\train\ec26e83e__80d420a0-%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_202508281445094.jpg: corrupt JPEG restored and saved
AutoBatch: Computing optimal batch size for imgsz=640 at 60.0% CUDA memory utilization.
AutoBatch: CUDA:0 (NVIDIA GeForce RTX 4060) 8.00G total, 0.10G reserved, 0.06G allocated, 7.83G free

开始对模型进行训练,可以看到最后输出了模型训练的pt文件,并且告诉了我们训练过程的可视化结果的保存路径

txt 复制代码
optimizer: AdamW(lr=0.002, momentum=0.9) with parameter groups 57 weight(decay=0.0), 64 weight(decay=0.00053125), 63 bias(decay=0.0)
Image sizes 640 train, 640 val
Using 8 dataloader workers
Logging results to runs\detect\boxing4
Starting training for 10 epochs...
Closing dataloader mosaic

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
       1/10      1.77G      1.732       3.44      1.523         33        640: 100% ━━━━━━━━━━━━ 1/1 1.8it/s 0.5s
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 1/1 9.4it/s 0.1s
                   all          2          6       0.01          1       0.03     0.0108

      Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
       2/10      1.77G      1.799      3.402      1.651         32        640: 100% ━━━━━━━━━━━━ 1/1 7.7it/s 0.1s
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 1/1 18.3it/s 0.1s
                   all          2          6       0.01          1     0.0299      0.011
...
10 epochs completed in 0.006 hours.
Optimizer stripped from runs\detect\boxing4\weights\last.pt, 6.2MB
Optimizer stripped from runs\detect\boxing4\weights\best.pt, 6.2MB
Validating runs\detect\boxing4\weights\best.pt...
Ultralytics 8.3.186  Python-3.11.13 torch-2.6.0+cu126 CUDA:0 (NVIDIA GeForce RTX 4060, 8188MiB)
Model summary (fused): 72 layers, 3,005,843 parameters, 0 gradients, 8.1 GFLOPs
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 1/1 58.2it/s 0.0s
                   all          2          6       0.01          1     0.0323     0.0141
Speed: 0.5ms preprocess, 5.1ms inference, 0.0ms loss, 1.6ms postprocess per image
Results saved to runs\detect\boxing4
Training completed.

然后我们执行了

python 复制代码
def val_model(model):
    print('Validating model...')

    metrics = model.val()
    
    return metrics

模型开始对验证数据集进行了验证,会看到以下的日志输出,可以看到验证可视化输出的结果

txt 复制代码
Validating model...
Ultralytics 8.3.186  Python-3.11.13 torch-2.6.0+cu126 CUDA:0 (NVIDIA GeForce RTX 4060, 8188MiB)
Model summary (fused): 72 layers, 3,005,843 parameters, 0 gradients, 8.1 GFLOPs
val: Fast image access  (ping: 0.10.0 ms, read: 2277.7136.5 MB/s, size: 1029.1 KB)
val: Scanning G:\Personal\智能零售\yolo\datasets\boxing\labels\val.cache... 2 images, 0 backgrounds, 0 corrupt: 100% ━━━━━━━━━━━━ 2/2 1842.0it/s 0.0s
val: G:\Personal\\yolo\datasets\boxing\images\val\431e150e__3197926a-%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_202508281445091.jpg: corrupt JPEG restored and saved
val: G:\Personal\\yolo\datasets\boxing\images\val\444deb1d__0a394335-%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_202508281445093.jpg: corrupt JPEG restored and saved
                Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100% ━━━━━━━━━━━━ 1/1 0.70it/s 1.4s
                  all          2          6       0.01          1      0.032      0.014
Speed: 0.8ms preprocess, 30.5ms inference, 0.0ms loss, 2.2ms postprocess per image
Results saved to runs\detect\boxing42

测试模型

我们现在可以通过YOLO来加载我们自己的模型对我们的测试图片进行目标检测

python 复制代码
  model = YOLO('runs/detect/boxing/weights/best.pt')

  results = model('datasets/boxing/images/test/微信图片_20250828163243.jpg')

  results[0].show()

可以看到还是检测出了目标,当然有些遮挡的目标没有识别出来我觉得可能是数据集太少的缘故

然后我们可以选择进行导出模型用于我们的部署

python 复制代码
from ultralytics import YOLO


def export_model(path):
    model = YOLO(path) 

    model.export(
        format="onnx",
        imgsz=640,
        dynamic=False,
        simplify=True,
        opset=12
    )

if __name__ == '__main__':
    path = 'runs/detect/boxing/weights/best.pt'
    export_model(path)

运行该脚本可以将之前的模型参数保存成一个onnx文件

总结:从数据到模型,我们走通了第一步

在本篇中,我们完整实现了使用自定义数据训练 YOLOv8 检测模型的核心流程

  • 数据准备 :将上一篇标注的数据整理为标准目录结构,编写 data.yaml 配置文件;
  • 模型训练 :基于 yolov8n 轻量模型,启用 Mosaic、MixUp 等增强策略,在小数据集上高效训练;
  • 验证与测试:通过 mAP、Precision、Recall 等指标评估模型性能,可视化检测结果;
  • 模型导出 :将训练好的模型导出为 .ptONNX 格式,为后续部署做好准备。

至此,我们不仅拥有了一个"看得懂"图片中目标的智能模型,更重要的是,走通了目标检测项目从数据到模型输出的完整闭环。这为后续的实际应用打下了坚实基础。

但这还只是开始------模型的价值,不在于它能否在本地跑通,而在于它能否被集成、被调用、被用起来。

🔮 下一篇预告:《YOLO 入门实战(三):用 FastAPI 构建模型推理服务》

相关推荐
自由的疯2 分钟前
Java 实现TXT文件导入功能
java·后端·架构
开开心心就好2 分钟前
PDF转长图工具,一键多页转图片
java·服务器·前端·数据库·人工智能·pdf·推荐算法
现在没有牛仔了5 分钟前
SpringBoot实现操作日志记录完整指南
java·spring boot·后端
小蒜学长9 分钟前
基于django的梧桐山水智慧旅游平台设计与开发(代码+数据库+LW)
java·spring boot·后端·python·django·旅游
l12345sy19 分钟前
Day16_【机器学习概述】
人工智能·机器学习
大千AI助手23 分钟前
InstructGPT:使用人类反馈训练语言模型以遵循指令
人工智能·gpt·语言模型·自然语言处理·rlhf·指令微调·模型对齐
文心快码BaiduComate23 分钟前
七夕,画个动态星空送给Ta
前端·后端·程序员
文心快码BaiduComate27 分钟前
早期人类奴役AI实录:用Comate Zulu 10min做一款Chrome插件
前端·后端·程序员
大象席地抽烟28 分钟前
Java异步编程的方式
后端
我在书社写代码29 分钟前
使用 React 和 Bun 构建的服务器端渲染(SSR)
后端·bun