ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

1738张成人和小孩数据集YOLOv9实战:70.9%识别率能否直接上项目?

1738张成人和小孩数据集YOLOv9实战:70.9%识别率能否直接上项目? 简介这份成人与小孩图像数据集面向计算机视觉入门者、目标检测课程实验者及需要快速验证模型的小型项目开发者用于训练和评估区分成人、小孩两类目标的检测模型。资源共包含2000个文件其中1738个txt为YOLOv9格式标注文件261个jpg为原始图片另有1个yaml配置文件用于定义数据集路径与类别信息压缩包整体约91.41MB目录结构便于直接接入YOLO系列训练流程。标注覆盖多场景下的人物图像可支撑分类与检测任务的快速迭代。目前已有167人学习下载适合作为课堂作业、课程设计或算法对比实验的轻量级数据来源。需要说明的是该数据集在现有条件下的识别率约为70.9%读者可据此评估基线表现并在此基础上通过数据增强、模型调参或补充样本进一步提升精度从而获得一套可直接复现的检测实验起点。1. 1738 张成人和小孩数据集70.9% 识别率到底能不能直接上项目上周有个做儿童看护摄像头的朋友甩给我一个数据集标题写着「成人和小孩数据集 1738 张原始图片识别率 70.9%yolov9 格式标注」。他问得很直接这东西能不能直接拿来训模型70.9% 是不是太低了。我拆开看了一遍先说结论——这个数据集的价值不在那个 70.9% 的数字上而在于它把「成人 / 小孩」这个二分类场景的原始图片和 YOLO 格式标注打包好了省掉的是你自己找图、自己标框的时间。1738 张原始图片全部是 jpg 格式标注文件是 YOLO 系列的 txt 格式可以直接喂给 yolov9 或者 yolov8 训练。适合谁适合做儿童区域监控、亲子互动分析、儿童用品广告投放筛选这类需要区分成人和小孩的从业者。不适合谁不适合指望拿来就上生产环境的人70.9% 的识别率意味着每十个目标里差不多有三个会判错这个精度只能当基线不能当终点。文件名里那些_jpg.rf.后缀是标注平台导出时自动加的哈希不影响使用但批量处理时要注意路径匹配。2. 拆开数据包1738 张图 YOLO 标注的真实结构2.1 文件命名规律与目录组织拿到压缩包解压后你会看到一堆类似000000000368_jpg.rf.a354cea163edd946205e4d13985aba16.jpg的文件。这个命名结构拆开看000000000368是原始图片的序号_jpg表示原格式.rf.后面那串 32 位十六进制是标注平台导出时生成的唯一标识防止重名覆盖。标注文件通常是同名的.txt放在labels目录下图片放在images目录下。常见做法是保持这个结构不动直接建一个data.yaml指向这两个目录。我一般会先跑一遍文件配对检查确认每张图都有对应的标注文件因为标注平台导出时偶尔会漏掉几张。# 检查图片和标注文件是否一一对应 import os img_dir dataset/images lbl_dir dataset/labels imgs set(os.path.splitext(f)[0] for f in os.listdir(img_dir) if f.endswith(.jpg)) lbls set(os.path.splitext(f)[0] for f in os.listdir(lbl_dir) if f.endswith(.txt)) missing_lbl imgs - lbls missing_img lbls - imgs print(f图片总数: {len(imgs)}) print(f标注总数: {len(lbls)}) print(f缺标注的图片: {len(missing_lbl)}) print(f缺图片的标注: {len(missing_img)})这段脚本做的是集合差运算。imgs和lbls分别收集图片和标注文件的文件名去掉扩展名然后做差集。如果missing_lbl不为空说明有图片没标注训练时这些图会被跳过或者报错。如果missing_img不为空说明有标注文件找不到对应图片YOLO 训练时会直接报AssertionError。我遇到过标注平台导出时把几张图漏掉的情况跑一遍这个检查能省掉后面调试的半小时。2.2 YOLO 标注格式的字段含义YOLO 格式的标注文件每行代表一个目标框格式是class_id x_center y_center width height五个字段用空格分隔。class_id是类别索引这个数据集里只有两个类成人通常是 0和小孩通常是 1。后面四个值是归一化后的坐标范围在 0 到 1 之间分别表示框中心点的 x、y 坐标和框的宽、高。归一化是相对于图片的原始宽高做的所以换分辨率不影响标注有效性。# 查看某个标注文件的内容 cat dataset/labels/000000000368_jpg.rf.a354cea163edd946205e4d13985aba16.txt # 典型输出 # 0 0.523 0.412 0.231 0.567 # 1 0.712 0.634 0.156 0.289第一行表示一个成人中心点在图片宽度 52.3% 位置高度 41.2% 位置框宽占图片宽度 23.1%框高占图片高度 56.7%。第二行表示一个小孩位置和尺寸类似解读。这里有个容易翻车的点有些标注平台导出的坐标不是归一化的而是绝对像素值。如果你直接拿去训练YOLO 会报Label class x_center 1之类的错误。判断方法很简单看数值有没有超过 1超过就是绝对坐标需要自己除以图片宽高转成归一化。2.3 类别分布与数据平衡检查在训练之前我习惯先统计一下两个类别的样本数量。如果成人样本远多于小孩样本模型会偏向把目标都判成成人小孩的召回率会很难看。这个数据集标题里没提类别分布但 70.9% 的识别率很可能就是类别不平衡导致的。import os from collections import Counter lbl_dir dataset/labels counter Counter() for f in os.listdir(lbl_dir): if f.endswith(.txt): with open(os.path.join(lbl_dir, f)) as fh: for line in fh: cls line.strip().split()[0] counter[cls] 1 print(类别分布:, dict(counter)) # 典型输出: {0: 1200, 1: 800}Counter统计每个类别出现的次数。如果0和1的比例超过 3:1训练时就需要考虑用cls_pw或者过采样来平衡。YOLOv9 的配置里可以通过class_weights参数给少数类更高的权重但更直接的办法是在数据加载时对小孩样本做重复采样。我一般会先跑一遍这个统计心里有数再决定要不要做平衡处理。3. 用 YOLOv9 跑通训练从 data.yaml 到第一个 checkpoint3.1 写对 data.yaml 的三个关键字段YOLOv9 训练入口认的是data.yaml里面必须写清楚train、val、nc、names四个字段。train和val指向图片目录nc是类别数names是类别名称列表。这个数据集只有两个类所以nc: 2names: [adult, child]。注意names的顺序必须和标注文件里的class_id对应如果标注里 0 是成人、1 是小孩那names列表第一个就得是adult写反了模型学出来的类别就全乱了。# data.yaml train: ./dataset/images/train val: ./dataset/images/val nc: 2 names: [adult, child]train和val的路径可以是绝对路径也可以是相对路径相对路径是相对于你执行训练命令时的工作目录。我一般会把数据集按 8:2 切分训练集和验证集分开放在images/train和images/val下标注文件对应放在labels/train和labels/val下。切分脚本很简单但要注意别把同一张图的不同版本分到两边否则验证集精度会虚高。3.2 训练命令与关键参数设置YOLOv9 的训练命令用train.py或者yolo命令行工具都行。我一般用命令行参数改起来直观。下面这条命令是跑这个数据集的一个合理起点yolo detect train \ datadata.yaml \ modelyolov9c.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectruns/train \ nameadult_childmodelyolov9c.pt是 YOLOv9 的中等规模预训练权重参数量适中适合 1738 张图这个量级。epochs100是上限patience20表示如果 20 轮验证集精度没提升就提前停防止过拟合。imgsz640是输入分辨率如果原始图片普遍小于 640可以降到 416 或 320 来加速。batch16取决于显存8G 显存跑 640 分辨率大概能撑到 16不够就降到 8。lr00.01是初始学习率YOLOv9 默认用 SGD 优化器这个值比较稳。如果 loss 震荡厉害可以降到 0.001。3.3 训练过程监控与指标解读训练启动后控制台会每轮打印box_loss、cls_loss、dfl_loss和mAP0.5。box_loss是边界框回归损失cls_loss是分类损失dfl_loss是分布焦点损失。这三个 loss 都应该随着轮次下降如果某个 loss 一直不降或者反弹说明对应部分出了问题。mAP0.5是 IoU 阈值 0.5 时的平均精度这个数据集标题里说的 70.9% 识别率大概率就是mAP0.5或者准确率。训练到 50 轮左右如果mAP0.5还在 0.7 附近晃基本就是数据本身的天花板了。# 训练结束后用验证集跑一遍评估 yolo detect val \ modelruns/train/adult_child/weights/best.pt \ datadata.yaml \ imgsz640val命令会输出每个类别的precision、recall和mAP。重点看小孩类别的recall如果明显低于成人说明模型对小孩特征学得不够需要检查标注质量或者增加小孩样本。我一般会把best.pt和last.pt都留着best.pt是验证集精度最高的last.pt是最后一轮的有时候last.pt在测试集上反而更稳。4. 避坑与排查70.9% 识别率背后的五个真实问题4.1 现象训练 loss 正常下降但 mAP 卡在 0.7 不动原因这个数据集的标注质量参差不齐。1738 张图里有一部分是低分辨率或者严重遮挡的标注框可能只框了半个身子或者把背景里的成人误标成小孩。模型学到这些噪声标注后验证集精度就上不去。解决跑一遍标注可视化把明显错误的标注挑出来修正或者直接删掉。YOLOv9 自带plot_labels功能训练前会生成标注分布图重点看框的宽高比和位置分布有没有异常离群点。4.2 现象小孩类别 recall 只有 0.5 左右成人却有 0.8原因类别不平衡。成人样本可能是小孩的两倍以上模型倾向于把不确定的目标判成成人。解决在data.yaml同级目录建一个hyp.yaml把cls_pw设为 0.5 到 1.0 之间的值给少数类更高权重。或者用copy_paste数据增强把小孩样本复制粘贴到更多背景里增加多样性。我一般先试cls_pw0.8不行再上过采样。4.3 现象推理时同一张图里成人框和小孩框重叠严重原因YOLO 的 NMS非极大值抑制阈值默认 0.45如果成人和小孩挨得很近两个框的 IoU 超过阈值其中一个会被抑制掉。解决推理时把iou参数调到 0.6 或 0.7让重叠框都能保留。但调太高会引入重复框需要根据实际场景权衡。儿童看护场景里成人和小孩经常抱在一起这个参数必须调。4.4 现象换一批新图片测试精度掉到 0.5 以下原因数据集的 1738 张图来源单一可能是某个特定场景比如室内、特定光照拍的模型过拟合到这个域。换到室外或者不同光照条件特征分布变了精度就崩。解决训练时开mosaic和mixup增强mosaic1.0默认开mixup0.1到 0.2能提升泛化。另外scale0.5和hsv_h0.015、hsv_s0.7、hsv_v0.4 这些颜色增强参数也建议打开。4.5 现象标注文件里出现 class_id 为 2 或更大的值原因标注平台导出时可能混入了其他类别的标注或者类别映射表没对齐。这个数据集只有两个类出现 2 就是脏数据。解决写个脚本扫描所有标注文件把class_id 2的行删掉或者修正。训练时如果遇到Label class 2 is not in the data.yaml报错就是这个问题。import os lbl_dir dataset/labels for f in os.listdir(lbl_dir): if f.endswith(.txt): path os.path.join(lbl_dir, f) with open(path) as fh: lines fh.readlines() cleaned [l for l in lines if int(l.split()[0]) 2] if len(cleaned) ! len(lines): with open(path, w) as fh: fh.writelines(cleaned) print(f修正: {f})这段脚本遍历所有标注文件把class_id大于等于 2 的行过滤掉。int(l.split()[0])取每行第一个字段转成整数 2保留合法类别。如果文件被修改过打印出来方便核对。跑完这个再训练就不会因为脏类别报错了。5. 把 70.9% 当基线三个提精度的实操技巧5.1 用预训练权重做分层微调YOLOv9 的yolov9c.pt是在 COCO 上预训练的COCO 里本来就有person类和成人 / 小孩的特征有重叠。直接从头训 1738 张图容易过拟合正确做法是加载预训练权重后冻结 backbone 前几层只训 head 和后面几层。YOLOv9 的freeze参数可以指定冻结层数freeze10表示冻结前 10 层。我一般先freeze10跑 30 轮再解冻全部跑 50 轮这样比直接全量训练收敛更稳。# 第一阶段冻结 backbone yolo detect train \ datadata.yaml \ modelyolov9c.pt \ freeze10 \ epochs30 \ imgsz640 \ batch16 \ lr00.01 \ projectruns/train \ nameadult_child_stage1 # 第二阶段解冻全量微调 yolo detect train \ datadata.yaml \ modelruns/train/adult_child_stage1/weights/best.pt \ epochs50 \ imgsz640 \ batch16 \ lr00.001 \ projectruns/train \ nameadult_child_stage2第一阶段freeze10让模型先适应新数据的分布第二阶段用更小的学习率lr00.001做精细调整。两阶段加起来 80 轮比直接跑 100 轮效果通常好 2 到 3 个点。注意第二阶段加载的是第一阶段的best.pt不是last.pt因为best.pt在验证集上表现最好。5.2 针对小孩样本做定向增强小孩样本少且形态变化大常规增强不够。我一般会额外加copy_paste0.3把小孩实例复制粘贴到其他图片的背景区域增加小孩在不同场景下的出现频率。另外degrees10做小角度旋转translate0.1做平移模拟小孩跑动时的位置变化。这些参数写在hyp.yaml里训练时用hyphyp.yaml加载。# hyp.yaml lr0: 0.01 lrf: 0.01 momentum: 0.937 weight_decay: 0.0005 warmup_epochs: 3.0 box: 7.5 cls: 0.5 dfl: 1.5 hsv_h: 0.015 hsv_s: 0.7 hsv_v: 0.4 degrees: 10.0 translate: 0.1 scale: 0.5 shear: 2.0 perspective: 0.0 flipud: 0.0 fliplr: 0.5 mosaic: 1.0 mixup: 0.1 copy_paste: 0.3 cls_pw: 0.8cls_pw0.8给少数类更高权重copy_paste0.3做实例级增强mixup0.1做图像混合。这些参数不是拍脑袋定的是跑过几轮对比后留下来的。degrees10别调太大小孩和成人的姿态差异不需要大角度旋转调大了反而引入噪声。5.3 用测试集做最终验证而不是验证集训练时的验证集是从 1738 张里切出来的模型间接见过这些图的分布。真正能反映泛化能力的是完全没参与训练的测试集。我一般会从原始数据里留出 10% 作为测试集训练全程不碰最后用val命令跑一遍。如果测试集mAP0.5比验证集低超过 5 个点说明过拟合严重需要加正则或者减模型规模。# 最终测试集评估 yolo detect val \ modelruns/train/adult_child_stage2/weights/best.pt \ datatest.yaml \ imgsz640 \ conf0.25 \ iou0.6conf0.25是置信度阈值低于这个值的框不输出。iou0.6是 NMS 阈值比默认的 0.45 高因为成人和小孩经常重叠。这两个参数要根据实际场景调儿童看护场景建议conf0.3、iou0.6宁可多留几个框也别漏掉小孩。从那以后我每次拿到标注数据集都强制先跑一遍文件配对检查和类别分布统计再开始写data.yaml。这个习惯帮我省掉了至少三次训练到一半才发现标注对不上的返工。希望帮到你。本文还有配套的精品资源点击获取
返回列表