猫情绪检测数据集构建与YOLO训练实战

📅 发布时间:2026/9/30 5:39:01
猫情绪检测数据集构建与YOLO训练实战
做猫情绪检测最现实的问题不是模型不够强而是数据集不够对。我最初拿通用目标检测模型去直接跑猫的图片模型能准确框出猫的位置但根本分不清这只猫是放松、警觉还是紧张。说白了目标检测只解决了猫在哪没解决猫怎么了。后来我下决心自己整理一套带情绪标注的宠物行为数据项目叫猫情绪检测数据集一共3200张图全部用YOLO格式标注按目标检测的方式训练。这篇博文就把这套数据集从设计、采集、标注到训练的全过程拆开讲适合正在做宠物行为识别、想用YOLO训练自己的数据集、或者对标注规范和模型调优有需求的朋友参考。1. 项目思路猫情绪检测到底在检测什么1.1 为什么要单独做一个情绪检测数据集宠物情绪识别最典型的落地场景有三个。智能家居摄像头想根据猫咪状态自动播放逗猫棒视频或者安抚音乐宠物医院需要量化评估猫咪就诊时的应激程度猫咖、宠物店则想在大空间里监控多只宠物的冲突苗头。这几种需求归根结底都要先回答一个问题画面里这只猫此刻处于什么情绪状态。普通的行为识别模型比如用分类网络判读整张图像有个天然缺陷当画面里同时出现两三只状态完全不同的猫时整图分类直接失效。所以采用目标检测的思路用边界框锁定每一只猫再在框内判断其情绪状态每个个体一个标签。这也是这套数据采用YOLO格式而不是普通分类数据集格式的原因。3200张图听起来不算大但放在宠物情绪这个垂直方向上是合理起步。通用数据集动辄几十万张但猫的情绪姿态高度重复同一组合适的图片引入归一化坐标后模型泛化的关键更多在于姿态多样性而不是绝对数量。带精细情绪标签的数据3200张足以支撑单类别检测的模型跑通全部训练流程并得到一个演示级甚至准产品级的初步结果。1.2 标签体系怎么定设计标签是第一步也是最容易拍脑袋的一步。我在做这套数据集之前翻了大量猫行为学资料结合宠物主人的直观描述最终把情绪状态收敛为三个主类和一个辅助类类别视觉特征常见姿势模型识别难度relax放松耳朵自然竖立、眼睛半闭、胡须松弛侧躺、舔毛、打盹较低alert警觉耳朵直立朝前、瞳孔微扩、身体前倾凝视某处、提爪静立中等anxious紧张/应激飞机耳、瞳孔扩大、尾巴紧贴身体低头后退、原地不动较高辅助类用于处理中间状态比如一只猫耳朵后压但同时尾巴正常摆动这种含糊样本放哪一类都容易制造噪声专门划为ambiguous类别。很多数据集不做这一步后期训练时这部分样本会让损失函数反复震荡。选择三类而不是五六类是我的经验判断。猫耳、瞳孔、尾巴几个关键特征在图像上可以明显区分三类但细分出开心和放松时标注员自己都经常投票不一致标注一致性越低模型上限就越受干扰。1.3 数据收集策略数据来源主要分三路。第一路是自建场景拍摄自己养猫或者请朋友帮忙在客厅、窗台、猫爬架等不同位置采集这部分最大的好处是场景多样、视角丰富可以从俯拍、平拍、仰拍多个角度获得同一只猫的不同姿态。第二路是现有宠物视频截帧把短视频段按场景抽成图像序列再做帧间去重这个渠道能快速扩充样本量。第三路是公开宠物图片库使用时我会注意筛选清晰的猫咪全身或大半身出镜的照片避免版权争议也避免下载到过度修图导致特征偏离真实场景。训练集、验证集、测试集按照8:1:1分配也就是2560张训练、320张验证、320张测试。数据集划分还有个原则同一只猫在不同帧的图片必须全部放进同一集合不然训练集和验证集里出现同一只猫的相似姿态mAP会虚高模型一到真实环境就打回原形。2. 数据预处理与YOLO格式标注实战2.1 图像清洗要狠心采集到的原始图片和截帧必须严格筛选。优先保留光线充足、主体占画面总面积超过5%、没有大面积遮挡的图。低于这个标准要么检测框质量差要么情绪特征无法辨认删掉比标注后拉低模型精度更划算。我筛了差不多一成半的不合格图片全是糊片、兔子式的背影、或者与画面重叠超过一半的杂物遮挡。清洗阶段的另一个关键是模拟真实部署场景。模型最终要部署到固定摄像头下画面会有俯视角度、有家具遮挡、还有运动模糊。所以筛选时不能只要标准证件照刻意保留了一批低角度、半遮挡、逆光但轮廓尚可的样本这部分样本能让模型在真实场景下不至于立刻崩掉。代价是训练难度上升但这钱花得值。2.2 标注规范YOLO格式怎么标才不乱YOLO格式是典型的归一化文本标注每个标签文件与一张图片同名后缀为txt。每一行代表一个目标内容依次为类别序号、边界框中心点x、中心点y、框宽w、框高h后四个值全部用边界框尺寸除以图片宽高做归一化取值范围在0到1之间。我举个具体标注例子。假设一张1600x1200的图片其中一只猫的边界框左上角位于(900, 640)右下角位于(1240, 900)。边界框中心点坐标就是((9001240)/21070, (640900)/2770)框宽为1240-900340框高为900-640260。归一化之后写成1 0.6687 0.6416 0.2125 0.2166看到这个机制你就能理解YOLO格式不关心图像绝对尺寸同样一只猫在手机照片和监控截图中的标注数值完全一致。标注工具我推荐X-AnyLabeling或LabelImg两者都支持YOLO格式导出。我习惯统一使用LabelImg不追新工具标注稳定性最重要。标注时有三条经验供参考。第一边界框要把膨起的毛发和低伏的耳朵都框进去情绪特征往往在轮廓边缘太紧的框会截断炸毛信号。第二一只猫被遮挡时框住可见部分即可不要凭想像画一个完整猫框YOLO目标检测天然支持部分遮挡。第三多只猫互相靠近时严格按每个个体各自画框猫与猫之间的空隙宁可框重叠也不能合并。2.3 文件组织与验证脚本最终数据集目录结构如下cat_emotion/ ├── images/ │ ├── train/ # 2560张 │ ├── val/ # 320张 │ └── test/ # 320张 ├── labels/ │ ├── train/ # 2560个txt │ ├── val/ # 320个txt │ └── test/ # 320个txt └── cat_emotion.yaml标注完成后一定要写脚本做格式校验。最常犯的错误是坐标越界、类别序号写错、空标签文件堆积。我写过一个几十行的Python检查脚本遍历所有标签文件自动报告坐标小于0或大于1的异常行、类别序号超过names字段的错误、以及零字节的空文件。越界通常来自标注工具手动修改时的误操作空文件则会在训练时被Ultralytics默认丢掉导致实际训练图片数少于目录统计数查起来让人头疼。3. 基于YOLO的训练实战3.1 环境配置与模型选型环境配置我用的是Ultralytics YOLOv8框架它在训练接口和日志监控方面做得最省心适合这种中小型数据集的快速迭代。具体依赖版本不展开只需要Python 3.9、PyTorch 2.x、CUDA 11.8以上即可我用的是PyTorch 2.1。硬体现网卡是单张RTX 309024GB显存训练这个规模的数据集非常宽裕如果显存只有8GB左右把batch size降到8并打开梯度累积也能跑。模型选型方面我对比过YOLOv8n、YOLOv8s和YOLOv5s。3200张数据集对小模型更友好任务当前在跑的大小约11M参数训练速度快一次完整训练在单卡上大约20到30分钟一个epoch全程100轮几个小时就能完成。大模型在这个数据量上容易陷入过拟合AP提升有限但训练时间和显存占用翻倍。我的结论是垂直小数据集起步优先选n或s级先把流程跑通再谈模型改进。看自注意力机面在后续扩数据之后再做调整也不迟。训练配置直接看yaml文件path: /data/cat_emotion train: images/train val: images/val test: images/test nc: 3 names: 0: relax 1: alert 2: anxious注意names还写了一个辅助类上面的nc和names只写了三个主类如果在标注阶段把ambiguous单独留了类就必须在nc里加一并进行训练。3.2 训练参数设置与调优训练脚本我直接放在项目根目录跑起来是这样from ultralytics import YOLO model YOLO(yolov8s.pt) results model.train( datacat_emotion.yaml, epochs100, imgsz640, batch16, device0, workers4, seed42, patience15, optimizerAdamW, lr00.001, weight_decay0.0005, warmup_epochs3, mosaic1.0, close_mosaic10, projectruns/cat_emotion, nameexp1, plotsTrue )几个参数我解释一下逻辑。imgsz640是YOLO的经典输入尺寸猫相对镜头通常占画面比例较大640能兼顾特征细节和显存占用不必盲目上1280。batch16是我根据显存和模型尺寸算出来的经验值3090跑这个组合毫无压力。lr0设0.001配合AdamW对中小数据集收敛起来比默认SGD更平稳省去手动调参的时间。mosaic增强默认开启它把四张图拼成一张训练相当于隐式扩容很适合这个数据规模。但最后10个epoch关掉mosaic避免一直用拼接图导致模型对真实整图分布不敏感这是YOLOv8的推荐做法我直接沿用。数据增强配置里还需要留意的是不要开太多随机擦除。猫的情绪特征经常集中在耳朵和尾巴随机擦除很容易把整只猫脸部的关键信息抹掉导致模型只能靠身体姿态去猜情绪短期测试精度看着还行换一组背景稍复杂的图精度立刻掉所以我把随机擦除的相关参数保持默认的较低水平。3.3 训练过程监控与结果分析训练过程中我重点关注三个日志指标box_loss、cls_loss、dfl_loss在验证集上的曲线。box_loss描述定位精度cls_loss描述情绪分类精度dfl_loss描述边界框边缘对焦点检测的效果。三者稳步下降是正常趋势若cls_loss先降后回升就说明过拟合已经开始此时即使训练集精度还在涨验证集AP大概率已经滞涨果断用早停机制截断训练。这是我训练完第60个epoch时的输出摘要过程相对典型Epoch (epoch_60/100) top1_acc0.78319 ap500.85254 ap50-950.68279 Epoch (epoch_61/100) top1_acc0.87950 ap500.89032 ap50-950.70189 Epoch (epoch_62/100) top1_acc0.83869 ap500.87921 ap50-950.69347这里有个关键观察即便训练到中后期单轮准确率仍有2到3个百分点的波动这在小数据集上完全正常。判断模型是否真的收敛不能只看某轮峰值应该用最后十个epoch的平均值对比。我最终保存的权重不是最后一轮而是patience机制内验证集mAP50-95最高的那一个。Ultralytics会自动保存best.pt这个才是部署时真正要用的文件。4. 评估效果与常见问题排查4.1 评估指标到底看哪个YOLO常用的评估指标有mAP50和mAP50-95很多初学者只盯着mAP50看觉得数值高就万事大吉。mAP50衡量的是预测框和真实框的交并比大于50%时的平均精度而mAP50-95进一步把交并比从50%到95%分档计算后者对边界框精度的要求严苛得多。对宠物情绪检测来说边界框多一点少一点并不影响情绪判断mAP50-95偏低一点可以接受但要小心它和mAP50差距过大那通常意味着框质量极不稳定。我自己得到的三个主类的最终成绩大致为relax类的mAP50接近0.91alert类在0.88anxious类压力最大只有0.79。这个差异主要来自数据本身的标注一致性放松的猫姿势稳定很好框紧张应激的猫姿态变化快、又总躲在遮挡物后面。如果焦虑类的成绩拖累整体不要急着改网络结构先检查该类图片是否符合标注规范再把该类样本数量拉一拉效果往往立竿见影。训练结束先跑一版测试集评估脚本看标签与预测的混淆矩阵。混淆矩阵的非对角线元素如果集中在anxious与alert之间不是这两个类在外观上相近就是标注时边界案例太随意。遇到这种矩阵我的处理办法是回归标注文件把所有冲突样本挑出来找标注员二次确认必要时直接删掉干净的数据比多几张凑数的图重要得多。4.2 踩坑记录五个常见问题速查我在这个项目里踩过的坑整理成一张表给后来人抄作业。问题现象根因解决方案训练开始时损失全部恒为0yaml文件里names行与标签类别序号不对应逐行检查txt首列序号必须从0开始连续编号mAP50高但mAP50-95特别低框偏大或偏小情绪特征不稳定时手画框偏差大统一标注缓冲区规则确保特征边缘在框内且在框上留3%-5%余量验证集loss下降但精度不涨同一只猫的相似图片泄漏到了训练集和验证集按猫个体分组划分数据集禁止同猫跨集合anxious类完全检测不到该类样本少且多在暗光环境扩充该类图片或对已有样本做强亮度增强部署时画面卡顿输入分辨率设置过高推理用户系统1080P下用640即可必要时用TensorRT加速这里面最值得展开的是框规范的细节。很多人标注时有个习惯猫耳朵竖起来就紧紧贴着耳朵尖画框遇到情绪紧张耳朵压平框又自动缩回去。这种做法看似精准实际伤害模型因为框架学到的定位规律被标注者自己的框习惯带偏。我后来的标注规范统一为框包含整个身体轮廓以及完整头部猫无论耳朵怎样变化都让边界框上下左右留出3%到5%的余量人为制造一个小小的安全区这样可以大幅度降低标注漂移造成的损失。4.3 部署时的小优化模型训练完部署到推理端我还有两个实用技巧。第一对输出框做NMS时类别置信度阈值推荐调到0.35到0.45之间不要沿用默认的0.25。情绪检测不同于普通目标检测类别间外观相似度高放宽阈值会大量混入误分类框尤其anxious很容易在不同环境中飘到其他类别。第二如果部署场景是固定的监控摄像头可以叠加一个简单的帧间投票机制连续三帧中同一只猫框内类别出现两次以上才输出瞬时误判会被过滤掉。这个方案不涉及模型改动收益却非常可观。5. 应用扩展方向5.1 从单一时刻到行为序列单帧情绪检测做出来之后最有价值的延伸是行为序列识别。猫的情绪往往不是一帧定乾坤而是在几秒内逐渐显现比如警觉到恐惧需要经过耳朵压低、瞳孔扩大、身体弓起几个阶段。用这套YOLO检测数据集作为前置编码器每一帧输出情绪类别和位置特征序列再接一个LSTM或Transformer时间序列模型就能预测情绪变化的趋势。这也是目前宠物情绪管理比较实用的方案可以提前干预而不是事后报警。5.2 多目标场景的交互分析数据集里的多猫共框场景单帧模型已经能分别输出每只猫的情绪状态。再接一步可以分析多只猫的情绪差值比如一只猫处于anxious而另一只猫处于alert往往意味着领地冲突的前兆。比较好的落地形式是做一个画面级别的情绪热度图把边界框中心点投影到二维坐标并映射成热力值管理者一眼看清哪个角落需要介入。这个想法不需要新的训练任务只是对已有检测输出的二次数值处理。5.3 数据处理和模型扩展的一致建议3200张数据集的体量决定了当前模型的上限。后续扩展数据时固定摄像头的视频帧序列比单纯搜集照片效率高很多同一个场景连续抽帧可以获得大量带一致性标注的样本。模型选型上如果数据超过2万张再考虑从YOLOv8s升级到YOLOv8m或者引入更多注意力模块是划算的在数据量没有突破之前把精力花在标注质量和场景覆盖上收益远大于换网络结构。改进方向可以关注高效注意力头和轻量上采样模块这类结构在YOLO中通用等数据体量上来之后可以作为扩展选项。我个人做完这套数据集最大的体会是垂直领域的小数据集最值钱的不是标注数量而是对关键视觉特征的准确抽象。猫情绪检测这类任务如果对行为学特征缺乏了解标注人员即使准确框出了猫也会在情绪分类决策时依赖主观感觉导致标注一致性崩溃。建议每一个做宠物行为识别的人先花两天时间观察真实猫咪在不同状态下的姿态变化再去动手标第一批数据这个前置步骤比选模型调参重要得多。我自己在整理过程中也踩了不少标注的坑后面把这套流程固化下来之后新扩充的几百张图标注速度明显加快模型精度也在稳步爬升。