尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

葡萄数据集YOLO训练实战:从标签解析到过拟合避坑指南

发布时间:2026/9/24 20:12:51

资讯中心
01
ARTICLE

葡萄数据集YOLO训练实战:从标签解析到过拟合避坑指南

葡萄数据集YOLO训练实战:从标签解析到过拟合避坑指南
简介面向YOLO系列目标检测的初学者与算法工程师这份葡萄图像数据集包含拣选点、斑点葡萄、腐烂葡萄、成熟葡萄、未成熟葡萄五类目标共165张已标注图像。数据集已完成训练集与验证集划分并附带可直接读取的data.yaml配置文件适用于YOLOv5、YOLOv7、YOLOv8、YOLOv9、YOLOv10、YOLO11等主流版本下载后即可开始训练和验证免去自行整理标注的繁琐流程。压缩包共496个文件包括165张jpg原图、165个txt格式的YOLO标注文件、165个xml格式的VOC标注文件以及1个yaml配置txt与xml两种标签格式同时提供便于在不同工具链间切换或做格式对照学习。YOLO标注格式中每行记录类别索引、目标框中心点归一化坐标以及宽高比例结构清晰非常适合用来理解目标检测标签的构造逻辑。整个资源仅13.85MB轻量易下载目前已有101人学习浏览可作为快速搭建葡萄检测项目的实用数据集。1. 葡萄数据集到手165 张图先别急着训这包料能干什么、不能干什么拿到这个包的第一反应是“才 165 张图五个类别能训出什么”。但解压后扫了一圈这包数据不是拿来拼精度的它是拿来跑通全流程的yolo 格式 txt 标签和 voc 格式 xml 标签双份齐全data.yaml 配置直接躺在根目录train / val / test 已经划分好喂给 yolov5、v7、v8、v9、v10、yolo11 都能直接开工。类别也很有意思不是简单的“葡萄/背景”而是按分拣场景拆成了拣选点、斑点葡萄、腐烂葡萄、成熟葡萄、未成熟葡萄五个细类标签粒度接近真实产线上的质检需求。适合两类人第一次训自己数据集、想搞明白 yolo 标签到底怎么组织的入门者以及需要一份规范双格式标注当模板拿去做果品分拣预研的工程师。指望这 165 张图训出能直接上产线的模型不现实但用它把数据体检、训练、验证、调置信度门限这一整条链路跑顺非常值。2. 目录结构与双标签格式拿到手先摸清 165 张图的家底2.1 目录结构与五个类别从文件名到标签 id这包数据解压之后的目录结构常见是这样组织的不同渠道打包习惯不一样以实际解压为准grape_dataset/ ├── data.yaml ├── images/ │ ├── train/ │ │ ├── img_0771_16.jpg │ │ ├── img_0964_30.jpg │ │ ├── ... │ ├── val/ │ └── test/ ├── labels_txt/ │ ├── train/ │ ├── val/ │ └── test/ └── labels_xml/ ├── train/ ├── val/ └── test/逻辑很清楚图像在 images 下txt 格式标签在 labels_txt 下xml 格式标签在 labels_xml 下三个子集各自成目录一一对应。图片命名是img_编号_序号.jpg这种风格同一个场景的多张图会共享前面一段编号实际操作里可以按这个规律反推哪些图来自同一批采集环境帮助判断训练集和验证集有没有泄露。五个类别的业务含义值得先说清楚这直接关系到后面怎么调参拣选点分拣流程中的操作参考点属于典型小目标框小、数量少最容易漏检。斑点葡萄果面有早期病斑或药斑特征弱、对比度低和干净果面容易混淆。腐烂葡萄颜色、纹理变化明显算是最好检的一类。成熟葡萄与未成熟葡萄按成熟度切分的双子类二者边界是渐变的标注本身就有主观性。从类别性质就能预判两个坑小目标拣选点和难分对斑点 vs 腐烂、成熟 vs 未成熟。数据量只有 165 张这两类问题会被进一步放大后面所有参数调整都绕不开这个前提。建议拿到手第一件事不是开训而是确认 data.yaml 里的 names 顺序——它决定了 txt 里每个数字对应哪个类别。cat data.yaml这个命令不用解释但它的输出你要逐行看。下面这张表是 data.yaml 里常见字段的解析方式我习惯把对应关系抄在笔记本上再往下走字段含义注意事项path数据集根目录相对路径时依赖运行位置跨机器要改train / val / test各子集图像路径要与实际目录结构一致names类别名列表列表下标就是标签 id顺序错了全盘皆错nc类别数量部分工具自动算缺失时手动补2.2 data.yaml训练边界的说明书data.yaml 就是这包数据的“施工图”。用 yolo 系列训练时ultralytics 框架启动后第一件事就是解析这个文件路径错了、names 顺序错了后面全白跑。下面是一份典型的 data.yaml 内容path: ./grape_dataset train: images/train val: images/val test: images/test nc: 5 names: 0: picking_point 1: spotted_grape 2: rotten_grape 3: mature_grape 4: immature_grape字段说明path是数据集根目录这里写的是相对路径意味着你执行训练命令时的工作目录必须和这个相对路径对上train / val / test是三个子集的图片目录相对 path 的路径nc是类别总数5names是类别名列表列表的下标 0 到 4 直接对应 txt 标签每行的第一个数字。注意一个关键点框架不会帮你校验 names 的顺序对不对它只会按下标取名字。如果你发现训练日志里类别名对不上实际内容先回来检查这个文件而不是怀疑模型。我一般拿到手会顺手跑一个命令确认路径是否存在避免训练到一半报 FileNotFoundErrorls -la images/train | head -20 ls labels_txt/train | head -20这一步能同时确认图片和标签目录都有内容还能扫一眼文件名前缀是否一致。文件名对不上是 yolo 训练最常见的“黑匣子报错”之一。2.3 yolo txt 与 voc xml 双格式并存为什么两份都留同一份标注同时给 txt 和 xml不是冗余是两种工作流的需要。labelimg 默认保存为 voc 格式的 xml人工复核、二次修框时用 xml 最顺手yolo 训练框架读取效率最高的是 txt 归一化坐标。两份都在意味着你可以直接用 labelimg 打开 xml 修完再转 txt不用重打标。对比看更直观annotation filenameimg_0964_30.jpg/filename size width1280/width height720/height /size object namemature_grape/name bndbox xmin412/xmin ymin230/ymin xmax618/xmax ymax405/ymax /bndbox /object /annotation对应的 txt 是3 0.40234375 0.44097222 0.16093750 0.24305556这里3是类别 id对应 data.yaml 里 names 的下标后面四个数字分别是归一化后的中心点 x、中心点 y、框宽、框高。python 里验算一遍就清楚了x_center (412 618) / 2 / 1280 # 0.40234375 y_center (230 405) / 2 / 720 # 0.44097222 width (618 - 412) / 1280 # 0.16093750 height (405 - 230) / 720 # 0.24305556逻辑说明把绝对像素坐标全部除以图像宽高得到 0 到 1 之间的比例值这样标签就和图像分辨率解耦了训练时无论输入 640 还是 1280都能直接换算回原图位置。参数说明如果 xml 里尺寸是 1280x720而你的训练 imgsz 是 640框架会自动等比例缩放不需要手动改 txt。双格式存在的另一个价值是txt 丢了可以用 xml 重新生成反过来也一样这相当于给你的标注数据上了双保险。3. 标签坐标换算与脚本体检yolo txt 不是画框画出来的3.1 五元组换算归一化坐标与像素坐标的来回yolo 标签每一行是五个数字class x_center y_center width height。很多新手以为这四个坐标是随便填的实际它们是归一化后的比例值。拿到 xml 要转 txt 时换算逻辑固定如下import xml.etree.ElementTree as ET def xml_to_yolo(xml_path, img_width, img_height, class_map): tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.iter(object): name obj.find(name).text if name not in class_map: continue cls_id class_map[name] box obj.find(bndbox) xmin float(box.find(xmin).text) ymin float(box.find(ymin).text) xmax float(box.find(xmax).text) ymax float(box.find(ymax).text) x_center (xmin xmax) / 2 / img_width y_center (ymin ymax) / 2 / img_height width (xmax - xmin) / img_width height (ymax - ymin) / img_height lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}) return lines逻辑说明先取框的绝对像素坐标算中心点和宽高再分别除以图像宽高完成归一化。class_map是类别名到 id 的映射字典必须与 data.yaml 里的 names 顺序一致这一步错了模型会拿“腐烂”当“成熟”训练而且不会有任何报错。参数说明img_width和img_height从哪里来可以直接读 xml 里size节点的值也可以用 PIL 打开对应图片获取。我个人倾向用 PIL 实时读原图尺寸因为有些打标工具写进 xml 的 size 和实际图片不一致留个心眼。反向换算同样常用。推理结果要画到原图上或者要算检测框的绝对像素面积时把归一化值乘回去就行def yolo_to_pixel(cls_id, x_center, y_center, width, height, img_w, img_h): x1 int((x_center - width / 2) * img_w) y1 int((y_center - height / 2) * img_h) x2 int((x_center width / 2) * img_w) y2 int((y_center height / 2) * img_h) return cls_id, x1, y1, x2, y2这里的核心思路是“中心点加减半宽高”得到左上和右下角点乘回图像宽高即还原绝对坐标。注意归一化值乘以宽高后要转 int但转 int 的时机要放在最后中间计算全程用 float否则累计误差会在小目标上放大——拣选点这类小框差几个像素就可能错位到相邻果粒上。3.2 脚本体检越界框、空标签与类别分布165 张图不算多但手工打标难免出错。我拿到任何 yolo 数据集的第一件事不是训练是跑一遍体检脚本。越界框、空标签、类别数量失衡这些问题都会在训练时变成莫名其妙的低 mAP。import os label_dir labels_txt/train img_dir images/train img_sizes {} # 先读所有图片尺寸 from PIL import Image for img_name in os.listdir(img_dir): if img_name.endswith(.jpg): img_sizes[img_name[:-4]] Image.open(os.path.join(img_dir, img_name)).size issues [] class_count {} empty_labels 0 total_boxes 0 for label_file in os.listdir(label_dir): if not label_file.endswith(.txt): continue stem label_file[:-4] if stem not in img_sizes: issues.append(f{label_file}: 对应图片缺失) continue img_w, img_h img_sizes[stem] with open(os.path.join(label_dir, label_file)) as f: lines f.readlines() if len(lines) 0: empty_labels 1 issues.append(f{label_file}: 空标签) continue for line in lines: parts line.strip().split() if len(parts) ! 5: issues.append(f{label_file}: 列数异常 - {line.strip()}) continue cls_id int(parts[0]) xc, yc, w, h map(float, parts[1:]) class_count[cls_id] class_count.get(cls_id, 0) 1 total_boxes 1 # 越界检查归一化坐标允许 -0.01 到 1.01 的容差 if not (-0.01 xc 1.01 and -0.01 yc 1.01): issues.append(f{label_file}: 中心点越界 xc{xc} yc{yc}) if not (0 w 1.01 and 0 h 1.01): issues.append(f{label_file}: 宽高异常 w{w} h{h}) print(f总框数: {total_boxes}, 空标签文件: {empty_labels}) print(f类别分布: {class_count}) print(f发现问题 {len(issues)} 条:) for item in issues[:30]: print( -, item)逻辑说明脚本先建图片文件名到尺寸的映射再逐行解析 txt 标签做三类检查——文件是否存在、字段是否完整、坐标是否越界。最后统计类别分布。参数说明越界容差给到-0.01到1.01是因为 labelimg 偶尔会画出微幅越界的框完全卡死 0 到 1 会误报。小越界可以容忍超过 1% 就建议回炉修正。类别分布那一行尤其值得看五个类别如果数量差一个数量级比如腐烂葡萄有 800 框、拣选点只有 40 框后面训练就得做类别权重处理否则大类会把 loss 整个带走。3.3 voc 转 yolo 兜底脚本双格式不同步时的后悔药txt 和 xml 两份标签并存最大的风险是某次人工修订只改了其中一份两份开始分叉。常见的做法是以 xml 为基准重新生成 txt或者写个脚本对比两侧的框数量数量不一致就报警。下面的函数是 xml 批量转 txt 的通用写法import os import glob from PIL import Image def batch_convert_xml_to_yolo(xml_dir, img_dir, out_dir, class_map): os.makedirs(out_dir, exist_okTrue) for xml_path in glob.glob(os.path.join(xml_dir, *.xml)): stem os.path.splitext(os.path.basename(xml_path))[0] img_path os.path.join(img_dir, stem .jpg) if not os.path.exists(img_path): print(f跳过 {stem}: 图片不存在) continue img_w, img_h Image.open(img_path).size lines xml_to_yolo(xml_path, img_w, img_h, class_map) if lines: out_path os.path.join(out_dir, stem .txt) with open(out_path, w) as f: f.write(\n.join(lines) \n) print(f转换完成输出目录: {out_dir})兼容性说明我在xml_to_yolo里通过class_map做了类别名过滤xml 里出现 names 之外的类别会直接跳过而不是报错这能避免脏数据打崩整个转换流程但跳过意味着丢框转换完务必对比一下总框数。我个人习惯是加一行统计打印把每个 xml 的框数和转换后的 txt 行数对上对不上就单独拎出来看。4. 训练避坑小数据集、类别不均衡与早停的取舍4.1 过拟合翻车train loss 一路掉val loss 从第 20 轮开始反弹现象训练日志里 train box_loss 和 cls_loss 在稳步下降看起来一切正常但 val loss 从第 20 轮左右开始掉头向上验证集 mAP 停滞甚至下滑。翻看 results.png训练曲线和验证曲线在某个 epoch 之后明显分道扬镳。原因165 张图对五个类别来说样本量偏小模型从第 20 轮开始已经把训练集纹理“背”下来了验证集上泛化能力反而下降。这是小数据集的典型过拟合信号不是代码写错了。解决分三路处理。第一路是早停训练命令里加patience20让框架在验证指标连续 20 轮不刷新时自动停用 best.pt 而不是 last.pt。第二路是增强把hsv_h、hsv_s、hsv_v从默认值往上调一档并对葡萄这类圆形果实加大scale和fliplr的扰动。第三路是换小模型yolov8n 起步跑通了再考虑 s 或 m不要一上来就上 x参数越多过拟合越快。yolo detect train data./grape_dataset/data.yaml modelyolov8n.pt epochs150 patience20 imgsz640 batch8 hsv_h0.02 hsv_s0.7 hsv_v0.5 fliplr0.5 scale0.5参数说明patience20是早停轮数hsv_h / hsv_s / hsv_v是色调、饱和度、亮度的增强幅度葡萄颜色多样适度加大能提升对光照变化的鲁棒性scale0.5是随机缩放比例用来模拟不同拍摄距离。血泪经验小数据集上增强参数宁可激进一点也不要保守欠增强的过拟合比过增强的形状失真更难处理。4.2 类别不均衡腐烂葡萄八百框拣选点五十框现象训练结束后打开 confusion_matrix.png对角线权重严重偏向腐烂葡萄和成熟葡萄斑点葡萄和拣选点的召回率惨不忍睹几乎全被预测成背景或相邻类别。原因cls_loss 是全局求均值大类样本多、贡献的梯度大模型自然偏向把难分样本归类到大类里。拣选点本身又是小目标特征像素占比低双重劣势叠在一起。解决先跑一遍 3.2 的体检脚本拿到各类别框数按比例调类别权重。ultralytics 框架支持在 data.yaml 里加cls_weights字段自定义 dataset 类时手动指定更稳或者简单粗暴的做法是给稀有类别过采样训练前把拣选点和斑点葡萄的样本复制几份混进 train 目录。更推荐的做法是直接用yolov8m替代yolov8n大模型的特征提取能力对小目标和稀有类更友好代价是训练时间变长但这个数据集总共才 165 张m 和 n 的绝对训练时长差距可以忽略。4.3 训练中途断了别从零再来resume 与 best/last 双权重现象训练到第 80 轮远程终端断了或显存被别的任务抢了进程被杀。重新执行同一条训练命令发现又从 epoch 0 开始跑之前 80 轮白费。原因ultralytics 默认从头训练并不会自动找到上次的断点。但它在训练过程中会持续保存两个权重best.pt和last.pt前者是验证集表现最好的快照后者是最近一轮的快照。解决用resumeTrue从 last.pt 续跑yolo detect train resume modelruns/detect/grape_yolov8n/weights/last.pt参数说明resume模式下框架会读取 last.pt 里记录的 epoch 和优化器状态数据路径、模型结构、超参数全都从原训练配置里恢复不需要重新指定。注意一个坑续跑时不要更换数据集路径也不要改 imgsz优化器状态和数据增强缓存对不上会出诡异曲线。推理和部署只用 best.ptlast.pt 只是断点续跑的“后悔药”。4.4 显卡只有 6GB 显存batch 和 imgsz 怎么搭配才不炸现象照搬教程里的batch16 imgsz640训练脚本跑起来两三秒就报CUDA out of memory黑匣子一样的问题不知道从哪个参数下手。原因yolov8 训练时显存占用主要由 batch size、输入分辨率和模型深度共同决定。6GB 显存跑 n 模型batch16 加 imgsz640 必然超。最关键的是很多人不知道 amp混合精度没开显存直接翻倍。解决显存有限时按这个顺序调——先开ampTrue再降 batch 到 8 或 4最后才降 imgsz。imgsz 最好不要低于 480否则本来就小的拣选点目标在特征图上只剩几个像素召回率会崩。亲测 6GB 显存下yolov8n imgsz640 batch8 amp可以稳定跑完 165 张图。另外有个技巧小数据集迭代一轮本身就快batch 小一点反而等于每轮更多次参数更新对收敛未必是坏事不必纠结一定要跑到标称 batch。5. 用 yolov8 把训练跑通命令行参数、结果指标与置信度门限5.1 环境安装与第一条完整的训练命令环境装好之后训练命令本身不复杂但每个参数都值得知道它在干什么。先把环境准备好conda create -n yolo python3.10 -y conda activate yolo pip install ultralytics逻辑说明ultralytics 是 yolov8、yolov9、yolov10、yolo11 的统一训练框架装这一个包就带上了模型定义、训练、验证、导出全套能力。python 版本建议 3.103.11 及以上在部分老版本 torch 下会有兼容噪音。装完可以先跑一个yolo predict sourcehttps://ultralytics.com/images/bus.jpg验证环境通不通再进训练。正式训练命令yolo detect train \ data./grape_dataset/data.yaml \ modelyolov8n.pt \ epochs150 \ imgsz640 \ batch8 \ patience20 \ device0 \ project./runs \ namegrape_v8n \ ampTrue参数说明data指向 data.yaml框架从这里读路径和类别modelyolov8n.pt会下载 COCO 预训练权重做迁移学习初始化前几层特征通用性很强对 165 张小数据集帮助很大——千万不要用随机权重从零开始训epochs150配合patience20是早停兜底device0指定第一张显卡没 GPU 就写devicecpu但这个数据量 CPU 也能训完只是慢project和name决定输出目录。跑起来之后日志里会实时打印每个 epoch 的 box_loss、cls_loss、dfl_loss 和 mAP 指标留心观察它们的变化趋势。5.2 结果目录里有什么从 confusion_matrix 到 results.png训练结束后所有产物都在runs/detect/grape_v8n/目录下。这些文件不光是给训练过程画句号更是判断这个模型能不能用的依据。ls -la runs/detect/grape_v8n/正常会看到 weights 目录best.pt 和 last.pt、confusion_matrix.png、results.png、F1_curve.png、PR_curve.png、val_batch_pred.jpg 等。重点看三个results.png 里三条 loss 曲线和 mAP 曲线整体走势confusion_matrix.png 的对角线亮度val_batch_pred.jpg 里真实标注与预测框的重合情况。读法上如果最后 20 轮 val 的 box_loss 还在下降说明训练没收敛可以加 epochs 或去掉早停再跑如果对角线只有少数几类亮说明类别不均衡问题没有解决。推理验证用 best.ptyolo detect predict modelruns/detect/grape_v8n/weights/best.pt sourcegrape_dataset/images/test/ conf0.25 saveTrue参数说明conf0.25是置信度门限低于这个分数的预测框会被过滤掉saveTrue会把标注了预测框的图片存到 runs/detect/predict 目录里供人工目检。5.3 置信度门限漏检和误检之间的平衡点模型输出的每个框都有一个置信度分数门限设得低框多但误检多门限设得高精度高但漏检多。分拣场景里这个参数直接决定产线效果值得单独写一个小脚本批量看不同门限下的表现from ultralytics import YOLO model YOLO(runs/detect/grape_v8n/weights/best.pt) results model.predict( sourcegrape_dataset/images/test/, conf0.1, iou0.5, saveFalse, verboseFalse ) for conf_thres in [0.1, 0.2, 0.25, 0.3, 0.4, 0.5, 0.6]: total 0 for r in results: boxes r.boxes if boxes is None: continue confs boxes.conf.cpu().numpy() total int((confs conf_thres).sum()) print(fconf{conf_thres}: 保留框数 {total})逻辑说明先用一个较低的门限0.1做推理把所有候选框保留下来再在内存里按不同门限统计保留框数量观察阈值变化对框数量的影响曲线。参数说明iou0.5是 NMS 阶段两个框重叠超过这个比例时合并一般保持默认即可葡萄果实密集如果重叠框被压得太多可以下调到 0.4。如果发现 conf 从 0.25 提到 0.4 时框数量骤降说明大量预测框集中在低置信度区间模型本身不确定度高这时调门限只是粉饰应该回头查训练数据质量和标注一致性。6. 特征可视化和双格式回写让模型不再是黑匣子6.1 用类激活图看模型到底在看葡萄的哪个部位模型训完mAP 达标但你不知道它靠什么特征做判断。对目标检测模型做可解释性分析常用的是 Grad-CAM它会生成一张热力图标出模型做分类决策时重点关注图像中的哪些区域。用 pytorch_grad_cam 库对 yolo 模型做可视化核心代码如下import torch from pytorch_grad_cam import GradCAM from pytorch_grad_cam.utils.model_targets import ClassifierOutputTarget from pytorch_grad_cam.utils.image import show_cam_on_image from ultralytics import YOLO import cv2 import numpy as np model YOLO(runs/detect/grape_v8n/weights/best.pt) image cv2.imread(grape_dataset/images/test/img_0964_30.jpg) image cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # 定位到模型最后一个卷积层 target_layers [model.model.model[-2]] # 前向推理准备输入张量 img_resized cv2.resize(image, (640, 640)) input_tensor torch.from_numpy(img_resized.transpose(2, 0, 1)).float() / 255.0 input_tensor input_tensor.unsqueeze(0) cam GradCAM(modelmodel.model, target_layerstarget_layers) targets [ClassifierOutputTarget(3)] # 类 id 3对应 mature_grape grayscale_cam cam(input_tensorinput_tensor, targetstargets)[0] visualization show_cam_on_image(img_resized.astype(np.float32) / 255.0, grayscale_cam)逻辑说明Grad-CAM 的原理是拿类别得分对最后一个卷积层的特征图求梯度用梯度加权特征图再上采样到原图尺寸得到“哪里对决策贡献最大”的热力图。参数说明target_layers选的是模型的倒数第二层结构因为越深的卷积层携带的语义信息越强ClassifierOutputTarget(3)指定想看哪个类别的响应这里类 id 3 对应 mature_grape。用法上如果热力图的亮区集中在果梗端部或病斑位置说明模型学到了有区分力的特征如果亮区散发到叶片或背景上就要警惕模型在“抄近道”比如靠背景颜色分类而不是靠果实本身。这个检查对 165 张小数据集尤其重要——数据少模型学歪的概率比大数据集高得多。6.2 labelimg 复核把误检样本拉回打标台可视化只能给你“模型在关注哪里”的宏观判断具体到某些框为什么误检还得把低置信度的预测框导出来用 labelimg 打开原图人工核对。我惯用的流程是三步先用 conf0.1 跑一遍 test 集把所有低置信度框输出为一个目录再用 labelimg 逐个打开看这些低置信度框到底是真目标还是误检最后只修正确认有问题的样本改完统一走双格式回写脚本保证 txt 和 xml 同步更新。labelimg 的操作很机械但效率高Open Dir 选图片目录Change Save Dir 选标签输出目录w 键画框、ctrls 保存、d 键切到下一张。值得提醒的是复核时一定要打开原图尺寸看缩略图下很容易漏掉拣选点这类小目标。从误检里能发现两类典型问题一是标注漏框——模型在图上框出了一个真实存在的腐烂葡萄但原始标签里没有导致训练时它被当成负样本二是边界类别主观性——同一串葡萄打标员甲标“成熟”标乙标“未成熟”这类框在混淆矩阵里表现为相邻类别互相串。发现第二类问题时不要急着改模型先把这类边界样本统一回标重新定义清楚判定标准再训。6.3 双格式同步回写确保 txt 与 xml 永远一致人工复核改了标签就要面对一个现实问题txt 和 xml 两份标签怎么保持一致。我强烈建议只维护一份标签作为基准我用 xml改完基准后跑一个同步脚本重新生成另一份import os import glob def sync_labels(xml_dir, img_dir, txt_out_dir, class_map): os.makedirs(txt_out_dir, exist_okTrue) synced 0 for xml_path in glob.glob(os.path.join(xml_dir, *.xml)): stem os.path.splitext(os.path.basename(xml_path))[0] img_path os.path.join(img_dir, stem .jpg) if not os.path.exists(img_path): continue img_w, img_h Image.open(img_path).size lines xml_to_yolo(xml_path, img_w, img_h, class_map) with open(os.path.join(txt_out_dir, stem .txt), w) as f: f.write(\n.join(lines) \n) synced 1 print(f已同步 {synced} 个文件到 {txt_out_dir})逻辑说明这个函数本质上就是批量 xml 转 yolo但它强调的是一个习惯——以 xml 为唯一基准所有人工修订只动 xmltxt 永远由脚本生成。这样做的好处是彻底避免两份标签各自演化、最后对不上的问题。从那以后我每次新拿到数据集都强制走一遍“体检脚本 → 确认基准格式 → 训练 → 复核 → 回写”的流水线训练前再顺手跑一次同步校验。165 张图的数据集不大但养成这个习惯后后面换大项目、多人协作打标时省下的对账时间远不止这几个小时。希望帮到你。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。