从零构建猫情绪检测数据集:YOLO格式标注与模型训练实战

📅 发布时间:2026/10/2 3:37:56
从零构建猫情绪检测数据集:YOLO格式标注与模型训练实战
猫的情绪到底能不能被机器识别出来这个问题我在两年前第一次接触宠物行为分析项目时就想过。当时团队想做一个智能猫窝核心功能是根据猫的情绪状态自动调节环境灯光和播放安抚音频结果卡在了最基础的一步——怎么让模型知道眼前的猫是放松、紧张还是炸毛状态。市面上现成的宠物数据集大多只标注了品种、姿态或者简单的行为类别真正针对情绪这个维度的标注数据少得可怜。后来我们决定自己动手从零构建一套猫情绪检测数据集前后折腾了将近三个月标注了3200张图踩了无数坑也总结出了一些在公开教程里看不到的经验。这套数据集最终采用YOLO格式组织覆盖了猫的多种情绪相关行为表现可以直接用于目标检测模型的训练和微调。如果你也在做宠物行为识别、智能硬件或者动物福利相关的东西这套数据集的构建思路和使用方法应该能帮你省下不少时间。1. 猫情绪检测这件事为什么值得单独做一套数据集1.1 情绪检测和普通目标检测的本质差异普通的目标检测任务比如检测行人、车辆、交通标志类别定义非常清晰——一个人就是一个人一辆车就是一辆车边界明确标注一致性容易保证。但情绪检测完全是另一回事。猫的情绪不是一个可以直接观测的物理实体它是通过耳朵角度、瞳孔大小、尾巴姿态、身体蜷缩程度、胡须方向等多个视觉线索综合推断出来的。这就意味着标注者需要对猫的行为学有一定了解否则标出来的愤怒和恐惧可能完全混淆。我在构建数据集时遇到的最大挑战就是标注一致性问题。同一张猫飞机耳的图片有的标注者认为是恐惧有的认为是愤怒还有的认为是警觉。后来我们参考了国际猫科动物行为学的一些公开资料把情绪类别做了合并和重新定义最终确定了六类核心情绪标签放松、好奇、恐惧、愤怒、玩耍、警觉。每一类都有明确的行为特征描述作为标注依据比如恐惧必须同时满足耳朵后压、身体低伏、瞳孔放大中的至少两个特征。1.2 为什么是3200张这个量级很多人会问3200张够不够说实话对于六分类的目标检测任务来说3200张确实不算多。但关键在于数据质量和类别均衡度。我们最初的版本只有1800张训练出来的模型在愤怒和恐惧之间几乎无法区分mAP只有0.42。后来补充了1400张针对性采集的图片重点增加了容易混淆类别的样本mAP提升到了0.67。3200张的分布大致是这样的放松类约700张好奇类约600张恐惧类约550张愤怒类约450张玩耍类约500张警觉类约400张。可以看到恐惧和愤怒类的样本相对较少这是因为这两种情绪在自然场景下本身就不容易捕捉到需要大量筛选。如果你要基于这套数据集做迁移学习建议对样本较少的类别做过采样或者数据增强。1.3 这套数据集适合谁用这套数据集最适合三类人第一类是做智能宠物硬件的开发者需要模型实时判断猫的情绪状态来触发相应功能第二类是动物行为研究者想用计算机视觉方法辅助行为分析第三类是想学习目标检测但苦于找不到有趣数据集的初学者。对于第三类用户猫情绪检测比检测交通标志有意思得多而且能直观感受到模型从瞎猜到看懂的过程。注意这套数据集标注的是情绪相关行为表现不是猫的真实内心感受。模型学到的是视觉特征与行为标签之间的映射关系不要过度解读为猫真的在生气或开心。2. 数据采集与标注那些教程不会告诉你的细节2.1 图片采集渠道的取舍逻辑采集渠道直接决定了数据集的多样性和泛化能力。我们主要用了三个来源第一是公开的宠物图片社区筛选出包含完整猫身体且姿态清晰的图片第二是合作宠物医院和猫舍提供的监控截图第三是团队成员自己养的猫用手机在不同光照条件下拍摄。这里有个很容易被忽略的问题——背景多样性。如果所有图片都来自同一个猫舍背景高度相似模型很容易学到背景特征而不是猫的情绪特征。我们后来专门补充了大量家庭环境、户外、宠物医院等不同场景的图片确保背景分布足够分散。实测下来背景多样性对模型泛化能力的提升比增加同类场景图片数量更明显。另一个坑是图片分辨率。有些网络图片看起来清晰但实际分辨率只有300x200放大后细节全糊了。猫的耳朵角度、瞳孔变化这些关键特征在低分辨率下根本看不出来。我们最终设定的最低分辨率标准是640x480低于这个标准的全部丢弃。2.2 标注规范是怎么一步步磨出来的标注规范不是一开始就定好的而是在标注过程中不断修正的。第一轮标注我们只给了六个情绪标签没有详细的判定标准结果三个人标同一批图一致率只有62%。后来我们做了三件事来提升一致性第一编写了详细的标注手册每个情绪类别列出3-5个必须满足的视觉特征标注者必须对照手册逐条确认。第二引入了不确定标签遇到实在拿不准的图片就标为不确定后续由经验丰富的标注者复核。第三每周做一次标注一致性校验随机抽取50张已标注图片让所有人重新标计算一致率低于85%就停下来讨论分歧点。经过三轮迭代最终标注一致率稳定在91%左右。这个数字在情绪类标注任务中已经相当不错了毕竟有些图片连人看了都会犹豫。2.3 YOLO格式标注的具体操作和常见错误YOLO格式的标注文件是每张图片对应一个txt文件每行格式为类别编号 中心x坐标 中心y坐标 宽度 高度所有坐标都归一化到0-1之间。这个格式看起来简单但实际操作中有几个高频错误坐标没有归一化直接写了像素值宽度和高度写成了右下角坐标而不是宽高类别编号从1开始而不是从0开始一张图有多个猫时标注框重叠导致训练时正样本分配混乱我们用的是LabelImg做标注后来换成了CVAT因为CVAT支持多人协作和标注审核流程。标注完成后写了一个Python脚本做格式校验检查每个txt文件的坐标是否在0-1范围内、类别编号是否在有效范围内、是否有空文件等问题。这个校验步骤非常关键我们第一次训练时loss一直不下降排查了半天才发现有200多个标注文件的坐标没有归一化。import os def validate_yolo_annotation(annotation_dir, num_classes): errors [] for filename in os.listdir(annotation_dir): if not filename.endswith(.txt): continue filepath os.path.join(annotation_dir, filename) with open(filepath, r) as f: lines f.readlines() if len(lines) 0: errors.append(f{filename}: 空标注文件) continue for i, line in enumerate(lines): parts line.strip().split() if len(parts) ! 5: errors.append(f{filename} 第{i1}行: 字段数量错误) continue cls_id int(parts[0]) coords [float(x) for x in parts[1:]] if cls_id 0 or cls_id num_classes: errors.append(f{filename} 第{i1}行: 类别编号越界) if any(c 0 or c 1 for c in coords): errors.append(f{filename} 第{i1}行: 坐标未归一化或越界) return errors3. 数据集的组织结构与训练配置3.1 目录结构设计数据集的组织结构直接影响后续训练脚本的编写效率。我们最终采用的目录结构是这样的cat_emotion_dataset/ ├── images/ │ ├── train/ # 训练集图片约2560张 │ ├── val/ # 验证集图片约320张 │ └── test/ # 测试集图片约320张 ├── labels/ │ ├── train/ # 对应的YOLO标注文件 │ ├── val/ │ └── test/ ├── data.yaml # 数据集配置文件 └── README.md # 类别说明和标注规范训练集、验证集、测试集按照8:1:1的比例划分。这里有个细节需要注意划分时要保证同一只猫的图片不会同时出现在训练集和验证集中否则验证集的评估结果会偏乐观。我们是在采集阶段就给每只猫分配了唯一ID划分时按ID分组划分。3.2 data.yaml配置文件的关键参数path: ./cat_emotion_dataset train: images/train val: images/val test: images/test nc: 6 names: 0: relaxed 1: curious 2: fearful 3: angry 4: playful 5: alert这个配置文件看起来简单但nc和names的对应关系必须和标注文件中的类别编号严格一致。我们遇到过一个问题标注时用的是0-5的编号但配置文件里names的顺序写错了导致模型把恐惧学成了愤怒。排查这种问题非常痛苦因为loss曲线看起来完全正常只是类别预测全乱了。建议在训练前先用小批量数据做一次过拟合测试确认模型能正确学习类别映射。3.3 训练超参数的选择依据我们用的是YOLOv8s作为基线模型主要考虑是模型体积适中在边缘设备上也能跑得动。训练超参数方面输入分辨率设为640x640batch size设为16初始学习率0.01用了余弦退火调度。训练了200个epoch前50个epoch冻结主干网络后150个epoch全量微调。这里重点说一下数据增强的策略。猫情绪检测对几何变换比较敏感因为耳朵角度、尾巴姿态这些特征在翻转后可能失去物理意义。比如猫的尾巴向左摆和向右摆可能代表不同情绪水平翻转会破坏这种区分。所以我们只用了小幅度的随机缩放0.8-1.2倍、亮度对比度调整和轻微的旋转±10度没有使用水平翻转和大幅度的裁剪。实测下来加入适度的马赛克增强mosaic对提升小目标检测效果有帮助但概率不能太高我们设的是0.3。太高的话模型会过度依赖拼接图像的上下文信息在单张图片推理时表现下降。4. 模型训练中遇到的典型问题与排查过程4.1 类别混淆恐惧和愤怒为什么总是分不清训练到第80个epoch左右我们发现混淆矩阵里恐惧和愤怒之间的误判率高达35%。这两个类别在视觉特征上确实有重叠——都会出现耳朵后压、身体紧绷的表现。区别在于恐惧通常伴随身体低伏和后退姿态而愤怒更多表现为身体前倾和尾巴快速摆动。排查过程是这样的先可视化了一批误判样本发现大部分误判图片中猫的身体姿态被遮挡或者拍摄角度不佳导致关键区分特征不可见。然后我们做了两件事第一在标注规范中补充了如果关键区分特征不可见则标为不确定的规则把这类模糊样本从训练集中剔除第二在训练时对这两个类别使用了更高的分类损失权重让模型更关注难分样本。调整之后这两个类别的误判率降到了18%左右。虽然还不够理想但已经可用了。如果你的应用场景对这两个类别区分要求特别高建议进一步补充针对性样本。4.2 小目标检测效果差的解决思路数据集里有一部分图片是远景拍摄的猫在画面中占比很小检测效果明显差于近景图片。我们试过几种方案提高输入分辨率到1280效果有提升但推理速度下降太多用切片推理把大图切成小块分别检测再合并效果不错但工程复杂度高。最终采用的方案是在数据增强中增加随机缩放的比例让模型在训练时见到更多小目标样本。同时把YOLOv8的检测头换成了带辅助训练分支的结构在浅层特征图上增加了一个小目标检测头。这个改动让小目标类别的mAP提升了约6个百分点推理速度只下降了8%左右性价比可以接受。4.3 训练loss震荡的排查链路有一次重新训练时loss在前30个epoch震荡非常剧烈从2.3跳到5.1又跳回来。排查链路如下第一步检查数据加载。写了个脚本随机抽取batch中的图片和标注可视化发现有几张图片的标注框完全错位猫在左上角但标注框在右下角。原因是标注文件在复制过程中文件名和图片名没有严格对应导致图片和标注错配。第二步检查学习率。初始学习率0.01对于batch size 16来说偏大改成了0.005之后震荡幅度明显减小。第三步检查数据增强。发现马赛克增强的概率设成了0.8太高了导致一个batch里大部分都是拼接图分布和真实数据差异太大。降到0.3之后loss曲线平滑了很多。这三个问题叠加在一起导致排查花了大半天时间。教训就是训练前一定要做数据可视化检查不要假设数据一定是对的。5. 模型评估与部署的实操建议5.1 评估指标怎么看才有意义目标检测常用的评估指标是mAP但mAP高不代表模型在实际场景中好用。我们除了看mAP还会重点看三个东西混淆矩阵、各类别的PR曲线、以及实际推理时的可视化结果。混淆矩阵能直观看到哪些类别容易混淆PR曲线能看出在不同置信度阈值下的精确率和召回率权衡。对于猫情绪检测这种应用我建议把置信度阈值设得高一些0.5-0.6宁可漏检也不要误检。因为误检会导致智能硬件做出错误的响应比如猫明明很放松却播放了安抚音频反而可能吓到它。实际推理可视化是最重要的评估环节。我们会录一段猫的日常视频用训练好的模型逐帧推理然后人工观察模型的判断是否合理。很多时候mAP看起来不错但实际视频里模型会在猫快速移动时频繁切换预测类别这种不稳定性在静态指标里是看不出来的。5.2 部署到边缘设备的注意事项如果要把模型部署到智能猫窝、宠物摄像头这类边缘设备上有几个实际问题需要提前考虑。首先是模型量化YOLOv8s的FP32模型大约22MB量化到INT8后可以压到6MB左右推理速度也能提升2-3倍。但量化会带来精度损失我们实测mAP下降了约3个百分点需要根据具体场景权衡。其次是输入分辨率。640x640在服务器上跑没问题但在低功耗芯片上可能帧率不够。我们试过降到416x416mAP下降了约8个百分点但帧率从12fps提升到了28fps。如果你的应用场景对实时性要求高可以接受一定的精度损失。最后是后处理逻辑。模型输出的原始检测框需要做NMS非极大值抑制和置信度过滤这些操作在边缘设备上也会消耗计算资源。建议把NMS的IoU阈值设成0.45左右既能去掉重复框又不会误删相邻的猫。5.3 持续迭代的数据闭环模型部署上线后真正的挑战才开始。实际场景中会遇到训练集里没有的猫品种、光照条件、拍摄角度模型的表现会下降。我们建立了一个数据闭环设备端把低置信度的推理结果和对应的图片回传人工审核后把确认错误的样本加入训练集定期重新训练模型。这个闭环跑通之后模型每迭代一次线上误判率大约下降5-8个百分点。跑了四轮之后模型在实际场景中的准确率从最初的72%提升到了89%。这个过程中最重要的是建立高效的标注和审核流程否则回传的数据堆积如山却没人处理闭环就断了。6. 这套数据集还能怎么扩展6.1 从情绪分类到行为序列分析目前的数据集是单帧图片标注模型只能判断某一时刻的情绪状态。但猫的情绪是连续变化的单帧判断容易出现抖动。一个自然的扩展方向是引入时序信息用视频片段而不是单帧图片来训练。可以基于现有的YOLO检测结果加上一个轻量级的时序模型比如LSTM或Transformer来平滑预测结果。这个方向我们做了一些初步实验用5帧连续检测结果作为输入情绪状态切换的准确率比单帧提升了约12个百分点。但时序模型的训练数据标注成本更高需要标注整个视频片段的情绪变化曲线目前还在探索阶段。6.2 多模态融合的可能性单纯依靠视觉信息判断猫的情绪有天然上限有些情绪状态在视觉上表现不明显但可以通过声音呼噜声、哈气声、叫声频率来辅助判断。我们尝试过把音频特征和视觉特征做简单的拼接融合在部分类别上有提升但整体效果还不够稳定。另一个思路是结合猫的生理数据比如智能项圈采集的心率和活动量。这些数据在情绪激动时会有明显变化可以作为视觉判断的补充。不过多模态数据的采集和同步本身就是个工程难题需要硬件层面的配合。6.3 跨物种迁移的可行性这套数据集的构建方法论其实可以迁移到其他宠物比如狗的情绪检测。狗的情绪表达方式和猫有相似之处尾巴姿态、耳朵角度但也有明显差异狗更依赖面部表情。如果要做狗的情绪数据集标注规范需要重新设计但YOLO格式的组织方式、训练配置、评估流程都可以直接复用。我们在猫数据集上训练好的模型在狗的数据上做微调只用了约800张标注图片就达到了可用的效果。这说明视觉特征层面存在一定的跨物种通用性对于想快速搭建其他宠物情绪检测系统的团队来说这是一个值得尝试的起点。最后分享一个在实际操作中总结的小技巧标注情绪类数据时不要一个人闷头标到底。每隔一小时停下来随机抽10张自己刚标过的图片重新标一遍看看两次标注是否一致。如果一致率低于90%说明你的标注标准在漂移需要重新对照标注手册校准。这个习惯能帮你省下大量返工时间我们团队就是靠这个方法把标注一致率从最初的62%拉到了91%。