猪行为识别数据集实战:1272张图从COCO转YOLO到92.6%复现
发布时间:2026/9/23 22:31:24 作者:尧图编辑部 阅读量:1,286

简介这份猪圈猪只行为识别数据集面向智慧养殖、动物行为分析与计算机视觉方向的研究者及算法工程师可用于构建猪只日常行为分类模型覆盖喝、吃、睡觉、站立等典型动作平均正确识别率约92.6%适合目标检测与行为识别任务的训练、验证与迁移学习。资源包共1275个文件其中1272张jpg图像与3个json标注文件压缩包约85.57MBjson采用coco格式可直接对接主流检测框架省去格式转换环节。目前已有214人学习下载具备一定参考热度。图像按视频帧序列命名覆盖多段猪圈监控场景便于按时间序列划分训练集与测试集读者可据此复现行为识别流程、调整类别映射并评估模型在真实养殖环境下的表现为后续部署与优化提供数据基础。1. 猪圈里的猪行为识别数据集1272 张图、92.6% 识别率这套数据到底能不能直接上手猪行为识别这件事真正卡住人的从来不是模型结构而是数据。你打开搜索引擎搜「行为识别」跳出来的多半是人体的、监控场景的、体育动作的跟猪圈里那几头猪的吃喝睡站没半点关系。这套数据集的价值就在这儿1272 张真实猪圈场景图片标注了喝、吃、睡觉、站立等行为类别官方给出的平均正确识别率在 92.6%标注格式是 coco json。对做智慧养殖、动物福利监测、边缘端行为分析的团队来说它省掉的是最贵的那一步——从零采集和标注。这篇文章不讲空泛概念只讲这套数据拿到手之后怎么读、怎么转、怎么训、怎么避坑以及 92.6% 这个数字在你自己场景里还能不能保住。2. 先看懂 coco json 标注1272 张图里到底存了什么2.1 coco json 的字段结构和猪行为类别的对应关系coco json 不是一张表而是五个顶层字段拼起来的字典images、annotations、categories、info、licenses。做行为识别的人最容易犯的错是把它当成纯检测数据直接喂给检测头结果发现「喝」和「吃」两个类别在空间上高度重叠模型学不动。先看清楚这套数据是怎么组织的。import json with open(pig_behavior/annotations/instances.json, r, encodingutf-8) as f: coco json.load(f) # 顶层字段 print(coco.keys()) # dict_keys([info, licenses, images, annotations, categories]) # 类别表行为类别在这里 for c in coco[categories]: print(c[id], c[name], c.get(supercategory)) # 1 drink behavior # 2 eat behavior # 3 sleep behavior # 4 stand behavior # 单张图的标注数量分布 from collections import Counter per_img Counter(a[image_id] for a in coco[annotations]) print(图片总数:, len(coco[images])) print(标注总数:, len(coco[annotations])) print(单图最多标注数:, max(per_img.values()))逻辑说明categories里的name就是行为标签supercategory一般写 behavior 或 action用来和普通目标检测类别区分。annotations里每条记录包含image_id、category_id、bbox、area、iscrowd。参数上要重点看iscrowd猪圈场景里猪只互相遮挡极多如果iscrowd1的比例超过 15%后面训练时就要考虑用 crowd 忽略策略否则框回归会被带偏。2.2 用 pycocotools 做一次数据体检别急着开训拿到任何 coco json我一般先跑一遍体检脚本而不是直接转 YOLO。体检要看四件事类别是否均衡、框的宽高比分布、是否有零面积框、图片路径是否全部可读。from pycocotools.coco import COCO import numpy as np coco COCO(pig_behavior/annotations/instances.json) # 1. 类别均衡度 cat_ids coco.getCatIds() for cid in cat_ids: ann_ids coco.getAnnIds(catIds[cid]) print(coco.loadCats(cid)[0][name], len(ann_ids)) # 2. 宽高比分布猪的行为框通常偏扁 ratios [] for ann in coco.loadAnns(coco.getAnnIds()): x, y, w, h ann[bbox] if h 0: ratios.append(w / h) ratios np.array(ratios) print(宽高比 中位数/均值:, np.median(ratios), ratios.mean()) # 3. 零面积框 bad [a[id] for a in coco.loadAnns(coco.getAnnIds()) if a[area] 0] print(零面积框数量:, len(bad))逻辑说明类别均衡度决定你要不要用重采样或 focal loss。宽高比中位数如果明显大于 1说明猪只多为侧躺或趴卧锚框尺寸要相应调扁。零面积框必须清掉否则训练时 loss 会出现 nan。参数上area是 coco 官方按w*h算的但有些标注工具会写错所以要以bbox重算为准。提示1272 张图属于小数据集体检阶段发现的任何类别不均衡都会在训练后期被放大成某几个行为识别率骤降。3. 把 coco json 转成 YOLO 格式脚本、参数和四个边界坑3.1 转换脚本从 coco bbox 到 YOLO txt 的完整实现现在主流做法还是拿 YOLOv8 或 YOLOv5 训练自己的数据集所以 coco json 转 YOLO txt 是绕不开的一步。YOLO 格式要求每行class_id x_center y_center width height且全部归一化到 0~1。下面这个脚本我用了很多次处理过猪、牛、羊多个养殖数据集。import json, os from pathlib import Path def coco2yolo(json_path, img_dir, out_dir): with open(json_path, r, encodingutf-8) as f: coco json.load(f) # 类别 id 重映射为 0 起始连续整数 cats sorted(coco[categories], keylambda x: x[id]) cat_map {c[id]: i for i, c in enumerate(cats)} names [c[name] for c in cats] img_map {img[id]: img for img in coco[images]} Path(out_dir).mkdir(parentsTrue, exist_okTrue) # 按 image_id 聚合标注 from collections import defaultdict anns defaultdict(list) for a in coco[annotations]: anns[a[image_id]].append(a) for img_id, img in img_map.items(): w, h img[width], img[height] lines [] for a in anns.get(img_id, []): x, y, bw, bh a[bbox] # 边界裁剪防止越界 x max(0, min(x, w - 1)) y max(0, min(y, h - 1)) bw min(bw, w - x) bh min(bh, h - y) if bw 1 or bh 1: continue xc (x bw / 2) / w yc (y bh / 2) / h nw bw / w nh bh / h lines.append(f{cat_map[a[category_id]]} {xc:.6f} {yc:.6f} {nw:.6f} {nh:.6f}) stem Path(img[file_name]).stem with open(os.path.join(out_dir, stem .txt), w) as f: f.write(\n.join(lines)) with open(os.path.join(out_dir, classes.txt), w) as f: f.write(\n.join(names)) print(类别顺序:, names) coco2yolo( pig_behavior/annotations/instances.json, pig_behavior/images, pig_behavior/labels )逻辑说明cat_map把原始 category_id 重映射成从 0 开始的连续整数这是 YOLO 的硬性要求不重映射会出现类别索引跳号导致训练报错。边界裁剪那几行是血泪经验猪圈图片里猪只经常贴着画面边缘标注框会超出图像边界不裁剪的话归一化后坐标大于 1YOLO 会直接忽略该框甚至报错。bw 1 or bh 1过滤掉极小框避免噪声标签污染训练。参数说明xc/yc是框中心点归一化坐标nw/nh是宽高归一化值保留 6 位小数足够。classes.txt的顺序必须和cat_map一致后面写 data.yaml 时names要按这个顺序填。3.2 data.yaml 怎么写以及训练前必须核对的三个路径转换完只是第一步YOLO 训练读的是 data.yaml。这个文件写错一个路径训练能启动但 mAP 全是 0属于最隐蔽的翻车点。path: /data/pig_behavior train: images/train val: images/val test: images/test nc: 4 names: 0: drink 1: eat 2: sleep 3: stand逻辑说明path是数据集根目录train/val/test是相对路径。nc必须等于类别数names的键必须从 0 连续。常见错误是names写成列表但顺序和classes.txt不一致模型会把「喝」学成「吃」。参数说明1272 张图建议按 7:2:1 划分即约 890 张训练、254 张验证、128 张测试。如果某些行为样本特别少划分时要用分层抽样保证每个 split 里四类行为都有。注意划分完一定要写脚本核对 train/val/test 三个目录下的图片数和标签数是否一一对应缺标签的图片会被 YOLO 当成纯背景图直接拉低召回。4. 用 YOLOv8 训练这套猪行为数据集参数怎么设、92.6% 怎么复现4.1 从预训练权重起步的最小训练命令小数据集不要从零训这是铁律。1272 张图从零训模型根本学不出「喝」和「吃」的细微姿态差异。正确做法是加载 COCO 预训练权重做迁移学习。yolo detect train \ data/data/pig_behavior/data.yaml \ modelyolov8s.pt \ epochs150 \ imgsz640 \ batch16 \ lr00.01 \ lrf0.01 \ patience30 \ cacheTrue \ projectruns/pig \ nameexp1逻辑说明modelyolov8s.pt是速度和精度的平衡点猪行为识别不需要超大模型n 或 s 足够。epochs150配合patience30验证集 30 轮不提升就早停避免过拟合。cacheTrue把图片缓存到内存1272 张图完全放得下能显著加快训练。参数说明lr00.01是初始学习率迁移学习常用值lrf0.01是最终学习率系数配合余弦退火。imgsz640是标准输入尺寸如果猪只目标偏小可以提到 800但显存要够。batch16在 8G 显存上跑 yolov8s 比较稳。4.2 影响 92.6% 识别率的四个关键参数官方给的 92.6% 是在特定划分和参数下测出来的你自己复现时如果差几个点先查这四个参数。参数推荐值作用调错后果imgsz640输入分辨率太小丢小目标太大显存爆conf0.25推理置信度阈值太高漏检太低误检iou0.7NMS 重叠阈值太低同类框被误删mosaic1.0马赛克增强关闭后小数据集易过拟合逻辑说明conf和iou是推理阶段参数训练时用默认即可但评估 mAP 时这两个值直接决定最终数字。猪只互相遮挡多iou设太低会把挨着的两头猪的框合并成一个。mosaic增强对小数据集几乎是必开项它把四张图拼成一张等效扩充了场景多样性。参数说明评估时用yolo detect val跑一遍看mAP50和mAP50-95两个指标。行为识别更关注mAP50因为框的位置精度对行为分类影响没那么大。如果mAP50到 90% 以上但mAP50-95只有 60%说明框回归还不够准可以加box损失权重。4.3 训练曲线怎么看判断过拟合和欠拟合的信号训练跑起来不是等结果中间要盯曲线。runs/pig/exp1/results.csv里有每轮的 loss 和 mAP。import pandas as pd df pd.read_csv(runs/pig/exp1/results.csv) df.columns df.columns.str.strip() # 看最后 10 轮的验证 mAP 和训练 loss print(df[[epoch, train/box_loss, val/box_loss, metrics/mAP50(B), metrics/mAP50-95(B)]].tail(10))逻辑说明如果train/box_loss持续下降但val/box_loss开始上升就是过拟合要加数据增强或减模型容量。如果两个 loss 都居高不下是欠拟合要加轮数或提学习率。metrics/mAP50(B)是行为识别的核心指标稳定在 0.92 附近说明复现成功。参数说明results.csv的列名带空格读进来先strip()。看曲线不要只看最后一轮要看最后 20 轮的波动波动大说明 batch 太小或学习率太高。5. 猪行为识别落地避坑五条踩过的坑和排查路径5.1 坑一喝和吃识别混淆mAP 卡在 80% 上不去现象训练完发现「喝」和「吃」两个类别的混淆矩阵里互相误判严重其他两类正常。原因猪喝水和吃食的姿态高度相似都是低头靠近地面或料槽单帧图像上差异极小。数据集里如果这两类的拍摄角度单一模型只能靠背景水槽 vs 料槽区分泛化差。解决一是引入时序信息用连续几帧判断头部运动方向二是数据层面补充不同角度的喝和吃样本三是训练时对这两类加大分类损失权重。我一般会先做类别权重重平衡再考虑上时序模型。5.2 坑二验证集 mAP 很高换到新猪圈全崩现象在自己划分的验证集上 mAP50 有 92%部署到另一个猪圈识别率掉到 60% 以下。原因1272 张图大概率来自有限几个猪圈背景、光照、栏杆样式高度一致。模型学到了背景捷径而不是猪的行为特征。解决划分验证集时按猪圈或时间段划分而不是随机划分。随机划分会让同一场景的图同时出现在训练和验证集指标虚高。部署前一定要在目标猪圈采一批图做域适应测试。5.3 坑三夜间红外图像识别率断崖下跌现象白天识别正常夜间红外摄像头画面下睡觉和站立几乎分不开。原因训练集里夜间样本占比过低模型没见过红外成像的灰度分布。猪躺卧时红外图像上轮廓模糊和站立的区分度下降。解决统计训练集的光照分布夜间样本不足就补采。推理阶段可以对红外图像做直方图均衡化预处理提升轮廓对比度。如果夜间是刚需建议单独训一个红外分支。5.4 坑四coco json 里 iscrowd 标注被当成正常框训练现象训练 loss 正常但密集猪只场景下框大量重叠NMS 后只剩一个框。原因coco json 里iscrowd1的标注表示该区域是人群/畜群不要求精确框。转换脚本如果没过滤这些框会进入训练教模型把多只猪当成一只。解决转换时跳过iscrowd1的标注或在 YOLO 里把它们标成 ignore 区域。体检阶段先统计iscrowd比例超过 10% 就要处理。5.5 坑五图片和标签文件名不一致导致静默丢样本现象训练正常启动但训练集图片数比预期少模型效果差。原因coco json 里file_name可能带路径或扩展名大小写不一致转换脚本用stem生成标签名和实际图片名对不上YOLO 找不到标签就跳过该图。解决转换后写脚本核对图片和标签的一一对应关系缺标签的图片要么补标签要么从训练集移除。这个检查我每次都会跑属于后悔药级别的步骤。from pathlib import Path imgs {p.stem for p in Path(images/train).glob(*.jpg)} labs {p.stem for p in Path(labels/train).glob(*.txt)} print(缺标签:, imgs - labs) print(缺图片:, labs - imgs)6. 把 92.6% 变成你自己的数字验证方法与一个提点技巧数据集给的是起点不是终点。真正决定这套猪行为识别能不能落地的是你能不能在目标场景里把识别率稳住。验证方法上我习惯做三件事第一按猪圈和时间段做交叉验证而不是随机划分这样得到的指标才接近真实部署第二单独统计每个行为类别的召回率喝和吃这两个易混类别要重点看第三用混淆矩阵定位误判方向是喝被判成吃还是站立被判成睡觉方向不同优化手段完全不同。提点技巧上分享一个我常用的后处理策略对连续视频帧做行为投票。单帧识别率 92.6%但如果对连续 5 帧的识别结果做多数投票稳定行为的识别率能再提 2 到 3 个点。猪的行为本身有持续性不会一帧喝一帧吃利用这个先验能压掉大量抖动误判。from collections import Counter def vote_smooth(frame_preds, window5): # frame_preds: 每帧的类别 id 列表 smoothed [] for i in range(len(frame_preds)): start max(0, i - window // 2) end min(len(frame_preds), i window // 2 1) window_preds frame_preds[start:end] most_common Counter(window_preds).most_common(1)[0][0] smoothed.append(most_common) return smoothed逻辑说明window5是经验值太小压不住抖动太大行为切换会延迟。参数上要根据实际帧率调25fps 下 5 帧约 0.2 秒行为切换响应足够快。这个后处理不改变模型只在推理侧加一层成本极低。最后说个我自己的习惯每次拿到新数据集先花半天做体检和可视化把标注框画到原图上逐类看一遍。这半天能省掉后面几天的调参玄学。猪行为识别这个方向数据质量比模型结构重要得多1272 张图不算多但用对了92.6% 是能摸到的。希望帮到你。本文还有配套的精品资源点击获取