
猫情绪识别这两年一直是个很微妙的方向——听起来像是个宠物爱好者的浪漫想象但真做起来你会发现它同时踩中了目标检测、行为识别、小样本学习好几个硬骨头。我手里这套3200张的YOLO宠物行为数据集定位就很明确用YOLO系列模型直接对猫的行为姿态做检测和分类把“伸懒腰”“飞机耳”“炸毛”“攻击准备”这类典型情绪状态框出来。文章会围绕数据集从样本设计、标注规范、训练调参到踩坑记录一路展开希望给想入坑这类细粒度动物行为检测的同行省点时间。1. 猫情绪检测为什么看着简单做起来处处是坑做猫情绪检测这件事难的不是“有没有数据集”而是默认你熟悉一套完全不同的数据逻辑。和人脸情绪识别不一样猫的情绪表达高度依赖组合信号耳朵角度、瞳孔变化、尾巴摆动速度、叫声频率、身体重心高低这些信号叠加在一起才构成人类能直观感受到的“它生气了”或“它很紧张”。而目标检测模型天然只吃空间特征你给它一张图它要同时回答“猫在哪”和“猫此刻处于什么情绪状态”两个问题这就决定了你不能照搬通用的姿态识别方案必须老老实实按检测任务的规则来设计数据。1.1 猫的情绪都写在脸上但算法不一定读得懂先说说为什么通用的人脸情绪方案套不上来。人有非常标准化的表情单元比如FACS系统眉头上扬、嘴角下撇都是可量化的动作单元所以人脸情绪数据集能把“开心”“悲伤”拆得很细。猫虽然也有耳朵、胡须、眼睛这些结构但猫面部的肌肉运动幅度远小于人耳朵角度的一个微小变化可能就代表完全不同的情绪信号。比如“飞机耳”耳朵向两侧压低、往后贴在恐惧和高强度警惕状态都会出现单独看一张静态图模型很容易把“害怕得发抖”和“准备扑咬”混在一起。这也是为什么纯粹做分类模型比如ResNet直接输出情绪类别在猫身上效果很飘——分类网络倾向于抓全局纹理特征它分不清炸毛的蓬松感到底是“愤怒”还是“寒冷”换句话说它学到的是猫的样子不是猫的状态。所以最终我选定了目标检测路线。检测和分类有一个本质差异检测会先定位到猫的区域再对区域内特征做判断相当于模型被迫聚焦在“这只猫”本身而不是整张图的背景、沙发纹理、光线阴影这些干扰物。对情绪判断来说检测天然就把“猫在哪”和“猫怎么了”绑定在一起既输出了位置框又输出了行为类别一套标注两种用途后续不管你只是想统计某只猫的情绪占比还是想做巡检系统自动报警都能直接复用这个检测结果。1.2 3200张规模合不合理够不够用数字确实不算大相比COCO这种几十万张的数据集3200张放在迁移学习数据增强的背景下属于“小而精准”的范畴。YOLO类模型有一个特点它的骨干网络已经在COCO这样的大规模数据集上预训练过骨干学到的底层纹理、边缘、形状特征可以直接迁移到猫身上我们在做的是“在NeckHead层微调——教模型区分猫的耳朵、尾巴、躯干的组合姿态”而不是从零学什么是猫。3200张如果类别设计合理、各类别分布均匀、每张图的标注质量都有保障完全能跑出一个可用的检测器真正让人翻车的地方往往不是数量而是类别混乱、样本重复度高、背景单一导致模型过拟合到场地特征。我手里这3200张设计思路是按“行为-情绪”联合状态直接做类别而不是先单独检测关键点再推断情绪。原因很实际只要细粒度关键点耳朵、尾巴尖、爪子稍微标注偏差一点后续情绪推理就错误被放大还白白拉高了维护成本。数据直接下沉到行为层面模型输出的是“这只猫在做什么、处于什么状态”从工程交付的角度讲更省事效果也更直观。2. 3200张数据集的构建全过程从样本设计到标注落地做数据集最容易犯的错是一开始就在纠结“我该去哪下载图片”上来就想堆数量最后堆出一堆全网重复图、网图水印图、分辨率忽高忽低的残次品。我的流程是先定义清楚这个数据集到底要解决什么场景的问题然后才去采集和清洗。2.1 样本设计情绪类别到底怎么切才不打架我把3200张按行为状态切成了基础情绪组大纲上分五类放松/平静常见的卧姿、理毛、缓慢甩尾、眯眼半睁特征是身体舒展、耳朵竖立偏前、瞳孔不扩张。警觉/好奇双耳直立向前、瞳孔微扩张、尾巴笔直竖起或末端微弯身体重心前移往往盯着某个方向。焦虑/紧张耳朵向两侧平展飞机耳、瞳孔扩张、尾巴夹紧或快速抽动、身体压低可能伴随舔嘴唇和来回踱步。攻击/防御准备弓背炸毛、尾巴竖直蓬松、瞳孔缩小到针尖状、身体侧对目标、有作势欲扑的前倾姿态。伸懒腰/状态转换前爪前探、后腿蹬直、背部下塌呈拱形这是非常容易被误标成“攻击准备”的类别两者的背部曲线和尾巴状态差异需要单独用连续帧区分。这个划分不是随便拍的。我复盘过大量养护场景发现“放松”和“警觉”是最容易被新手混淆的因为很多猫在放松时眼睛半闭但耳朵依然竖着我会在采集时额外给这批样本做侧视图和正视图的打散处理避免模型只学会看“眼睛大小”。另外“伸懒腰”这个类别加入也是很关键的一步——如果省略它模型会把伸懒腰的高背弓形误判成“攻击/防御准备”在真实场景里出现大量误报。数据集里类别之间如果咬得太死纯靠模型自己学边界是很痛苦的事不如在样本设计阶段就把语义距离拉开。2.2 数据采集渠道和清洗策略这3200张来自三个部分混合公开宠物比赛图库中用脚本筛选的高质量侧拍/俯拍图、自己养的几只猫在不同时间不同光照下拍的照片大约占20%、以及在一家宠物店和猫咖现场拍摄的场景图。采集时我会为每张图额外记录一个来源批次号后期一旦发现某个场景的图占据了压倒性比例就能溯源并做平衡。清洗环节我做了三步每一步看着简单但都直接影响后续训练分辨率过滤统一过滤掉长边低于800像素的图不然缩放到训练尺寸后猫的耳朵边缘会糊情绪特征直接消失。明显误标修正倒不是说标注框画错而是原图本身信息不足比如一只背光到只剩轮廓的猫人的肉眼都判断不了情绪状态模板却硬标了一个“警觉”这种图我全部剔除。原则是人的肉眼都看不出来的状态就不该盖章成为标签。画面元素冲突检测猫的小便姿态在侧视角度下很容易和伸懒腰混淆凡是存在这种语义模棱两可的单帧图除非能判断出明确后腿姿态否则我也不收进最终集合——这属于“同一帧到底算哪个类”的源头歧义留到后期只会让损失曲线反复震荡。2.3 YOLO格式标注规范和质检流程标注格式一句话就能说清楚每张jpg图对应一个同名txt每行五个数字依次是class x_center y_center width height坐标和宽高都归一化到0到1之间。框的取值不需要精确到像素级但中心点绝不能偏离身体核心区域。我用LabelImg逐张画框说实话这个工作非常磨人。3200张图如果全是单人标注光画框就得画到崩溃我拆成了两次标注加一次仲裁的方式先由三位标注同学分别独立对同一批图做初标然后我每个类别抽样比对IoU一致性对边界框IoU低于0.7的图重新开会讨论约定——“耳朵尖该不该进框”“尾巴尖要不要包含在框内”。最终确定的约定是框体覆盖颈部到尾巴根部耳朵尖和四肢允许部分出框因为情绪主要取决于躯干和头颈的相对姿态尾巴末端反而会因为甩动频繁形成不稳定干扰。这个看似很小的规范直接影响后续模型对“飞机耳”这类特征的感知。质检上我还会额外做一轮“类别旋转检验”随机抽取每类100张把图水平翻转后丢给标注员重新判断类别如果翻转后标注员给出和原图不同的标签说明这张图本身的情绪表达和位置方向高度耦合比如猫因为侧对镜头炸毛翻过来看起来像伸懒腰这种图同样容易被模型当成bug来学直接做删除或归入不确定样本处理。3. YOLO训练实操选型、配置与损失收敛数据集落地后按我个人的习惯是直接选YOLO系模型具体版本我对比下来认为YOLOv8是平衡精度和推理速度的低风险选择。YOLOv8在Neck部分用C2f结构替换了以往的C3结构在保证特征融合密度的情况下梯度流更清晰直接效果就是小目标你画面里相对较小的猫召回率比v5有明显改善而且官方库训练生态完整不必去造重复的轮子。3.1 环境准备和基础配置环境没什么神秘的有张卡就行。我用的是单张约8GB显存的卡训练整个训练环节的存储开销最大的是缓存增强后的样本。我的配置大概是这样模型YOLOv8m比n和s大一些保证耳朵、瞳孔这些细粒度特征有通道去表达输入尺寸640×640这个尺寸对猫这种中等体型目标很友好长边统一缩放不会把猫压到几十个像素导致情绪特征完全丢失batch size16受显存限制配合梯度累积等效到64优化器SGD初始学习率0.01配合余弦退火训练轮数300轮配合早停patience30如果是不想折腾配置的人直接用YOLOv8官方仓库的默认训练脚本改一下数据集yaml的路径就能跑起来但有几个隐藏参数要自己调后面我会单独讲。注意这里的“默认能跑”和“效果好”是两回事。3.2 数据划分和增强策略我先按8:1:1切了train/val/test并且保证每个类别在每个集合中的比例和总体保持一致——用代码做一下按类别的分组抽样一般是sklearn的train_test_split配合stratify参数这一步能省掉后续大量因为“验证集里只有8张攻击图导致验证损失来回弹跳”的纠结。增强策略上YOLO官方默认会开启mosaic、随机仿射变换、HSV扰动这三板斧对宠物场景非常适用但有两个地方要按数据集调整Mosaic拼图虽然能丰富上下文但猫的情绪检测非常依赖单个目标的结构完整性如果四张图拼在一起每张猫都只剩一半身体耳朵和尾巴的比例关系就被打断了。我在前50轮把mosaic关闭先用纯样本把骨架训稳50轮后再打开做细节扰动损失下降曲线明显更平滑。HSV扰动中饱和度扰动幅度我会加大一点。猫的毛色从纯白到纯黑跨度极大训练数据里黑色猫和白猫的高光细节差异非常影响耳朵轮廓识别加大饱和度扰动相当于让模型对毛色变化更不敏感把注意力放到结构特征上。3.3 训练过程中我盯的三类指标训练不是丢进去等epoch结束就行。我每10个epoch存一次checkpoint重点盯三个指标训练损失和验证损失之间的gap如果gap持续拉大到2倍以上而mAP不再涨基本可以断定过拟合我会回到数据层面看是不是某个类别占了绝对多数或者增强强度是否过猛。按类别的mAP0.5只看整体mAP是会被平均成绩骗的。有时候整体mAP漂亮但点开分类明细发现“攻击/防御准备”类别mAP只有0.3这就是典型类别不平衡信号需要针对性补样本或调整类别权重。混淆矩阵我每次验证都导出混淆矩阵重点关注伸懒腰和攻击准备之间的互相污染程度。如果这两个一直在彼此串说明标注规范里“背部曲线”的约定没在图集里形成稳定区分我会直接翻数据再校对而不是盲目加训练轮数。最终我在验证集上的成绩大概在mAP0.5达到0.87左右mAP0.5:0.95在0.58附近这个成绩对细粒度情绪状态来说已经够用。坦白讲如果你只想检测“猫有没有生气”分数会高得多一旦拆成五种细腻状态平均分被“紧张”这个难样本类别拖低非常正常别慌。4. 训练和推理阶段的踩坑记录这五个问题最隐蔽这部分的内容看起来像是一些琐碎细节但实际每一个都需要花掉你不少肉眼检查时间。我按踩坑顺序逐条写出附带我最终的解决方式。4.1 标注框偏大导致的情绪特征稀释第一次训练完发现“警觉/好奇”的召回率低得异常回去看标注才发现部分标注员习惯性地把框拉大把猫周围的沙发、靠垫都包进框里了。框不等于物体边缘框越大模型在提取特征时越会被背景信息干扰等于精神涣散。按照我的经验框体的边界应该紧贴猫的颈根和尾根宁可让耳朵出框也不能大范围圈进环境。对这个问题我加了半自动修正脚本对训练集中每个gt框做轻微的宽高收缩中心不动宽高各乘0.9再配合人工抽查同一个类别mAP能涨3到4个百分点。4.2 一张图里出现多只猫的处理宠物店场景里经常一帧出现四五只猫这时候情绪标注的边界很微妙。我的做法是按“只给画面主猫做框”的原则处理每张图最多标注3个主体其他猫如果不清晰就放弃标注。但如果画面里多只猫都清晰且情绪状态不同我会尽量同时标注因为这是天然的困难样本对模型学会“区分不同个体的情绪差异”非常有用。需要注意的坑是一张图里如果有两只猫挨得很近彼此遮挡严重标注框之间可能出现大面积重叠。这种情况下我会直接放弃其中一只的重叠标注因为YOLO的训练逻辑需要两个框各自与anchor匹配重叠框会让后处理阶段的NMS死锁训练损失正常但预测时不断漏检。4.3 黑猫的怨恨暗色毛发的特征丢失测试时发现黑猫的检测效果普遍比橘猫、白猫差一大截。不是因为YOLO对毛色有偏见而是640×640输入下暗色毛皮和阴暗背景的纹理对比度极低耳朵轮廓几乎融入背景。我的解决办法不是换更强的模型而是从数据层面增加“低光照下的黑猫侧拍图”同时在预处理pipeline里加了一层自适应直方图均衡化只用于推理前预处理把暗部细节的对比度拉出来。效果立竿见影黑猫的mAP从0.61提到0.79。这个坑说明一个道理在很多真实场景里瓶颈不是模型是你没采集到足够挑战性的样本。4.4 飞机耳与伸懒腰的终极混淆前面说了这个类是设计时的头疼点训练后果然还是重灾区。分析混淆矩阵后发现两张图如果同为侧视角背部弓起的轮廓几乎一致模型完全没有线索区分区别在于攻击准备状态尾巴明显蓬松且竖直而伸懒腰的尾巴是自然垂下的。解决方式从两个方向下手一是在标注规范里强制要求“伸懒腰类别必须能看到尾巴或后腿的延展状态”否则不给标签二是在数据增强里适度随机裁剪掉部分尾巴区域强迫模型去学躯干和头部角度这条次要线索。经过这轮处理两类别的互混比例下降了约40%。4.5 部署阶段的batch推理与置信度博弈训练结束后落到实际推理我发现置信度阈值必须重新校准。测试集上0.25的置信度表现良好但到真实宠物监控画面里因为场景光照复杂这个阈值会产生大量“警觉/好奇”的误报。最终我选择了给不同类别设置独立阈值确定性强的攻击状态阈值放低到0.3宁可多报不可漏报而放松/伸懒腰这类低业务风险类别阈值拉到0.5减少无效告警。工业落地的经验就在这里——mAP是指标的参考但业务上你要自己学会用置信度做风险的二次分级。5. 数据集的边界在哪里后续还能怎么挖3200张不是终点它更像是地基。你必须清醒认识到这套数据的适用边界它更偏向室内和半室内场景室外强光、雨雪天气、猫迅速奔跑的运动模糊状态覆盖极少。如果你要部署的场景是室外流浪猫监测那这套集子只能当预训练权重需要在目标场景里再做至少几百张标注微调。5.1 从静态图到视频时序的延展单张静态图里情绪判断其实是不稳定的很多状态依赖前后几帧的上下文。比如“尾巴快速抽动”在单帧里就是一根模糊的尾巴线条但在5帧连起来看就能和“悠闲甩尾”明确区分。我已经开始着手把这套数据集按帧序列方式组织一个序列提供同一次行为连续10到15帧的样本和标签后续计划接一个轻量时序模块比如在YOLO输出的框序列后面挂个TinyRNN做行为状态转移预测。这套数据集因为保留了批次号天然可以追溯哪些图属于同一次连续拍摄做时序扩展不需要重新采集。5.2 跟关键点检测和多模态结合情绪识别的最终形态一定是组合判断而不是单靠一个检测头。我的后续计划是在这批数据上继续叠加两只耳朵、尾根、四个爪子的关键点标注用姿态关键点来修正检测头的情绪输出。比如“攻击/防御准备”的关键点特征是后腿呈蓄力弯曲、重心压在后躯耳朵尖明显向两侧下压这些是几何上的强约束能极大提升对难样本的区分度。另外猫的呼噜声、嘶叫声和情绪高度相关同一时刻的监控录像如果有音频源完全可以做一个多模态的轻量融合让音频作为预测的先验分布视频进一步确认具体姿态。多模态的想象空间很大但基础仍然是有干净的数据集这套3200张可以作为关键时刻对齐的时间轴锚点。5.3 关于“扩展数据还是优化模型”的优先级建议根据我做过多个类似细分检测项目的经验我的建议一直很明确先扩数据再调模型。很多人在模型参数上反复试验换来换去不过是1到2个点的mAP变化而补齐某一类稀有样本的30张图可能直接带来8个点以上的提升。YOLO这类检测模型的成本结构决定了它对数据分布的敏感性远大于对骨干网络微小差异的敏感性所以如果你想复现这个项目最值得投入精力的事情是用统一标准把你的场景样本整理干净再去看模型配置。做数据集最大的心得其实不是技术而是“定义清楚”把情绪状态定义得足够清晰让标注员和人眼都能判断让类别之间的语义边界足够远比选择一个复杂模型重要得多。3200张看起来不起眼如果组织得当它足够撑起一个真实可用的宠物行为感知系统。后续我会把训练好的权重、标注样例和类别配置整理成一份完整包发布出来。如果有同学在类似项目上遇到类别划分、标注规范或者训练不收敛的问题欢迎来交流具体的样本图和当时的损失曲线我们一起去定位是数据的病还是模型的锅。