4. YOLO训练数据准备:数据采集策略、数据清洗与标注规范

数据准备这件事,说难不难,说简单也真不简单。我见过太多同学花大把时间调模型参数,结果效果上不去,最后发现是数据本身出了问题。说白了,YOLO模型再强,也怕垃圾数据。这一章,我就把我在多个落地项目中积累的数据准备经验,掰开了揉碎了讲给你听。

4.1 数据采集策略:从源头把控质量

数据采集不是随便拍几张照片就完事了。你得想清楚:模型上线后要面对什么样的场景?

核心原则:采集的数据必须覆盖模型部署时可能遇到的所有变化因素。

4.1.1 多样性覆盖

我个人习惯把变化因素分成这几类:

变化维度 具体因素 举例说明
光照条件 强光、逆光、暗光、阴影 白天/傍晚/夜间,室内灯光/自然光
拍摄角度 俯视、平视、倾斜 无人机航拍 vs 手持拍摄 vs 监控杆
目标尺度 近景、中景、远景 行人占画面80% vs 占5%
遮挡程度 无遮挡、部分遮挡、严重遮挡 树丛后的车辆、人群中的行人
背景复杂度 简单、中等、杂乱 纯色墙面 vs 商场货架

我在做一个智慧零售项目时,客户只给了白天货架的照片。模型在实验室跑得挺好,一上线就崩了——晚上灯光一换,检测率直接掉到30%。后来我补采了不同时段、不同灯光下的数据,才把问题解决。你想想看,如果只采集理想环境的数据,模型就是个「温室里的花朵」。

4.1.2 数据量估算

很多新手会问:「到底要多少张图?」我的经验是:

  • 每类目标至少500张,这是底线
  • 复杂场景每类1000-2000张,效果才稳
  • 困难样本(遮挡、小目标)单独补充,至少占20%

我的小技巧:先采集少量数据(每类200张),快速训练一个baseline模型。然后用这个模型去检测未标注数据,把置信度低的样本挑出来人工标注。这叫「主动学习」,能帮你精准找到模型最需要的样本。

4.2 数据清洗:别让脏数据毁了你的模型

数据采集回来,别急着标注。先做一轮清洗。我曾经接手过一个项目,标注员把「猫」标成了「狗」,这种错误在训练集里一多,模型就学歪了。

4.2.1 清洗清单

  1. 去重:删除完全相同的图片,避免模型过拟合
  2. 去模糊:运动模糊、失焦模糊的图片直接扔掉
  3. 去异常:曝光过度、全黑、全白的图片
  4. 去无关:不包含任何目标的背景图(除非你专门做负样本)
  5. 格式统一:所有图片转成JPG或PNG,分辨率统一

注意:不要用有损压缩太狠的JPG图片。YOLO对小目标的检测很依赖纹理细节,压缩过度会让边缘模糊,小目标就检测不到了。

4.3 标注规范:统一标准才能出好模型

标注这件事,最怕「每个人都有自己的理解」。我见过一个团队,三个人标同一个数据集,框的大小、边界的贴合程度都不一样。模型训练出来,效果可想而知。

4.3.1 标注基本原则

原则 说明 错误示例
紧贴目标 标注框必须紧贴目标边缘,不留白 框比目标大一圈
遮挡处理 遮挡部分不标,只标可见部分 凭想象标出被遮挡的轮廓
截断处理 目标超出画面边缘,标到画面边界即可 不标截断的目标
类别一致 同一类目标用同一个标签名 「car」「Car」「vehicle」混用

4.3.2 YOLO标注格式

YOLO用的是归一化的坐标格式,每个目标一行:

class_id x_center y_center width height

所有值都归一化到0-1之间。举个例子:

0 0.5 0.5 0.2 0.3
1 0.8 0.6 0.1 0.15

这表示:类别0的目标中心在图片的(50%, 50%)处,宽占20%,高占30%;类别1的目标中心在(80%, 60%)处,宽占10%,高占15%。

避坑指南:我曾经犯过一个低级错误——坐标归一化时忘了除以图片宽高,结果训练时loss死活不降。检查了半天才发现坐标值都大于1。记住:所有坐标必须除以图片的宽和高。

4.4 标注工具:LabelImg vs CVAT

工具选对了,效率翻倍。我两个工具都用过,说说我的感受。

4.4.1 LabelImg

轻量级,安装简单,适合个人或小团队。

  • 优点:开箱即用,支持Pascal VOC和YOLO格式导出
  • 缺点:没有协同功能,标注效率一般
  • 适用场景:数据集小于5000张,单人标注

安装方式:

pip install labelImg
labelImg

4.4.2 CVAT

企业级工具,支持多人协同标注。

  • 优点:Web界面,自动标注(用预训练模型辅助),审核流程完善
  • 缺点:部署稍复杂,需要Docker环境
  • 适用场景:团队协作,数据集上万张

快速部署:

docker compose up -d

我个人建议:项目初期用LabelImg快速验证,数据量大了再上CVAT。别一上来就搭CVAT,万一项目黄了,白折腾。

4.5 数据集划分:训练/验证/测试

划分比例是个老生常谈的问题。我的经验是:

数据集 比例 用途 注意事项
训练集 70% 模型学习参数 必须包含所有变化因素
验证集 15% 调参、早停、模型选择 不能参与训练,不能泄露
测试集 15% 最终评估泛化能力 全程不能看,最后用一次

重要:划分时一定要做随机打乱,并且保证每个子集的类别分布与原始数据集一致。我习惯用scikit-learn的train_test_split配合stratify参数做分层采样。

代码示例:

from sklearn.model_selection import train_test_split
import os, shutil

# 假设images是所有图片路径列表,labels是对应的标签
train_imgs, temp_imgs, train_labels, temp_labels = train_test_split(
    images, labels, test_size=0.3, stratify=class_ids, random_state=42
)

val_imgs, test_imgs, val_labels, test_labels = train_test_split(
    temp_imgs, temp_labels, test_size=0.5, stratify=temp_class_ids, random_state=42
)

嗯,这里要注意:测试集是「圣杯」,只能在模型最终定稿后用来评估一次。如果你用测试集调参,那它就不再是测试集了,你的泛化能力评估就是假的。

4.6 本章知识体系

下面这张图总结了数据准备的整体流程,你可以对照着检查自己的项目:

YOLO训练数据准备流程 数据采集 数据清洗 标注规范 多样性覆盖 数据量估算 主动学习策略 去重 / 去模糊 去异常 / 去无关 格式统一 紧贴目标 / 遮挡处理 YOLO格式归一化 LabelImg / CVAT 数据集划分 训练集 70% 验证集 15% 测试集 15% 关键:分层采样保证类别分布一致,测试集只在最终评估时使用一次

数据准备这件事,花的时间越多,后面训练就越省心。我见过太多项目在数据上偷懒,最后在模型调优阶段花了几倍的时间来弥补。说白了,高质量的标注数据,比一个花哨的模型结构更重要。