ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

YOLO26训练自己的数据集?先搞定数据标注与格式转换

YOLO26训练自己的数据集?先搞定数据标注与格式转换 如果你打开YOLO26的源码仓库或者在网上刷到“yolo26改进专栏”的帖子大概率会先被结构图、C2f、注意力模块这些内容吸引。但我做了这么多年计算机视觉项目说句得罪人的话在YOLO26这类数据驱动的检测模型上真正拉开项目差距的往往不是谁的网络结构调得花哨而是谁的数据集和标注更扎实。一个标注质量参差不齐的数据集可以让再新的模型结构直接报废而一份规范、均衡、边界清晰的数据集哪怕用默认参数也能跑出让别人以为你偷偷改了什么黑科技的效果。这篇专题只聊一件事在YOLO26框架下怎么高效搞定数据集和标注。具体会覆盖公开数据集的查找与筛选、标注工具的选型和实操注意事项、VOC/COCO/YOLO三种标签格式的互相转换、标注质量控制的踩坑记录以及训练前数据划分和校验的完整流程。内容适合两类人一是计算机视觉大作业、毕业设计需要“YOLO26训练自己的数据集”的学生二是工作中要做人员入侵检测、x光安检物品检测、无人机或遥感图像目标检测等实际场景的工程师。前者能快速走通全流程后者可以对照着复盘自己数据集流程里到底哪一环在拖后腿。1. 训练YOLO26之前先把数据集的基本盘盘清楚很多人上来就找“yolo26源码下载”“yolo26环境配置”配置完环境就急着跑demo结果换成自己的数据后mAP掉得惨不忍睹然后开始怀疑是不是模型结构需要“yolo26改进”。我的经验是先别折腾模型回去检查数据。数据集的完整度、标注精度、类别分布、划分合理性这四样才是YOLO26落地的真正地基。1.1 YOLO26训练时到底在“读”什么数据先明确一个底层事实YOLO系列训练时使用的是YOLO txt格式的标签而不是直接在COCO的JSON或VOC的XML上训练。每张图片对应一个同名的txt文件文件名与图片文件名去掉扩展名后保持一致例如image_001.jpg对应image_001.txt。txt里每一行代表一个目标框格式是class_id x_center y_center width height这里的x_center y_center width height全部是归一化坐标也就是相对于图片宽度和高度的比例取值在0到1之间。举个例子一张宽1920像素、高1080像素的图片里某个目标框左上角在(480, 270)右下角在(960, 540)那么框宽度 960 - 480 480归一化后是 480 / 1920 0.25框高度 540 - 270 270归一化后是 270 / 1080 0.25中心x 480 480/2 720归一化后是 720 / 1920 0.375中心y 270 270/2 405归一化后是 405 / 1080 0.375最后txt里对应的行就是0 0.375 0.375 0.25 0.25类别id从0开始编号类别名和id的对应关系写在data.yaml文件里。这一步看起来简单但极容易出错。我见过不少人转换标签时忘了归一化直接把像素坐标塞进txt训练时loss直接飞掉还有人图片和txt不同名导致图片被当成无标签样本跳过。1.2 “公开数据集凑合跑”和“业务数据精标”的分界线如果你的场景是公开数据集就能覆盖的通用检测问题比如行人检测、车辆检测、日常物品检测那直接下载现成的VOC或COCO子集就够了不需要自己标。但如果你要做的是“x光安检物品检测数据集”这种带明显垂直场景属性的任务或者遥感图像里的特定目标无人机视角下的小目标检测那就别指望通用数据集能给你好的结果。公开数据集和业务场景之间往往存在三个差异成像视角不同、目标尺度分布不同、背景分布不同。同一个“人”在COCO里是平视街景在无人机数据集里是俯拍小目标模型迁移过去效果自然打折。1.3 先建立“数据基线”再谈模型改进我推荐的做法是任何项目开始前先把数据集做成一个干净基线。流程是收集图片 - 清洗坏图 - 标注 - 格式转换 - 可视化校验 - 划分数据集 - 用一个未经修改的YOLO26默认配置训练50轮。这个基线代表你数据集的天花板下限。如果基线结果差先不要改网络结构而是回看标注和划分如果基线正常再去做“yolo26改进”之类结构上的尝试。这样能避免把模型改进带来的收益和数据清洗带来的收益混在一起说不清是谁起了作用。2. 数据集从哪来公开渠道筛选与业务场景匹配合集明确需要什么数据后下一步就是解决“从哪搞到这批图片”的问题。2.1 常见的公开数据集来源先梳理几个高频渠道绝大多数计算机视觉方向的数据都能从这些地方找到雏形渠道说明适合场景COCO官网数据集80类日常物体标注质量极高通用目标检测、预训练、对比实验VOC数据集20类经典但年代久远教学、基础训练、Pascal格式练习Roboflow Universe社区上传的海量数据集包含x光安检、无人机、遥感等垂直领域快速找垂直场景数据、YOLO格式直接下载Open Images谷歌维护图片量大、类别多但部分标签噪声偏高大规模预训练、类别丰富的任务Kaggle数据集各类竞赛和论文复现数据特定竞赛任务、论文实验Roboflow Universe是我找垂直数据时最常逛的地方。搜“x-ray baggage”这类词能直接找到已经整理成YOLO格式的安检数据集搜“aerial detection”能找到大量无人机视角的图像数据。它的好处是很多数据集已经划分好了train/valid/test且自带标注。但要注意每个人的标注标准不一样不能盲目相信来源尤其是做论文或商用项目时需要抽检一部分数据确认边界框标准和类别定义是否靠谱。2.2 垂直场景数据集怎么选结合我实际做过的项目几个常见场景的数据集选择建议如下人员入侵检测优先找监控俯视角、园区周界场景的数据集。重点看图片里人的尺度分布是否包含远处的小目标。如果数据集里全是近景大尺寸目标训练完部署到实际园区会发现远处漏检率很高。x光安检物品检测网上搜到的多是“vocyolo”混合格式的标注数据拿到手后需要先统一转换。安检图像是灰度透明度叠影和自然图像差异极大强烈建议用专门数据集Fine-Tune不要直接用ImageNet预训练权重不做任何适配。遥感图像目标检测遥感图片往往是超大图比如8000x8000以上直接丢进YOLO26会爆显存需要滑窗切图。标注时还要注意方向和密集排列有时需要用到带角度检测框。这类场景更推荐先做切图再训练。无人机视角数据集数据来源常是高空拍摄目标是车辆、行人、船只等普遍问题是目标小、密度高。选择数据集时优先看是否有大量小目标而不只是总目标数量。2.3 拿到任何数据集后的“验货清单”我从GitHub或社区下载一个数据集后不会急着训练而是先按清单检查是否包含类别说明文件类别列表和标注文件里的class_id是否一一对应少一个都可能导致标签串位。图片尺寸是否统一长宽比差异过大的数据在resize时会引入严重形变。是否存在损坏图片或非图像文件比如下载中断遗留的0字节jpg。标注框是否超出图片边界YOLO在训练时会忽略或报错这类样本需要修正。图片文件名是否有空格、中文、特殊字符很多训练框架在读取路径时对中文支持并不友好轻则警告重则中断。标注里有没有空的txt文件如果一张图片应有目标但txt为空可能是导出时出问题。这些检查看着繁琐但能省下调试事故的几小时。尤其是跑训练到一半才发现标签有问题那种体验感很折磨。3. 数据标注工具横评与实操细节如果公开数据集覆盖不了你的场景那就得自己做数据标注。现在标注工具已经非常成熟没必要自己写前端但工具之间的差异需要知道自己踩在哪。3.1 主流工具怎么选工具是否开源标注界面协作能力推荐场景CVAT开源支持自部署Web端多人协作、任务分配强中大型团队、复杂标注项目Label Studio开源支持自部署Web端多用户图像、文本、音频多模态统一平台makesense.ai开源纯前端网页直接打开单机为主初学者、快速处理小批量图片X-AnyLabeling开源桌面应用单人利用SAM模型辅助自动分割标注Roboflow Annotate在线服务Web端云端协作与Roboflow数据集平台深度绑定如果你是一个人做毕设或小项目图片量在几百张以内直接打开makesense.ai就能干活不需要部署服务。如果图片量上千且需要多人协作建议花半小时把CVAT用Docker部署起来长期看非常值得。如果你的任务需要标注分割掩码X-AnyLabeling这类带SAM辅助的工具会减少大量鼠标手绘操作。YOLO26虽然以检测框为主但部分变体也支持实例分割选择工具时提前确认导出格式能否覆盖你后续要做的任务。3.2 CVAT实操中容易被忽视的几个细节CVAT很大这里只提炼几个最影响下游使用的点创建label时一定要保证name和id的一致映射。CVAT允许给label设置多个属性导出YOLO格式时label的顺序直接影响class_id。如果你先增删改过标签列表再导出务必检查一遍导出的obj.names或标签顺序。我就在这上面栽过前期用“person”和“car”训练后期为了统一命名把“car”改成“vehicle”结果导出的模型类别顺序变了重新训练时旧模型和label文件对不上。CVAT有AI辅助跟踪功能适合视频连续帧标注。标一帧后让模型自动跟踪再手动修正跟踪漂移效率能提升好几倍。但要注意视频里目标的外观变化如果过大自动跟踪容易脱靶漏标或错标后直接复制到后续帧会批量制造错误标签。所以用自动跟踪后还是要抽帧复核。导出格式选择YOLO 1.1时CVAT会把标签文件压缩包发给你。解压后可以看到每个标签文件单独放置这没问题但需要把标签文件全部移动到与图片同级的labels目录里再配合YOLO框架目录结构使用。3.3 makesense.ai的轻量用法makesense.ai是一个纯浏览器标注工具不需要安装打开网页导入图片就能标。选“Object Detection”后创建标签并开始画框。这个工具支持自动保存到浏览器本地也可以导出VOC XML、COCO JSON和YOLO txt格式。它比较适合那种临时标注几百张图片、不想为标注工作配置任何环境的场景。但它有个明显短板不支持多人协作数据全在本地浏览器里换电脑就断档。而且图片量很大时页面会卡顿。所以我的习惯是尝试性验证用makesense.ai真正做项目用CVAT或Label Studio。3.4 Label Studio图像标注要注意的设置Label Studio是个多模态工具做文本、音频标注也很方便。用它做图像目标检测时影响后续转换的一个关键点在于Label Studio底层标签结构是“区域”的概念导出为COCO格式以后有些时候类别映射需要自己在代码里额外处理。不要以为导出的JSON一定符合COCO官方规范实际使用中可能需要你写一个转换脚本对id、category_id重新编号。这一点项目里有严格格式依赖时需要提前评估好工作量。当然Label Studio平台本身非常值得学尤其是课程作业或论文实验用了一个晚上部署好接下去标注效率确实比某些老式工具高。它的画像、重叠区域、标签嵌套功能也很适合复杂标注场景不只是画检测框那么简单。4. 标签格式互转VOC、COCO与YOLO txt之间的桥标注完成后你很可能拿到的是VOC的XML或COCO的JSON而YOLO26训练需要的是txt。格式互转绕不开下面直接给出我用过的转换逻辑和一份可直接套用的代码。4.1 三种格式的核心差异先讲清楚VOC格式是一个XML文件对应一张图标注信息写在objectbndbox标签内如下annotation filename000001.jpg/filename size width1920/width height1080/height depth3/depth /size object nameperson/name bndbox xmin100/xmin ymin150/ymin xmax300/xmax ymax450/ymax /bndbox /object /annotation这个坐标是像素坐标左上角和右下角。COCO格式是一个大JSON文件汇总所有图片的信息常用两种核心字段images里存图片id、宽高、文件名annotations里存每个标注框的bbox和category_id。注意COCO的bbox是[x, y, width, height]其中x、y是框左上角坐标而不是中心点。这就是换到YOLO格式时最容易算错的点必须分清楚。YOLO txt前面已经说了是class_id x_center y_center width height全部归一化。三者转换靠的就是坐标系数换算。4.2 一份可直接复用的VOC XML转YOLO txt脚本下面的脚本基于我平时的工作流简化而来。如果你想直接跑把xml_dir改成你的XML文件夹txt_dir改成输出文件夹然后准备一个classes.txt每行一个类别名顺序从0开始。import os import xml.etree.ElementTree as ET def voc_xml_to_yolo_txt(xml_dir, txt_dir, classes_file): os.makedirs(txt_dir, exist_okTrue) with open(classes_file, r, encodingutf-8) as f: classes [line.strip() for line in f.readlines() if line.strip()] class_to_id {name: idx for idx, name in enumerate(classes)} for xml_name in os.listdir(xml_dir): if not xml_name.lower().endswith(.xml): continue xml_path os.path.join(xml_dir, xml_name) tree ET.parse(xml_path) root tree.getroot() # 图片宽度和高度在size节点里YOLO归一化必须用这个真实尺寸 size root.find(size) width int(size.find(width).text) height int(size.find(height).text) txt_name os.path.splitext(xml_name)[0] .txt lines [] for obj in root.findall(object): name obj.find(name).text if name not in class_to_id: print(f[跳过] {xml_name} 中出现未定义类别: {name}) continue class_id class_to_id[name] bndbox obj.find(bndbox) xmin float(bndbox.find(xmin).text) ymin float(bndbox.find(ymin).text) xmax float(bndbox.find(xmax).text) ymax float(bndbox.find(ymax).text) # 防止裁剪导致负数坐标 xmin max(xmin, 0) ymin max(ymin, 0) xmax min(xmax, width) ymax min(ymax, height) if xmax xmin or ymax ymin: print(f[警告] {xml_name} 存在无效框已忽略: {name}) continue x_center (xmin xmax) / 2.0 / width y_center (ymin ymax) / 2.0 / height box_width (xmax - xmin) / width box_height (ymax - ymin) / height lines.append(f{class_id} {x_center:.6f} {y_center:.6f} {box_width:.6f} {box_height:.6f}) with open(os.path.join(txt_dir, txt_name), w, encodingutf-8) as f: f.write(\n.join(lines)) if __name__ __main__: voc_xml_to_yolo_txt( xml_dir./annotations/voc_xml, txt_dir./annotations/yolo_txt, classes_file./classes.txt )脚本里做了三件容易出错但常被忽略的事跳过未定义类别、把越界坐标裁剪回图片边界、过滤掉宽高为0的非法框。这些防御性逻辑看着不起眼却能避免训练中断或精度异常。4.3 COCO JSON转YOLO txt的关键代码分段COCO转YOLO时需要先建立图片id到宽高的映射再遍历annotations。因为COCO标注的bbox是左上角坐标加宽高所以中心点坐标要自己计算import json import os def coco_json_to_yolo_txt(json_file, output_dir): os.makedirs(output_dir, exist_okTrue) with open(json_file, r, encodingutf-8) as f: coco json.load(f) image_id_to_info {} for img in coco[images]: image_id_to_info[img[id]] { file_name: os.path.splitext(img[file_name])[0], width: img[width], height: img[height] } # 按图片id聚合所有目标框 anns_by_image {} category_id_map {} for cat in coco[categories]: category_id_map[cat[id]] cat[name] for ann in coco[annotations]: image_id ann[image_id] anns_by_image.setdefault(image_id, []).append(ann) for image_id, info in image_id_to_info.items(): width info[width] height info[height] txt_path os.path.join(output_dir, info[file_name] .txt) lines [] for ann in anns_by_image.get(image_id, []): category_id ann[category_id] bbox ann[bbox] # [x, y, width, height] x, y, bw, bh bbox x_center (x bw / 2.0) / width y_center (y bh / 2.0) / height bw_norm bw / width bh_norm bh / height # 如果你的数据集categories id不是从0开始连续这里要重映射 # 下面默认category_id本身可以作为class_id使用 lines.append(f{category_id} {x_center:.6f} {y_center:.6f} {bw_norm:.6f} {bh_norm:.6f}) with open(txt_path, w, encodingutf-8) as f: f.write(\n.join(lines)) # 打印类别映射表供核对 print(类别映射:) for cat_id, cat_name in category_id_map.items(): print(f {cat_id}: {cat_name})此代码有一个前提你拿到COCO JSON里的category_id正好和你想用的YOLO class id一致。但真实项目里往往不一致例如原数据集的类别id从1开始中间还有缺失或很多无用的“背景”类别。遇到这种情况建议先建立一层映射表把所有类别按字母顺序重新排序再按新id写txt。4.4 转换完成后必须做可视化验证转换脚本输出的txt人眼无法直观判断框是否正确。我强烈建议你写一个可视化脚本把标签框叠回图片上肉眼抽查100张。如果框和图片目标对不上不是转换问题就是原始标注本身有问题。一个最简单的方式是直接用OpenCV画框。读取图片按行解析txt把归一化坐标还原成像素坐标然后用cv2.rectangle画出来保存到result文件夹。重点抽查目标密集的小图、边缘目标、宽高比极端的目标这几类出问题的概率最大。如果抽查结果不对不要急着训练尽早定位是转换部分还是标注部分的问题。5. 标注质量控制决定模型上限的隐形环节我见过很多团队在标注工具、格式转换上花了不少时间却忽视了标注质量是一个动态产品。好的标准不是“画个框就行”而是整套规则的一致性和可复核性。5.1 边界框的四个常见画法错误把一千个人叫来给同一张图标注大概率能产出五花八门的框。常见错误集中在四个方面第一框太松。目标实际边缘只占边界框面积的70%剩下30%全是背景。这类噪声会让模型学到“目标周围带着背景也正确”。当你的测试集和训练集标注习惯一致时指标不低但部署后发现模型定位偏大就是这类标签潜移默化的影响。第二框太紧。目标被截断比如人头部或车尾部被切掉一截。检测框裁剪到了目标主体内部模型很难学到完整的特征边界后续用小目标验证时更明显。第三框没完全包住目标或者目标只有一部分在框内这叫漏标部分但不误标。尤其两个目标重叠时很多标注员只画了暴露在外的那部分导致被遮挡目标丢失大块信息。第四包含背景过多。这在“人拿包”“人骑车”这类复合目标上最典型有的标人有的标人与自行车整体有的框包了整个交互场景。标注规则不定清楚模型预测时就会混乱。我没有通用的万能框定义但给出一个适用性很广的标准框贴住目标可见部分的视觉外轮廓既可以把所有可见像素包进去又不留太大背景目标有遮挡时只标可见部分不猜测被遮住的形状。但这个标准在不同任务里可以调整关键是“写下来让组里所有人都遵守”。5.2 类别混淆的边界案例如何统一口径数据标注里最让人崩溃的不是画框而是“这个东西到底算哪一类”。例如x光安检图片里一个打火机出现在背包中边界模糊再比如行人和骑电动车的人检测模型到底该输出“person”还是“motorcyclist”如果数据集的category定义来自COCO的“person”那么骑车上的人和车上载的货物如何切分我的做法是在标注开始前为每个容易混淆的类别写一份“决策表”。比如当人骑在自行车上时是标注人形外接框还是“人自行车”两个独立框如果目标被遮挡超过50%是继续标注还是跳过去一个物体的剪影和另一个物体重叠是各画各的还是只画上层物体写不清楚的规则不同标注员就会用自己直觉行动后续清洗时只能摔盘子。5.3 遮挡、截断、模糊样本的标注约定越是“难样本”对模型泛化价值越大。但在标注层面难样本也最容易制造不一致。我的约定一般是三点一是被遮挡目标尽量标可见区域不猜测被遮住部分。这样做的原因是如果两个标注员对被遮挡部分的猜测不一致模型收获的是完全不同的监督信号而预测时模型本来也看不到被遮挡区域标注可见部分反而更合理。二是图片边缘截断的目标不能漏标。很多标注员习惯忽略图片边缘的目标导致后面训练数据里“边缘出现目标的概率”被低估部署时边缘目标漏检变多。为了避免这种问题可以在标注规范里明确要求不能跳过边缘截断目标。三是对严重模糊、已经无法靠人眼判断类别的目标宁可放弃也不标错。标注错误比漏标对模型伤害更大因为模型把它当正确样本学习学到的是误导信息。另外如果条件允许最佳实践是拿出一部分图片让两个标注员分别标注然后计算标注一致性。这个指标能很直观反映你的标注规范是否清晰。两轮操作下来再统一训练标准后面的返工率会低很多。5.4 多人协同时必须做阶段性抽检假设你带着5个人一起标别等到全部标完再去质检。正确节奏是第一天每个人都标10张先不开工拉会讨论彼此的框差异跑一轮过堂把有分歧的图亮出来再写第二版规范。之后每完成500张随机抽50张进行交叉复核。交叉复核不需要复杂后台就可以用最朴素的方式导出两张图的标签人工对比。我在实操中会用一个小脚本统计每张图的框数量凡是框数量为0或异常多的图片都挑出来人工确认。“异常多”一般定义为超同批次图片均值的3倍标准差。这个统计逻辑虽然粗糙却能快速发现大批量漏标。6. 数据划分、增强与第一次训练前校验标注也完活了标签格式也转换了训练前还有最后几道工序数据集划分、目录组织、标签可视化复查和首次训练配置。6.1 训练集、验证集、测试集怎么分才不“打架”YOLO26训练需要train、val文件夹测试集建议单独留一份或至少留出没参与过任何调参的图片。划分比例我习惯用8:1:1数据量过小时用9:0.5:0.5但必须保证验证集里能看到各类别的代表性样本。划分时的关键约束是不能随机乱分要在“类别”维度保持均衡。如果某个小众类只出现在10张图里而这10张图全被划到训练集验证集里这个类就永久缺席反之全划到验证集训练学不到这种类别。简单做法是用分层抽样保证train/val/test中的类别分布与整体接近。写个简易脚本import os import random import shutil random.seed(42) img_dir images_all txt_dir labels_all train_ratio, val_ratio 0.8, 0.1 img_names [f for f in os.listdir(img_dir) if f.lower().endswith(.jpg)] random.shuffle(img_names) train_n int(len(img_names) * train_ratio) val_n int(len(img_names) * val_ratio) splits { train: img_names[:train_n], val: img_names[train_n:train_n val_n], test: img_names[train_n val_n:], } for split, names in splits.items(): os.makedirs(fimages/{split}, exist_okTrue) os.makedirs(flabels/{split}, exist_okTrue) for name in names: src_img os.path.join(img_dir, name) src_txt os.path.join(txt_dir, os.path.splitext(name)[0] .txt) shutil.copy(src_img, fimages/{split}/) shutil.copy(src_txt, flabels/{split}/)这个脚本没有做类别分层数据量比较大的时候问题不大数据量小但类别不均衡时建议用sklearn的train_test_split(stratifyy)按图片主类别分层先计算每张图的最频繁类别再以这个类别为分层依据。6.2 数据增强什么时候开Mosaic什么时候关掉YOLO系列默认会开启Mosaic增强把4张图拼接成一张训练。这在数据量大、目标多样时能大幅提升泛化能力但对某些任务却有害。举个典型的例子在遥感图像或x光安检图像里目标尺寸整体比较小且分布规律Mosaic强行拼接出来的24等分图跟你实际推理时的原图分布严重不一致反而干扰学习。所以我的建议是第一个基准实验先用YOLO26默认增强参数跑一遍观察loss和mAP曲线。如果训练loss能正常下降但val mAP振荡剧烈尤其小目标类别AP极低可以尝试把Mosaic关闭或者在训练后期关闭Mosaic。在部分具体实现里可以设置mosaic0.0关闭close_mosaic10表示最后10轮关闭。无论如何增强策略要服务于场景不能为了开增强而开增强。6.3 训练前跑一个“数据检查脚本”训练启动前的最后一个保险是跑一遍数据检查。我的检查包括这些内容每个txt文件是否都能在images中找到同名jpg且一一对应。图片和标注的宽高是否一致很多问题来自标注时的分辨率与训练时的分辨率不一致尤其缩放后没有更新归一化坐标。标签中是否存在class_id越界比如classes.txt只有3类但txt里出现了class_id 5。每张图片至少包含一个目标排除全背景图。检查脚本逻辑简单这里不贴完整代码但强调一点你看到“所有图片都有匹配标签”并不代表万事大吉还要再验证可视化叠框最好抽一个批次直接看。我就是因为少做这一步把COCO里带iscrowd1的标注也转进了YOLO txt导致正样本里混入大量群体聚集的“伪单目标”训练出来的模型对密集人群一个都框不准。6.4 第一次训练启动后观察什么指标启动YOLO26训练后不要只盯mAP或者loss数值。我更关心的是以下三个信号一是训练loss和验证loss的gap。如果训练loss持续下降、验证loss不降反升大概率开始过拟合先停轮或加大数据增强不要急着调模型结构。二是各类别的AP曲线。当成箱图看哪几个类别AP极低基本都是数据量的锅先确认该类的训练样本数是否明显偏低哪几个类别AP还行但框偏移明显往往说明标注框贴合度不统一。三是把验证集上的预测结果可视化出来。具体做法是随便抽几十张图把预测框画出来看错在那里。错检类型比mAP数值更能暴露数据问题如果模型总把货车预测成轿车那可能是类别定义里“货车”和“轿车”的边界本来就没写清如果模型漏掉了图片边缘的小目标就要审视边缘截断样本的标注覆盖。7. 复盘几个“训练自己的数据集”时反复出现的坑这部分不写教程只谈我踩过或者看别人反复踩的坑就当是给你打个预防针。先说说公开数据集格式的假象。你在Roboflow上直接下载的YOLO格式压缩包看起来已经很标准。但Roboflow的划分甚至会按照它自己的逻辑把同一视频连续帧都塞进训练集导致验证集几乎没难度。这个数据泄露问题在网络公开数据集里特别普遍你拿到的验证结果不是真实水平。强烈建议自己重新划分一遍保证同一目标或相邻帧不会同时出现在训练集和验证集。第二个高频坑是类别命名顺序随意变更。有些人今天用中文名明天改成英文名或者类别列表排序一换老模型就废了。YOLO的class_id其实没有语义它只是索引真正要紧的是这个索引在data.yaml、classes.txt、标签文件夹和推理脚本四处的顺序保持一致。我自己的惯例是给每个版本项目建一个classes.txt作为唯一事实任何脚本都从它去读类别顺序不再手动维护第二份。第三个坑是小数据集硬上大模型。YOLO26并没有比yolov8有压倒性的暴力提升核心依赖还是数据量。如果只有三四百张图先别急着追求结构老老实实做数据增强或者先拿轻量版本跑通流程确认数据没问题再换大模型。否则你改了一堆“yolo26改进”模块结果训练一抖过拟合根本说不清是模块的问题还是数据太少的问题。第四个坑是忽略类别不均衡。比如“人员入侵检测”里行人类占了总框数的95%那么即使总AP高也只能说明大类别学好了。我一般会打印每类别的框数量分布如果某个类占比低于5%先考虑补数据或做类别重采样而不是指望模型自己神奇地学会长尾类别。还有一个比较少人提但影响很大的坑图像Exif方向信息。手机拍摄或部分相机导出的图片会带旋转元数据数据加载库在解码时有的自动旋转有的不自动。一旦同一张图片在标注工具里是正的训练时被转成了旋转过的标注坐标就完全错位。我处理图片的第一步就是统一把图片转正后另存去掉Exif旋转信息后续所有环节都不用担心方向不统一。最后再提醒一下时间规划。不少人做计算机视觉项目时把80%时间都花在调模型上留了两天收集和标注数据。这个时间分配完全反了。以我自己的经验一个数据集的质量最终决定项目80%的上限而这个质量靠的是时间堆出来的收集、清洗、规范标注、质检、转换、抽样复查每一步都不快但每一步都有价值。第一次做YOLO26训练自己的数据集预留的时间要足够在“标注环节”返工一到两次。把数据这块磨扎实了后面的模型训练和效果优化反而会很顺利。
返回列表