ARTICLE DETAIL

资讯详情

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

70张手套图跑YOLO:小样本定制数据集训练与调优实战

70张手套图跑YOLO:小样本定制数据集训练与调优实战 简介这是一份面向目标检测初学者与算法工程师的手套定制数据集可直接用于YOLO系列模型的训练与验证测试。数据集已按标准流程完成划分并附带data.yaml配置文件兼容yolov5、yolov7、yolov8、yolov9、yolov10及yolo11等主流版本省去自行整理与转换格式的繁琐步骤。压缩包共211个文件包含70张jpg原始图像、70个txt格式YOLO标注、70个xml格式VOC标注以及1个yaml配置文件整体约3.96MB。其中txt标注采用归一化的中心点与宽高比例xml则保留VOC标准结构两种格式分别存放便于按需选用或做格式对照。图像覆盖多种手套目标场景适合作为课程实验、算法对比或小样本微调的训练素材。目前已有104人学习下载可作为快速验证检测流程与标注解析逻辑的轻量级起点。1. 70 张手套图也能跑 YOLO小样本定制数据集的真实定位70 张图像、带标签、手套目标检测这三个条件放在一起很多人的第一反应是「数据量太少训不动」。但实际产线里这类需求恰恰最常见某条装配线要判断工人是否戴了防护手套某间实验室要统计无菌操作合规率某个仓储口要识别搬运人员的手部防护状态。场景单一、背景固定、目标类别只有一两类采集 70 张高质量图像往往比堆 7000 张杂乱图像更有效。这个标题真正要解决的问题不是「如何从零训练一个通用检测器」而是「如何用一份 70 张规模的手套定制数据集在 YOLO 系列上跑出可用的检测模型」。适合谁手头已经有一份标注好的手套数据集、想快速验证 YOLO 在自己场景下能不能用的工程师也适合刚接触 YOLO 数据集、想拿一个小规模真实案例走通「标注格式检查 → 环境配置 → 训练 → 推理 → 调参」全流程的新手。70 张不是缺陷是约束条件理解这个约束后面的每一步选型才有依据。2. 手套数据集拿到手先别急着训标签格式与图像质量的四道检查2.1 先确认标签是 YOLO 格式还是 VOC/COCO 格式YOLO 系列训练时读取的标签是每张图对应一个同名.txt文件每行格式为class_id x_center y_center width height后四个值都是相对图像宽高的归一化浮点数范围 0 到 1。如果你拿到的标签是.xmlVOC或.jsonCOCO必须先转换。常见做法是用脚本批量转不要手动改。import os import xml.etree.ElementTree as ET # VOC xml 转 YOLO txt假设只有一个类别 glovesclass_id 0 def voc_to_yolo(xml_dir, out_dir, img_w, img_h): os.makedirs(out_dir, exist_okTrue) for name in os.listdir(xml_dir): if not name.endswith(.xml): continue tree ET.parse(os.path.join(xml_dir, name)) root tree.getroot() lines [] for obj in root.iter(object): cls obj.find(name).text # 这里只保留手套类其他类别按需扩展 if cls ! gloves: continue bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 归一化并转为中心点宽高 x_c (xmin xmax) / 2.0 / img_w y_c (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f0 {x_c:.6f} {y_c:.6f} {w:.6f} {h:.6f}) with open(os.path.join(out_dir, name.replace(.xml, .txt)), w) as f: f.write(\n.join(lines))逻辑说明遍历 VOC 标注目录逐个解析object节点把绝对坐标转成 YOLO 需要的归一化中心点格式。参数说明img_w、img_h必须和对应图像真实尺寸一致如果图像被预处理过比如统一缩放这里要用缩放后的尺寸否则框会整体偏移。转换完成后务必抽查 3 到 5 张用可视化脚本把框画回图上确认。2.2 70 张图的划分比例不能照搬 8:1:1常规数据集动辄几千张按 8:1:1 划分训练/验证/测试没问题。70 张的规模下如果按 8:1:1验证集只有 7 张测试集 7 张指标波动会非常大一次训练和下一次训练的 mAP 可能差十几个点这就是小样本的玄学来源。我一般会这样处理训练集 56 张、验证集 14 张暂时不单独切测试集等模型稳定后再从验证集里抽一部分做最终评估。或者用 5 折交叉验证每折 56 张训练、14 张验证最后看平均指标。# 按 8:2 划分生成 train.txt 和 val.txt ls images/*.jpg | shuf --random-source(yes 42) | head -n 56 train.txt ls images/*.jpg | shuf --random-source(yes 42) | tail -n 14 val.txt参数说明--random-source固定随机种子保证每次划分一致方便复现。head -n 56和tail -n 14对应 70 张的 8:2。如果你的图像是.png把*.jpg换掉即可。2.3 图像分辨率和长宽比要统一检查YOLO 训练时默认会把图像缩放到统一尺寸比如 640×640如果原始图像长宽比差异很大缩放后目标会变形小目标可能被压没。70 张图里如果混了手机拍的竖图和相机拍的横图先统计一下尺寸分布。from PIL import Image import os sizes {} for name in os.listdir(images): with Image.open(os.path.join(images, name)) as im: sizes[im.size] sizes.get(im.size, 0) 1 for k, v in sorted(sizes.items(), keylambda x: -x[1]): print(k, v)如果发现尺寸种类超过 3 种建议统一缩放到一个基准尺寸或者训练时把imgsz设成接近多数图像的长宽比。注意缩放后要同步更新标签里的归一化坐标否则框会错位。2.4 标签里的空文件和越界框要提前清掉70 张图里如果有一张图没有目标对应的.txt应该是空文件这是合法的YOLO 会把它当作背景图。但如果.txt里出现坐标小于 0 或大于 1训练时可能报错或产生异常梯度。用下面这段脚本扫一遍。import os bad [] for name in os.listdir(labels): if not name.endswith(.txt): continue with open(os.path.join(labels, name)) as f: for i, line in enumerate(f): parts line.strip().split() if len(parts) ! 5: bad.append((name, i, 字段数不对)) continue vals list(map(float, parts[1:])) if any(v 0 or v 1 for v in vals): bad.append((name, i, 坐标越界)) print(bad)发现越界框先回原图确认是标注错误还是转换错误不要直接截断到 0 或 1那样会引入错误监督信号。3. 用 YOLOv8 在 70 张手套图上跑通第一个基线3.1 环境配置Anaconda 建环境加 ultralytics 安装YOLOv8 的官方实现是ultralytics包Python 3.8 以上即可。我一般用 conda 建一个干净环境避免和系统里的 PyTorch 版本打架。conda create -n yolo_gloves python3.10 -y conda activate yolo_gloves pip install ultralytics # 如果需要 GPU 训练确认 torch 能识别到 CUDA python -c import torch; print(torch.cuda.is_available())参数说明python3.10是当前兼容性较好的版本3.11 和 3.12 也能用但部分依赖轮子可能还没跟上。torch.cuda.is_available()返回True才说明 GPU 可用返回False时训练会走 CPU70 张图虽然不多但 CPU 训练仍然很慢建议先解决 GPU 驱动和 CUDA 版本匹配问题。3.2 数据集 YAML 文件怎么写YOLOv8 通过一个 YAML 文件描述数据集路径和类别。在项目根目录建gloves.yamlpath: /home/user/gloves_dataset train: train.txt val: val.txt names: 0: gloves逻辑说明path是数据集根目录train和val是相对于path的列表文件路径列表文件里每行是一张图的绝对或相对路径。names是类别索引到名称的映射手套只有一类所以只写0: gloves。注意train.txt里的路径要和实际图像位置一致如果图像在images/子目录下列表里要写images/xxx.jpg。3.3 启动训练命令行参数怎么设yolo detect train \ datagloves.yaml \ modelyolov8n.pt \ epochs200 \ imgsz640 \ batch8 \ lr00.001 \ patience50 \ projectruns/gloves \ namebaseline参数说明modelyolov8n.pt用最小的 nano 版本70 张图用大模型容易过拟合nano 足够。epochs200是小样本常用的轮数配合patience50早停验证指标 50 轮不提升就停。batch8在 70 张图下每个 epoch 只有 7 个 batch显存压力小。lr00.001是初始学习率小样本建议比默认的 0.01 小一个量级避免震荡。imgsz640是输入尺寸如果手套目标很小可以提到 960 或 1280但显存占用会上升。训练开始后终端会打印每个 epoch 的 box_loss、cls_loss、mAP50 等指标。70 张图通常 50 到 100 轮就能看到 mAP50 趋于稳定。如果 loss 一直不降先检查标签格式和路径再考虑调学习率。3.4 推理验证用训练好的权重跑几张图yolo detect predict \ modelruns/gloves/baseline/weights/best.pt \ sourceimages/ \ conf0.25 \ saveTrue参数说明conf0.25是置信度阈值低于这个值的框不显示。小样本模型初期置信度普遍偏低可以先设 0.1 看召回再逐步提高。saveTrue会把画框后的图存到runs/detect/predict目录。跑完后人工看几张重点看漏检和误检分别出现在什么场景是手套颜色和背景接近还是手套被遮挡还是图像过暗。这些观察直接决定下一步是补数据还是调增强。4. 小样本训练避坑70 张手套图最容易翻车的五个地方4.1 现象训练 loss 正常下降但验证 mAP 始终为 0原因验证集列表文件里的路径写错了YOLO 读不到验证图或者验证图的标签目录和图像目录没有对应上。另一种可能是验证集里的类别索引和names不一致。解决先手动打开val.txt确认每一行路径都能在文件系统里找到对应图像再检查图像同目录或对应labels/目录下是否有同名.txt。用yolo detect val datagloves.yaml modelbest.pt单独跑验证看终端报的具体错误。4.2 现象模型在训练集上框得很准换一张新图就乱框原因70 张图如果背景高度相似比如都在同一个工位拍模型学到的是背景纹理而不是手套特征。这是小样本过拟合的典型表现。解决训练时开启更强的数据增强。YOLOv8 默认已经带了 HSV 抖动、随机翻转、 mosaic但小样本可以额外加degrees10、translate0.1、scale0.5、mixup0.1。如果增强后仍然过拟合说明 70 张图的场景多样性不够需要补拍不同角度、不同光照、不同手套颜色的图哪怕只补 20 张效果也可能明显提升。4.3 现象训练到一半报 CUDA out of memory原因imgsz设得太大或者batch设得太大或者同时开了多个训练进程。解决先把batch降到 4 或 2再把imgsz从 1280 降到 640。如果还是爆显存用yolo detect train ... device0明确指定单卡避免多卡并行时的显存碎片。70 张图用yolov8n加imgsz640加batch86GB 显存的卡就能跑。4.4 现象推理时同一张图里手套被重复框了好几次原因置信度阈值设得太低或者 NMS 的 IoU 阈值设得太高导致重叠框没被合并。解决推理时把conf从 0.1 提到 0.3 到 0.5 之间试同时确认iou参数默认 0.7是否合适。如果手套目标密集IoU 可以降到 0.5 到 0.6让重叠框更容易被抑制。注意调高 conf 会降低召回调低 iou 会减少重叠框但可能漏掉紧挨着的手套需要根据实际场景权衡。4.5 现象换了随机种子重新训练mAP 波动超过 10 个点原因70 张图的验证集只有 14 张指标本身方差就大。这不是模型不稳定是评估集太小导致的统计噪声。解决不要只看单次训练的 mAP跑 3 到 5 次不同种子的训练看平均值和标准差。如果标准差超过 5 个点说明验证集划分方式需要调整可以改用 5 折交叉验证每折的验证集不同最后报告平均 mAP。另外训练时固定seed42可以让同一次实验可复现但不代表换种子后结果不变。5. 从 70 张到可用模型三个提效技巧和一套验证习惯5.1 用预训练权重做冻结训练再解冻微调YOLOv8 的yolov8n.pt是在 COCO 上预训练的已经学到了通用的边缘和纹理特征。70 张图直接从头训容易过拟合我一般分两阶段先冻结 backbone只训检测头 50 轮让模型先适应手套这个新类别再解冻全部层用更小的学习率微调 100 轮。# 第一阶段冻结 backbone yolo detect train datagloves.yaml modelyolov8n.pt epochs50 freeze10 lr00.001 # 第二阶段解冻微调学习率降一个量级 yolo detect train datagloves.yaml modelruns/gloves/train/weights/best.pt epochs100 lr00.0001参数说明freeze10表示冻结前 10 层YOLOv8n 的 backbone 大约对应这个范围。第二阶段加载第一阶段的最好权重学习率降到 0.0001避免破坏已经学到的特征。这个流程在 70 张图上通常比直接训 200 轮效果更稳。5.2 用验证集上的混淆矩阵定位类别混淆训练结束后runs/gloves/baseline/目录下会生成confusion_matrix.png。如果手套只有一类矩阵是 2×2背景和手套重点看背景被误判成手套的比例以及手套被漏检成背景的比例。前者高说明误检多后者高说明漏检多。误检多就提高conf阈值漏检多就补数据或降低conf。这个图比单看 mAP 更能指导下一步动作。5.3 用 5 折交叉验证替代单次划分70 张图做 5 折每折 56 张训练、14 张验证跑 5 次训练记录每次的 mAP50 和 mAP50-95。最后看均值和标准差。如果均值能到 0.8 以上标准差在 0.05 以内说明模型在这个场景下基本可用。如果标准差很大先检查每一折的验证集里是否包含特别难或特别简单的图必要时做分层抽样保证每折的难度分布接近。import numpy as np # 假设 5 折的 mAP50 结果 map50_scores [0.82, 0.79, 0.85, 0.77, 0.81] print(f均值: {np.mean(map50_scores):.3f}) print(f标准差: {np.std(map50_scores):.3f})参数说明np.mean和np.std分别算均值和标准差。如果标准差超过 0.05建议增加折数到 10 折或者补数据。注意5 折交叉验证的训练时间是单次训练的 5 倍70 张图下每次训练可能只要几分钟总体可接受。5.4 一个我踩过的坑别在验证集上调参调到过拟合早期我做小样本项目时习惯反复在验证集上试不同的conf、iou、imgsz看哪个组合 mAP 最高。结果模型在验证集上表现很好换一批新图就崩了。后来我改成验证集只用来早停和选模型调参用另一小部分从训练集里切出来的数据或者干脆用交叉验证的平均指标来选。70 张图的场景下验证集只有 14 张任何针对这 14 张的精细调参都可能是过拟合。这个习惯让我在后来的项目里少走了很多弯路。希望帮到你。本文还有配套的精品资源点击获取
返回列表