资讯动态

YOLO老鼠数据集实战:2295张带标签图像训练与避坑指南

发布时间:2026/10/4 1:00:58 来源:尧图企业网站定制
简介这是一份面向YOLO系列目标检测学习者的老鼠目标检测数据集适合正在做小目标识别、动物检测或课程设计、毕业设计的同学直接上手训练与验证。数据集已按训练与验证需求划分完毕兼容yolov5、yolov8、yolov9、yolov7、yolov10及yolo11等主流版本无需额外整理即可投入模型训练。压缩包共约2000个文件整体约119.3MB其中1610个xml文件为VOC格式标注390个txt文件为YOLO格式标注两种标签分别存放于独立文件夹便于按框架灵活切换。YOLO格式采用类别索引加归一化中心点与宽高的标准写法坐标范围均在0到1之间可直接被训练脚本读取。目前已有143人学习下载资源提供图像与对应标签的完整配对能帮助读者省去标注与格式转换环节把精力集中在模型调参、效果对比与检测精度提升上也便于复现和扩展自己的检测方案。1. 老鼠数据集 2295 张带标签这套 YOLO 组合包到底能解决什么问题实验室里要做一个鼠类行为识别或者鼠害监测的项目最卡脖子的往往不是模型结构而是手里没有一批标注干净、类别明确的老鼠图像。公开数据集里猫狗、行人、车辆一抓一大把老鼠这种小目标、多姿态、易被遮挡的对象反而稀缺。这个标题里的「yolo算法-老鼠数据集-2295张图像带标签-组合鼠标.zip」本质就是一份面向 YOLO 目标检测训练的老鼠图像数据集2295 张图像配对应标签文件打包成一个压缩包拿来就能接进 YOLO 训练流程。它适合三类人刚入门 YOLO 想找一个真实小目标数据集练手的新手、做鼠情监测或动物行为研究需要快速起一个 baseline 的从业者、以及想验证自己数据增强和调参策略是否有效的老手。2295 张不算大但足够跑通从数据检查、格式转换、训练到推理的完整链路也足够暴露小目标检测里那些玄学问题。下面我按自己实际处理这类数据集的顺序把每一步拆开讲清楚。2. 拿到压缩包先别急着训练数据体检与标签格式确认2.1 为什么 2295 张必须先做体检很多人拿到数据集第一反应是直接yolov8 train结果训练 loss 不降或者 mAP 一直趴在地上回头才发现标签里有大量空文件、坐标越界、类别编号从 1 开始而不是 0。老鼠数据集这类小目标数据尤其容易出问题标注时鼠标点偏一点框就可能只有几个像素有些图像里老鼠只露出尾巴或耳朵标注员干脆漏标。2295 张里哪怕只有 5% 的脏数据也足以让模型学到一个错误的先验。所以第一步不是训练是把压缩包解压后做一次结构化体检确认图像数量、标签数量、类别分布、框的尺寸分布这四件事。2.2 解压后的目录结构与标签格式核对常见做法是解压后得到images/和labels/两个目录或者JPEGImages/配Annotations/的 VOC 结构。YOLO 训练需要的是每张图对应一个同名.txt每行class_id x_center y_center width height且坐标是归一化到 0~1 的。先用下面这段脚本把家底摸清楚。import os from pathlib import Path from collections import Counter img_dir Path(images) lbl_dir Path(labels) img_exts {.jpg, .jpeg, .png, .bmp} imgs [p for p in img_dir.rglob(*) if p.suffix.lower() in img_exts] print(f图像总数: {len(imgs)}) missing, empty, bad_coord [], [], [] cls_counter Counter() box_sizes [] for img in imgs: lbl lbl_dir / (img.stem .txt) if not lbl.exists(): missing.append(img.name) continue lines [l.strip() for l in lbl.read_text().splitlines() if l.strip()] if not lines: empty.append(img.name) continue for line in lines: parts line.split() if len(parts) ! 5: bad_coord.append((img.name, line)) continue c, x, y, w, h int(parts[0]), *map(float, parts[1:]) cls_counter[c] 1 box_sizes.append((w, h)) if not (0 x 1 and 0 y 1 and 0 w 1 and 0 h 1): bad_coord.append((img.name, line)) print(f缺失标签: {len(missing)}) print(f空标签文件: {len(empty)}) print(f坐标异常行: {len(bad_coord)}) print(f类别分布: {dict(cls_counter)}) if box_sizes: ws sorted(w for w, _ in box_sizes) hs sorted(h for _, h in box_sizes) print(f框宽中位数: {ws[len(ws)//2]:.4f}, 框高中位数: {hs[len(hs)//2]:.4f})这段脚本做四件事统计图像总数、找出没有对应标签的图、找出空标签文件、校验每行坐标是否归一化且在合法范围同时输出类别分布和框尺寸中位数。参数上img_dir和lbl_dir按你解压后的实际路径改img_exts覆盖常见图像后缀。跑完重点看两个数框宽高中位数如果低于 0.05说明这是典型小目标数据集后面训练必须调小 anchor 或改用更适合小目标的检测头类别分布如果严重倾斜比如某一类占 90%就要考虑过采样或类别加权。2.3 把 VOC 或 COCO 标签转成 YOLO 格式如果压缩包里给的是 XML 或 JSON就得先转。VOC 转 YOLO 的核心是把xmin,ymin,xmax,ymax转成中心点加宽高再归一化。下面这个转换函数我一般直接复用。import xml.etree.ElementTree as ET from PIL import Image def voc_to_yolo(xml_path, img_path, class_map): tree ET.parse(xml_path) root tree.getroot() w, h Image.open(img_path).size lines [] for obj in root.findall(object): name obj.find(name).text if name not in class_map: continue cid class_map[name] bnd obj.find(bndbox) xmin float(bnd.find(xmin).text) ymin float(bnd.find(ymin).text) xmax float(bnd.find(xmax).text) ymax float(bnd.find(ymax).text) # 裁剪到图像边界防止标注越界 xmin, ymin max(0, xmin), max(0, ymin) xmax, ymax min(w, xmax), min(h, ymax) xc (xmin xmax) / 2 / w yc (ymin ymax) / 2 / h bw (xmax - xmin) / w bh (ymax - ymin) / h lines.append(f{cid} {xc:.6f} {yc:.6f} {bw:.6f} {bh:.6f}) return linesclass_map是你自己定义的类别名到 0 起始编号的映射比如{mouse: 0}。注意这里做了边界裁剪因为标注越界是 VOC 数据里最常见的脏数据之一不裁的话归一化后会出现大于 1 的坐标YOLO 训练时直接报错或静默丢弃。转换完再跑一遍 2.2 的体检脚本确认干净。3. 用 YOLOv8 在 2295 张老鼠图上跑通第一个 baseline3.1 数据集配置文件与目录组织YOLO 训练不直接吃散图需要按train/val划分并写一个data.yaml。2295 张我一般按 8:2 切验证集留 450 张左右保证每个类别在验证集里都有足够样本。目录结构建议这样组织dataset/ images/ train/ # 约1836张 val/ # 约459张 labels/ train/ val/ data.yamldata.yaml内容如下路径写绝对路径最稳避免训练时工作目录变化导致找不到文件。path: /abs/path/to/dataset train: images/train val: images/val nc: 1 names: [mouse]nc是类别数老鼠数据集通常就一类如果压缩包里区分了不同鼠种或姿态按实际类别数改names顺序必须和标签里的class_id严格对应错一位整个训练就废了。3.2 训练命令与关键参数怎么设baseline 先用yolov8n或yolov8s别一上来就上大模型2295 张撑不起大参数量过拟合风险高。命令如下yolo detect train \ datadataset/data.yaml \ modelyolov8s.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ lrf0.01 \ patience20 \ cacheTrue \ projectruns/mouse \ namebaseline逐个说参数imgsz640是输入分辨率老鼠是小目标理论上可以提到 960 或 1280但显存和速度会明显上升先用 640 看 baselinebatch16按显存调8G 显存跑yolov8s640 大概能到 16lr00.01是初始学习率小数据集可以降到 0.005 更稳patience20是早停验证指标 20 轮不涨就停省时间cacheTrue把图像缓存到内存2295 张不大开了之后每轮省不少 IO。训练完看runs/mouse/baseline/results.csv重点看metrics/mAP50-95和val/box_loss两条曲线如果 box_loss 震荡不降多半是学习率太大或标签有问题。3.3 小目标检测的针对性调整老鼠在图像里往往只占几十个像素默认 anchor 和检测头对小目标不友好。三个调整方向第一把imgsz提到 960让老鼠在特征图上多占几个像素第二用yolov8s-p2这类带 P2 小目标检测层的变体P2 层 stride 是 4对小目标响应更强第三开 Mosaic 和 CopyPaste 增强mosaic1.0默认开copy_paste0.3可以增加小目标的出现频率。我一般先跑 640 baseline再跑 960 对比如果 mAP50-95 提升超过 3 个点就说明分辨率是瓶颈值得为它牺牲推理速度。4. 训练完别只看 mAP推理验证与坏案例排查4.1 用验证集跑推理并可视化训练结束模型权重在runs/mouse/baseline/weights/best.pt先别急着部署拿验证集跑一遍推理把预测框画出来人眼看。yolo detect predict \ modelruns/mouse/baseline/weights/best.pt \ sourcedataset/images/val \ conf0.25 \ iou0.5 \ saveTrue \ projectruns/mouse \ nameval_predconf0.25是置信度阈值低于它的框不显示iou0.5是 NMS 的 IoU 阈值重叠超过 0.5 的框会被合并。跑完去runs/mouse/val_pred看可视化结果重点找三类坏案例漏检老鼠在但没框、误检背景被当成老鼠、框不准框住了但偏移大。漏检多说明召回不够可以降conf到 0.1 再看误检多说明模型把背景纹理当成了老鼠需要补负样本或提高conf。4.2 从混淆矩阵和 PR 曲线定位问题YOLO 训练完会自动生成confusion_matrix.png和PR_curve.png。混淆矩阵里如果background那一列数值高说明大量背景被误检成老鼠如果mouse行里background高说明漏检严重。PR 曲线看曲线下的面积曲线越靠右上越好。2295 张的数据量mAP50 能到 0.85 以上算正常如果只有 0.5 左右先回去查标签八成是格式或类别编号问题而不是模型不行。4.3 导出 ONNX 做一次跨框架验证训练框架里指标好看不代表部署没问题我习惯导出 ONNX 再用 onnxruntime 跑一张图确认输出形状和数值对得上。import onnxruntime as ort import numpy as np from PIL import Image sess ort.InferenceSession(best.onnx) img Image.open(test.jpg).resize((640, 640)) x np.array(img).transpose(2, 0, 1)[None].astype(np.float32) / 255.0 outs sess.run(None, {sess.get_inputs()[0].name: x}) print(outs[0].shape) # 期望 (1, 4nc, 8400)输出形状里4nc是框坐标加类别分数8400是三个尺度特征图展平后的候选框数。如果形状不对多半是导出时opset或dynamic参数没设对回去用yolo export modelbest.pt formatonnx opset12重新导。5. 老鼠数据集训练避坑5 个血泪踩坑记录5.1 标签类别编号从 1 开始导致全盘皆输现象训练 loss 正常下降但 mAP 始终接近 0推理时一个框都不出。原因标注工具默认类别从 1 开始而 YOLO 要求从 0 开始模型学到的类别索引和data.yaml里的names对不上。解决跑 2.2 的体检脚本看cls_counter的 key如果有 1 没有 0把所有标签文件的第一个数字减 1或者改data.yaml的names前面补一个占位类。这个坑我踩过两次每次都是训练了半天才发现。5.2 空标签文件被当成负样本现象验证集误检率异常高背景里到处是框。原因部分图像确实没有老鼠标注时生成了空.txtYOLO 会把空标签文件当成「这张图没有目标」的负样本但如果空文件比例过高比如超过 30%模型会倾向于预测背景反而在真有老鼠的图上漏检。解决统计空标签比例如果过高要么补充正样本要么在训练时用close_mosaic提前关掉增强让模型在后期专注正样本。5.3 图像和标签文件名大小写不一致现象训练时报No labels found但明明标签文件都在。原因图像是Mouse_001.JPG标签是mouse_001.txtLinux 下大小写敏感匹配不上。解决写个脚本统一转小写或者用Path.stem匹配时统一lower()。这个坑在 Windows 上开发、Linux 上训练时特别常见。5.4 小目标框归一化后宽高接近 0现象训练时警告ignoring degenerate boxes部分目标学不到。原因老鼠只占几个像素标注框宽高归一化后小于 0.001YOLO 在生成 anchor 时直接丢弃。解决提高输入分辨率到 960 或 1280让框的绝对像素变大或者改用带 P2 层的模型实在不行把极小框合并或剔除别让它们污染训练。5.5 验证集和训练集图像重复现象验证集 mAP 高得离谱部署后效果断崖式下跌。原因2295 张里可能有连拍或近似帧随机划分时同一只老鼠的相邻帧同时进了训练集和验证集造成数据泄漏。解决按图像相似度或拍摄时间分组后再划分保证验证集里的老鼠和训练集不重叠。用imagehash做感知哈希去重是个快办法。6. 把 2295 张用到极致小数据集上的增强与半监督技巧2295 张在目标检测里属于小数据集想再往上提点光调参不够得在数据层面做文章。我一般会做两件事一是离线增强扩样本二是用训练好的模型去伪标注未标注图像做半监督。离线增强不是简单开 Mosaic而是针对老鼠的姿态和光照做定向增强随机旋转 ±30 度模拟不同拍摄角度随机调整亮度对比度模拟昼夜随机遮挡模拟老鼠被杂物挡住。用 Albumentations 写一个增强管道把 2295 张扩到 8000 张左右再训练mAP 通常能涨 2 到 4 个点。import albumentations as A import cv2 transform A.Compose([ A.RandomRotate90(p0.3), A.Rotate(limit30, p0.5), A.RandomBrightnessContrast(0.3, 0.3, p0.5), A.CoarseDropout(max_holes8, max_height32, max_width32, p0.3), A.HorizontalFlip(p0.5), ], bbox_paramsA.BboxParams(formatyolo, label_fields[class_ids])) img cv2.imread(mouse.jpg) with open(mouse.txt) as f: boxes [list(map(float, l.split())) for l in f if l.strip()] bboxes [b[1:] for b in boxes] class_ids [int(b[0]) for b in boxes] out transform(imageimg, bboxesbboxes, class_idsclass_ids)BboxParams里formatyolo告诉 Albumentations 输入是归一化的xcycwh它会自动同步变换框。CoarseDropout模拟遮挡Rotate模拟角度变化这两个对老鼠这种姿态多变的目标准确率提升最明显。增强后的数据单独存一份别覆盖原图方便对比增强前后的效果。半监督的做法是先用 2295 张训练一个 baseline拿它去推理你手头其他未标注的老鼠图像把置信度高于 0.7 的预测框当伪标签和原数据混在一起再训一轮。这一步能把有效样本量翻倍但要注意伪标签的噪声置信度阈值别设太低0.7 是个比较稳的起点。我自己的习惯是每轮半监督后都拿固定验证集测一次涨了就保留掉了就回退别盲目堆数据。这套流程跑下来2295 张老鼠数据集足够撑起一个能用的检测模型剩下的就是根据你的实际场景调阈值和部署了。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑