
前阵子有位读者拿着训练好的模型来问我为什么同一份测试视频别人用 YOLO26 可以做到接近实时的稳定检测自己的模型却动不动漏检、误检是不是要把网络结构再改一改我看了他发的截图先没聊结构而是让他把训练集里抽 20 张图片和标注框导出来看一眼。结果问题很清楚目标框普遍偏大、边缘切到了背景还有一小部分样本的类别标反了。这其实是我特别常见到的现象——很多人把调参和改模型当成重点却忽略了更根本的数据和标注。所以这次想把“YOLO26 数据集与标注”这个环节单独拎出来写一篇。YOLO26 作为新一代 YOLO 系列模型大家对它的结构、优化器和部署方式讨论得很多但是真正落到自己训练时最难的不是把环境配好也不是把 yaml 模型配置跑通而是喂给它的数据集是否干净、标注是否可信、划分是否合理。这篇文章会从数据集选型、采集自采、标注工具、格式换算、目录结构、数据划分到特殊场景把一条路走完基本能覆盖大多数要训练自己 YOLO26 模型的开发者需求。1. 模型的天花板有一半在数据YOLO26 也不例外1.1 一个让我印象深刻的“人员入侵检测”咨询案例先说一个真实场景。有人想用 YOLO26 做一个园区的人员入侵检测项目一开始图省事直接拿 YOLO26 官方预训练权重跑视频 demo在办公室里的效果相当不错。后来把同一套权重部署到园区俯视摄像头画面里漏检率暴涨晚上开了低照度模式之后几乎隔几帧就丢一次人。问题出在哪里不是 YOLO26 不够强而是预训练阶段它见到的人大多是日常视角、日常光线下的完整人体。园区摄像头的角度是自上而下俯视画面里经常只有头肩区域夜间是红外成像的灰白画面目标尺度又小。这些分布差异靠一个预训练模型是盖不住的必须用贴近真实部署场景的数据重新训练。换句话说YOLO26 的骨干网络只是个“容器”数据集决定它到底能学会什么东西。我经常跟人说一句话模型的能力上限是数据给的训练只是在逼近这个上限。网络结构、训练技巧能决定你逼近得有多好但永远改变不了上限本身。所以当你发现训练结果不理想时不要先把锅甩给模型结构先怀疑数据。1.2 数据质量影响结果的三个典型层面我带过的项目里数据质量造成的问题基本可以归成三类问题类型典型表现排查方法域差距过大训练集效果好部署环境效果差统计训练图和真实场景的拍摄视角、光照、分辨率差异标注错误率高loss 降不下去验证集精度波动大随机抽图人工复核重点看边界框是否贴合、类别是否标反类别不均衡多数类表现好少数类几乎不检出统计每个类别实例数画柱状图看一眼就能发现这三种问题里域差距最隐蔽因为它不会让训练报错甚至训练集的 loss 可以降得很漂亮只有拿到真实场景里才会现原形。标注错误则直接影响优化过程——如果一个框大部分区域是背景模型就被反复教育“这个特征代表那个物体”自然学不干净。类别不均衡比较直接一两张可视化统计图就能看清。1.3 动手之前先把三个问题问清楚在开始找数据、标数据之前我建议先强迫自己回答三个问题任务到底要检测哪些类各种类是否经常同时出现单类检测和多类检测的数据要求差别很大。比如只需要检测“是否有人”那么所有其他东西都可以当背景标注的压力小很多如果是“人 车 宠物”还需要尽量平衡各类数量。部署环境是什么是俯视还是平视、室内还是户外、白天还是晚上、目标是小物体还是占据画面大半的大物体。这决定你要重点补哪些分布。你的评价指标是什么产品只关心误报率还是漏检率优先比如安全监控通常更怕漏检那对正样本的采集和标注就要更加严格。这些问题想清楚之后数据集的规模、采集方向和标注策略才不会跑偏。2. 数据集从哪找公开资源与自采路线怎么搭2.1 几类能省下大量时间的公开数据集很多人一上来就想着自己拍图、自己标其实公开数据集如果选得巧能省下很多时间。以最常见的几类为例COCO 数据集官方提供 80 类通用物体检测是目前做通用检测训练、预训练首选的基准数据。很多人问“COCO 官网数据集怎么下”“COCO2017 数据集结构是什么样的”我建议直接看官方页面images 和 annotations 两个文件夹的分工很清晰一份数据可以转成多种模型需要的格式。它的结构和转换脚本基本是社区里的“标准教材”。Pascal VOC 数据集20 类虽然类别少但是标签是 XML 形式结构明白适合刚接触检测格式的人理解“一张图对应一个标注文件”的模型。垂直领域数据集比如 X 光安检物品检测数据集、无人机视角数据集、遥感图像数据集很多以 VOC YOLO 两种格式同时发布。这类数据集通常聚焦在某个特定任务内如果项目域刚好接近可以直接用。我自己就见过有人用“X 光安检物品检测数据集 vocyolo”来训练安检初筛模型效果起步就比通用数据集好很多。不过公开数据集有一个通病作者整理时的类别顺序可能很不统一有些人按字母排有些人按标注顺序排小写变大写、命名不一致也很常见。所以公开数据集下载下来先做一次统一格式处理再进训练流程别直接丢给模型。2.2 自采数据最关键的是覆盖“视角、环境、状态”三个变量如果公开数据集里实在找不到和你的部署场景相近的数据就只能自己采。自采数据最容易被忽略的是你在办公室楼下拍的样本不能代表部署现场的情况。“镜头视角标注台”这类工具概念越来越常被提到其实就是强调了视角在图像数据里的重要性。一台相机从高角度向下拍和从人眼高度平着拍模型看到的同一个物体会差很多。自采时我会刻意控制三个变量视角变量同一个目标要有不同方位、不同距离、不同俯仰角度的采样。环境变量白天、傍晚、夜间、逆光、顺光、室内灯光、户外阴天都要考虑。做夜间监控哪怕真实数据不好采也不能用白天图硬扛。状态变量目标是静止还是运动是单个出现还是成群出现有没有互相遮挡比如检测行人如果几乎所有样本都是目标站在画面正中、没有遮挡那么部署时遇到人群密集场景模型表现一定崩。数据量上我的个人经验是用一个相对保守的“起步线”单类目标检测最少先保证有 1000 个目标实例左右多类任务每个类别至少 300 到 500 个实例理想是 1000 以上。如果是做验证性的最小闭环先每类挑 200 到 300 张图跑通训练流程也可以但别指望这个量级上生产环境。2.3 先做最小数据集再迭代扩展以前我做一个新项目时会犯一个错误总想一次性把数据采完美再开始训练结果标了两周模型还是一张没训练。后来改成“最小数据集 快速迭代”的节奏效果好了很多。步骤是这样的先手工挑几十张代表性图片快速标注跑一个很小的 YOLO26 训练把 pipeline 跑通确认数据格式、配置文件和损失函数都正常然后看模型在验证集上犯的错再反过来补数据。这样做的好处是你在标注工作上不会盲目投入模型会告诉你“它需要看见什么”。这一点对项目时间紧张的人来说尤其重要。3. 标注工具选型与格式问题关系到你后面会不会返工3.1 个人快速标注makesense.ai 和 Label Studio 怎么选标注工具不用一开始就上重型平台。我个人经验是几十张到几百张的规模makesense.ai直接用浏览器打开就能用支持 YOLO 格式导出不需要部署。对只想快速验证的人来说它几乎没有学习成本导入图片、画框、导出文本文件十分钟能搞定。但如果你要标注的类别多、需要多人协作或者以后可能涉及到分割、关键点这类任务我还是建议从 Label Studio 或 CVAT 这类更完整的工具里选。Label Studio是一个标注平台它不止支持图像检测框文本、音频、图像分割都能做单机部署简单界面是 Web 的多人可以同时开账号。很多人提到“label studio 文本标注”实际是把它用于 NLP 数据标注反过来也说明这套工具的通用性。对你接 YOLO26 来说用它的图像标注模块就足够。小规模选型时有个建议留意导出格式能不能直接贴近 YOLO 需要的 txt而不是每次都从 COCO JSON 再转换。减少一次格式转换就少一次踩坑的机会。工具适合规模优势注意点makesense.ai数百张以内零部署、轻量、导 YOLO 格式直接项目和标签管理较弱Label Studio数百到数千张多模态标注、可多人需要安装配置略重CVAT数千张以上团队协作、视频标注、自动标注部署较复杂适合长期项目3.2 团队协作和视频抽帧标注建议直接上 CVAT如果是团队协作、数据量过千或者需要标注视频我非常推荐CVAT 标注工具。CVAT 的特点在于它把一个标注流程拆成了“任务—作业—复核”的结构可以给不同成员分配任务可以设置标签规范可以让一个人标、另一个人审。这样做本质上是把标注质量管控从“口头要求”变成“流程约束”。用 CVAT 的时候记得把标签列表提前固定成 yaml 里的 names 顺序。很多人没在意这一点标注界面里的标签顺序和后面训练配置里的类别顺序不一致导出的 txt 中“类别 0”在训练时变成了“人”训练出的模型会把人识别成车。这个错误我在项目里见过不止一次。CVAT 还有一个值得用起来的功能是自动标注。你可以拿一个已经训练过的 YOLO26 模型部署成自动标注后端先让模型在未标注图片上跑一遍生成粗标签再由人工修正。这个流程能把纯人工标注的时间缩短一半以上但对“自动标注的粗框还需要逐个检查”这件事不要心存侥幸否则标注错误会沿着错误数据一路传导到最终模型里。3.3 三个标注格式的换算必须手到擒来YOLO 系模型训练用的标签格式和 COCO、VOC 不同。项目里经常碰到的情况是你从公开数据集下载时拿到的可能是 COCO 格式的 JSON 或者 VOC 格式的 XML要训练 YOLO26 就得先转成 YOLO txt。换算规律其实很固定COCO JSON 里给出的坐标是x, y, width, height这个x, y是目标左上角的绝对像素坐标。VOC XML 里是xmin, ymin, xmax, ymax也就是左上角和右下角的绝对像素坐标。YOLO txt 里是class_id, cx, cy, w, h其中cx, cy是目标中心点的归一化坐标w, h是归一化后的宽高。从 VOC 转 YOLO 时核心操作是# 以 VOC 格式为例转换成 YOLO 归一化标签 x_center ((xmax xmin) / 2) / image_width y_center ((ymax ymin) / 2) / image_height box_width (xmax - xmin) / image_width box_height (ymax - ymin) / image_height最常见的坑是坐标没有用图像宽高做归一化或者xmax和xmin计算时顺序写反导致中心点跑到画面外面。通常转换完我会立刻写一个脚本把 txt 里的归一化坐标乘回图像宽高画框人眼抽查几张确认框的位置没问题再进训练。3.4 标注质检抽检比例不是随意定的标注做完一定不要直接开训。我见过太多“标完就训练训完发现数据不对回头改标注再训一遍”的无效循环。标注质检可以在训练前帮你省下两三轮重复时间。我的质检流程遵循一个简单原则越难判断的样本抽得越多。边界清晰的大目标抽检比例可以低一些5% 到 10% 即可。小目标、遮挡目标、目标互相贴近的图建议抽检 30% 以上。整个数据集标注完成后做一次全量可视化把它拼成一张大图看整体效果往往比逐张看更快发现问题。标注质量的检查重点有几个框边缘是否贴住目标边界、是否框入过多背景、类别是否混淆尤其是相似类别、有没有漏标。这几个问题对最终模型的影响程度比大部分人想象中大得多。4. YOLO26 训练数据集目录结构与 yaml 配置最容易翻车的地方4.1 一套能直接用起来的目录结构和标签格式YOLO26 的数据集组织方式和之前的 YOLO 版本一脉相承。我常用的目录结构是dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ ├── data.yaml └── README.mdlabel 目录下的每个 txt 文件名必须和 images 里对应的图片文件名完全一致扩展名不同没关系每行表示一个目标格式是类别编号 x_center y_center width height坐标都做了归一化。举个例子0 0.512345 0.623456 0.083210 0.154789如果图中没有目标txt 文件允许是空文件此时这张图就作为纯背景样本参与训练。这一点很多人不知道白白删了一批负样本反而降低了模型区分背景的能力。4.2 data.yaml 里最要命的是 names 顺序训练 YOLO26 时需要一个 yaml 配置文件这个文件看起来很简单但里面的错误往往是最隐蔽的。# data.yaml path: /path/to/dataset train: images/train val: images/val test: images/test names: 0: person 1: dog 2: bicyclenames字段的顺序必须和标签文件里每行开头的数字对应。如果标注工具导出时把“dog”的编号设置成了 0而这里把“person”设成了 0模型就会把狗当成人来训练最后推理时也是错乱的。建议所有环节只维护一份类别顺序文件标注前就把这个顺序绑定到标注工具里后面导出、训练都依赖同一份列表不要手工改。还有一点容易被忽略path字段到底写绝对路径还是相对路径。我的建议是写相对路径以data.yaml所在目录为基准这样整个项目目录移动到别的机器上也不容易出问题。团队协作时也避免出现“我这边能跑你那边跑不了”的情况。4.3 训练前用一个小脚本替你做数据完整性体检很多训练中途报错都和数据文件本身有关。我最常遇到的情况包括某张图片下载到一半损坏了、标注 txt 里有超出 names 范围的类别编号、坐标归一化后小于 0 或大于 1。这些问题与其等训练到一半报错再回头查不如在训练前用脚本统一检查一遍。下面这段脚本的思路可以直接抄import os from PIL import Image def check_dataset(images_dir, labels_dir, num_classes): errors [] for img_name in os.listdir(images_dir): stem, _ os.path.splitext(img_name) img_path os.path.join(images_dir, img_name) label_path os.path.join(labels_dir, stem .txt) # 1. 图片能否正常打开 try: with Image.open(img_path) as im: im.load() except Exception: errors.append(f图片损坏: {img_path}) # 2. 标签文件是否存在 if not os.path.exists(label_path): errors.append(f缺少标签文件: {label_path}) continue # 3. 解析标签内容 with open(label_path) as f: for line in f: parts line.strip().split() if not parts: continue cls_id int(parts[0]) if cls_id 0 or cls_id num_classes: errors.append(f类别编号越界: {label_path}: {line.strip()}) # 4. 坐标是否在0~1之间 coords [float(x) for x in parts[1:]] if any(c 0 or c 1 for c in coords): errors.append(f坐标越界: {label_path}: {line.strip()}) return errors errors check_dataset(dataset/images/train, dataset/labels/train, num_classes3) print(errors if errors else 数据集检查通过)跑完这个脚本再抽几张图叠加可视化数据侧面的基础问题就全部排掉了。养成这个习惯后面训练过程会顺很多。5. 数据划分、增强与迭代方法决定了训练效率5.1 数据划分最忌“同源泄漏”和比例失衡数据集划分看起来是分三个文件夹的事其实里面有很多讲究。最常见的问题发生在“视频抽帧”场景。假设你采集了一段连续视频每隔 5 帧抽一张图作为训练数据。如果直接把抽出来的帧随机打散后划分 train/val那同一段画面里的连续帧很可能一部分进了训练集一部分进了验证集。经过这种“偷看答案”式验证集验证出的精度会虚高等模型部署到真实的新场景时效果立刻打回原形。正确的做法是在抽帧时就要按“视频段”来划分。比如一共有 10 段视频可以约定前 7 段视频的帧全部进 train后 3 段视频的帧全部进 val确保验证集和训练集没有时间上的连续性重叠。静态图片场景则多注意不要让同一地点、同一角度拍摄的图片同源太多否则验证集的代表性也会打折扣。另外一个朴素但是重要的点是每个类别在 train 和 val 里的比例尽量保持一致。不能训练集里有 90% 的人、10% 的自行车验证集里却反过来。哪怕样本总量再大这个比例失衡也会让评估结果失真。5.2 增强策略不要照搬要看部署的场景YOLO26 训练默认会带不少在线数据增强包括马赛克、随机平移、翻转、色彩抖动这些。它们能提升通用性但要结合你的部署环境决定哪些增强该保留、哪些该减弱。举个例子。如果做的是依赖颜色特征区分的工业检测过强的色彩抖动往往是有害的会让模型把“颜色”当成不稳定因素而忽略。反过来如果做低光场景检测问题不在颜色而在亮度靠增强把图片调暗只是帮助学生“适应黑暗”真正的信息量不足还是补不回来更重要的还是增加真实低光样本。再比如旋转增强。对于水平视角的大目标检测小角度的随机旋转是有效的但如果你做的是无人机俯视或者园区远距离监控过大的旋转增强会让标注框与实际目标匹配失真。所以我现在的习惯是第一轮训练尽量保持官方默认增强等看到具体的 badcase再按错误类型去关闭或调低某一类增强而不是一开始就做一堆魔改。5.3 第一轮训练结束后先看错例再调参第一轮训练跑完很多人会急着看 mAP然后马上动手调学习率、改 anchor。我的建议是先别动这些拿出一部分时间做错例分析。具体操作是把 val 集里表现比较差的图片和对应的预测结果导出成一张张可视化图然后做三件事。看是不是标注错了。如果图里目标边缘明明很清楚可因为标注框把旁边另一个物体也包了进去导致模型学到一个“混合体”特征那再调参也没用乖乖去改标注。看是不是漏标了。有些目标模型检测出来了但在标注里被漏掉实际预测结果反而会被当成误检惩罚这会让 mAP 虚低。把漏标补齐模型精度可能立刻上来一轮。看是不是目标本身太小或太密。如果错例大多是小目标群那这不是超参能解决的问题需要考虑提高输入分辨率、做图像切片或者补一批近距离/大尺度的样本。按这个顺序修数据通常比闷头调超参见效快得多。我见过好几个项目调参调了一周都没突破最后回头补了标注、扩了错例数据精度立刻跳了两个点。这不是玄学是数据矛盾和优化方向被修正了。6. 低光、小目标、X 光安检数据集这些特殊场景的实战心得6.1 低光环境检测别指望增强能把黑夜变成白天很多人做低光环境检测时第一反应是“要不要先做图像增强把暗图调亮再输入”。我的经验是这类“画质修复”手段只适合人眼观察对检测模型来说未必划算。真实低光照相机里出现的噪点、红外成像的灰度分布、动态范围压缩都不是简单调亮度能模拟出来的。更务实的做法是直接采集一批真实低光数据把标注工作集中在那些“人眼勉强能辨认”的目标上。如果一张图在画面上已经完全看不出目标那标注人员的判断也会变得不稳定标出来的框往往带了大量猜测成分对训练不但无益还会引入噪声。还要特别留意摄像头的自动增益和红外切换。这类现象会造成目标在两种完全不同的视觉风格之间切换如果你只标了白天风格夜间的表现自然好不到哪里去。社区讨论里也有人把 YOLO26 和深度信息结合起来做低光场景即所谓 yolo26 depth 方向的尝试。它的基本思路是引入额外的深度通道或融合分支给模型在低光下更容易“定位”到目标的线索。但我个人认为光有模型侧的多模态仍然不够输入侧的数据分布依然要兜底。你的训练集里如果一张低光红外图都没有融合什么模态都白搭。6.2 小目标和密集目标先把图切了再说小目标的问题是“信息量不够”。一个目标如果只占整张图几百甚至几十个像素标注框只要差一两个像素对 IoU 的影响就很显著这也导致小目标数据集的标注质量普遍更难保证。我们经常看到“无人机视角检测”或“遥感图像标注”项目一大张 4K 图上分布着密密麻麻的小目标如果直接把整张图放进 YOLO26 训练下采样几轮后小目标几乎就没了响应。处理这种问题我有一个很土但很有效的办法离线切片。把大图切成若干 640×640 或 1280×1280 的 patch让目标在 patch 里相对变大再进行标注和训练。要注意切片时保留一定的重叠区域避免目标正好被切在 patch 边缘导致标注被截断。推理阶段也用同样方式切片预测再通过 NMS 合并结果对小目标的召回率会比直接缩放大图好很多。另外如果目标尺度跨度很大可以在目录里维护多尺度数据让同一目标既出现在小 patch 里也出现在大 patch 里。不要强迫一个模型用一个固定分辨率去通吃所有尺度那对数据集的要求太高了。6.3 X 光安检物品数据集的启发遮挡目标怎么定标注边界X 光安检物品检测数据集在这几年的讨论度一直很高很多朋友在训练这种带有 VOCYOLO 双格式的数据集时发现效果还行但一旦换到真实安检机数据就崩。仔细看样本会发现X 光图像里的物体彼此重叠、透视关系复杂一件物品被另一件挡住是常态。这种场景下的标注边界其实需要单独约定。我习惯的做法是标注时尽量把被遮挡物体的完整轮廓“脑补”出来而不是只标露出来的部分。原因很简单——模型要学习的不是一个“可见碎片”而是“这个物体在遮挡下仍然作为一个整体存在”的概念。你只标可见部分遇到新的遮挡方式框的边缘会对不齐模型会认为同一个物体在不同遮挡下是不同目标。这一点在行李箱里塞满物品的安检场景尤为明显。类似的经验可以迁移到所有目标互相遮挡严重的业务里比如货架商品检测、仓库堆叠物体检测。标注前先和团队定好“被遮挡目标的标注规则”比返工标注省出十倍时间。6.4 我最想强调的一件事数据也要闭环最后说一个项目里最有价值的习惯。很多团队把训练完成的模型部署之后就万事大吉但真实环境会不断产生新的数据分布变化。我现在的做法是给每个部署的模型配一个“badcase 回流”环节把线上检测置信度较低、或者漏检的图定期收集回来人工标注后补进训练集形成“数据—训练—部署—反馈—再训练”的闭环。这个机制长期运转下来模型在真实场景里的表现会越来越稳。很多人以为吃性能红利靠的是反复调参实际上数据闭环带来的提升往往更扎实。哪怕 YOLO26 之后还有新一代模型它依然需要高质量的数据来喂这个规律不会变。