ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于YOLO的猫情绪检测:3200张数据集构建与训练部署实践

基于YOLO的猫情绪检测:3200张数据集构建与训练部署实践 1. 起点这个猫情绪检测数据集是怎么攒出来的做宠物行为识别这几年我一直觉得猫的情绪检测是个被低估的方向。狗的情绪相对外放摇尾巴、吐舌头、呜咽特征明显猫就不一样了耳朵角度、瞳孔大小、尾巴摆动的幅度全是很细微的信号人有时候都判断不准更别说让模型去学。但正是这种难反而让这个方向值得投入。这次的项目就是我花了将近一个月时间亲手攒出一套3200张图片的猫情绪检测数据集再基于YOLO系列跑通训练和部署的全过程记录。先说说这个数据集本身的定位。3200张听起来不多但对情绪识别来说够用和堆量是两码事。市面上公开的猫狗分类数据集动辄几万张但那些大多是品种识别或者目标检测用的猫的情绪标注少之又少。原因很简单情绪标注的主观性太强同样的猫脸有人觉得是放松有人觉得是警惕众包标注出来的质量根本没法看。所以我这次选择自己做一套小规模、高标注质量的数据集核心目标不是刷榜而是把猫的情绪识别这件事从0到1跑通包括数据采集、清洗、标注、训练、评估的整个链路。这个数据集面向的人群也比较明确一是做宠物智能硬件、猫脸识别、行为分析产品的开发者二是高校里做计算机视觉相关课题的学生尤其是想用YOLO做自定义目标检测但找不到合适练手数据的朋友三是养猫养到想用技术手段读心的极客铲屎官。无论你是哪种身份这套数据集的构建思路和训练配置都是可以完全复现的不需要万卡集群一张消费级显卡就能跑。再讲讲数据的来源结构。3200张图片里我按场景分了室内日常、窗台观察、户外偶遇、医疗/洗澡场景四类。为什么这么分因为猫的情绪在不同场景下表现差异极大——比如洗澡时的惊恐和窗台看鸟时的专注耳朵位置看起来有点像但身体姿态完全不同。如果训练集里全是客厅沙发上的猫模型一到陌生场景就抓瞎。所以场景多样性比单纯的数量更重要这一点在后面训练验证时也体现得很明显。数据集的标注类别最终定为五类放松relaxed、警惕alert、紧张/害怕fearful、攻击/愤怒aggressive、兴奋/玩耍playful。这个分类参考了动物行为学里常用的猫情绪评估框架不是拍脑袋定的。我还额外做了一个二分类版本只分正向情绪和负向情绪用于快速验证模型能不能抓住情绪的大方向。后面的章节我会详细说每类标签的判定标准以及YOLO格式下如何把这些标注做得又干净又一致。2. 情绪类别定义与标注规范这一步决定模型上限2.1 五类情绪怎么划分才科学很多人做情绪检测上来就把标签分成开心、难过、生气这是典型的想当然。猫的五官结构和人类差太远你没法用微笑这种表情去定义猫的情绪。做标注规范之前我专门翻了一些动物行为学的资料又把国内外几个宠物表情识别的论文里的标签体系拉出来对比最终确定了一套可操作、可判定的标准。我定义的五个类别每一类都有明确的肢体信号组合而不是单一特征放松relaxed眼睛半闭或缓慢眨眼耳朵自然前竖或微微后转尾巴松弛下垂或缓慢摆动身体舒展或侧躺。警惕alert眼睛圆睁、瞳孔略微放大耳朵竖直向前身体紧绷尾巴直立或尾尖轻微抖动通常伴随对特定方向的注视。紧张/害怕fearful耳朵压平或完全后贴飞机耳瞳孔放大身体弓起或压低贴地尾巴夹紧或炸毛有时伴随嘶嘶声或回避动作。攻击/愤怒aggressive耳朵大幅度后压瞳孔收缩成细线胡须前张身体前倾尾巴快速抽动伴随哈气或低吼姿态。兴奋/玩耍playful瞳孔放大耳朵前倾身体呈伏击姿态尾巴高竖或快速摆动常伴随扑咬、抓挠动作。这里有一个关键心得单看面部是不够的必须结合耳朵、瞳孔、尾巴、身体姿态四个维度综合判断。我在标注指南里要求标注员至少看到两个以上维度信号一致才允许打标签否则宁可把这张图剔除。正是这个标准保证了后续训练出来的模型不会学到只要张嘴就愤怒这种偏离常识的特征。2.2 YOLO格式标注与工具实操数据集的目标格式是YOLO的txt标注每张图片对应一个同名txt文件每一行代表一个目标格式为类别id、归一化中心x、归一化中心y、归一化宽度w、归一化高度h。类别id从0开始对应我上面五类标签的顺序。标注工具我首推LabelImg理由很朴素开源、免费、不需要注册账号、本地运行不传数据。考虑到宠物图片很多涉及私人拍摄场景数据隐私这一条就足够pass掉一堆在线标注平台。LabelImg的使用流程大概是这样用pip安装labelImg或直接下载打包好的可执行文件。打开图片目录预先配置好classes.txt把五个类别名按顺序写好。使用快捷键W开始画框建议框住猫的整个身体而不是只框脸部。因为情绪判定的关键信号尾巴、身体姿态往往在脸的下方或侧面只框脸会丢失大量上下文信息。画完框之后按CtrlS保存自动生成同名txt文件。框选范围这里我踩过一次坑。最初我为了追求检测框的精度把框收得很紧只贴合猫的轮廓。结果训练出来的模型对尾巴炸毛身体弓起这些远离重心的特征完全无感因为那些像素被切在了框外。后来我把标注框统一调整为覆盖身体主要部分允许上下左右各留出10%左右的空白边mAP直接涨了将近4个点。这个细节大家在标注的时候一定要留意。标注的耗时也要有心理准备。3200张图平均每张图1到2个目标我加上两个帮忙的朋友断断续续标了大概8天。中间还经历了一次返工——有大约200张图的耳朵状态看不清我拿原始大图放大到200%重新核对后才确认标签。情绪类标注就是这样宁可慢一点也要准因为标签噪声对模型的负面影响远大于图片噪声。3. 从原始图片到YOLO训练集数据预处理的完整流水线3.1 图像清洗与质量排除标准图片收集齐了、初步标注完了并不能直接进训练必须先做一轮清洗。我定的排除标准有五条可以说非常严格模糊严重猫咪动态场景多快门速度跟不上很容易糊目测无法看清耳朵轮廓的一律删。目标过小猫占整张图面积小于5%的删除这类图对检测任务没有训练价值。多目标混淆画面出现两只以上猫且目标框重叠严重时标注容易出错直接删除。严重遮挡猫的耳朵、尾巴、身体任一关键部位被遮挡超过50%的删除。一只趴在毯子里只露个头的猫情绪判断几乎无从下手。光线极度异常全黑或全白过曝的图片连人都看不清猫在哪模型更不可能学到东西。清洗后数据从原始的3400多张降到3200张损失率大概6%这个比例在我的预期范围内。清洗过程也体现了小数据集更要讲究质量的原则——少量干净数据的效果往往好于大量脏数据这也是我坚持自己构建而不直接抓取网上现成数据集的原因。清洗完成后我把所有图片统一处理成640x640分辨率这是YOLO系列标准的输入尺寸。处理方式很简单先等比缩放把长边压到640然后对短边进行灰色填充而不是直接拉伸。为什么要填充而不是拉伸因为直接拉伸会改变猫的宽高比例而情绪识别里比例本身就是重要特征——炸毛的猫看起来会变胖变圆拉扁了以后模型就分不清是胖还是炸毛了。这个细节很多新手容易忽略但对检测精度的影响是实打实的。3.2 数据增强策略与训练集划分小数据集的训练数据增强是重中之重。我对比了几种增强方式对最终精度的影响最终保留了一套比较实用的组合水平翻转、随机亮度调整、随机饱和度调整、轻微旋转±10度以内、随机裁剪缩放。这里的核心逻辑是增强要模拟真实拍摄中的变化但绝不能扭曲猫的情绪特征。比如旋转角度就不能太大猫头倒过来和平躺的状态在实际场景中很少出现强行加入反而让模型学到错误的东西。为了最大化利用3200张图我采用了动态增强策略而不是把增强结果提前固化到磁盘上。也就是说训练过程中每次迭代都会对图片做一次随机增强相当于模型在训练中看到了更多样的数据而不是固定不变的同一批增强图片。实测下来动态增强比离线增强在验证集上的表现更稳泛化能力也更好。数据集划分我按8:1:1的比例分成训练集2560张、验证集320张、测试集320张。划分之前我做了一个容易被忽视的操作按场景分层洗牌。因为室内图和户外图差异较大如果随机划分导致某个场景全挤在验证集里训练过程会看到验证集分数骤降的假象。分层划分保证了各个场景在三个集合中的比例一致训练评估才有参考价值。另外要提醒的是划分完之后的标注文件要同步检查。最典型的错误是划分后的图片数量对得上但txt标注文件缺失或者类别id超出了范围。我在划分后写了一个简单的脚本自动核对每张图是否有对应txt、txt是否为空、类别id是否在0到4之间。这步检查看似基础但能省掉训练中途报错的无数麻烦。4. YOLO训练配置与过程复盘从损失曲线到实际效果4.1 模型选型与关键超参数设定模型选型上我直接在YOLOv8上跑没有纠结要不要上YOLOv9或者YOLO11。原因很简单YOLOv8生态最成熟文档齐全预训练权重好找出了问题社区里基本都能搜到答案。对于这种小规模的五分类检测任务YOLOv8的nano和small版本完全够用追求极致精度再上medium。训练配置文件的核心参数我列在下面这套配置在单张RTX 3060上能稳定跑完显存占用大约6GB没锻炼的朋友也能跟得上参数设置值说明modelyolov8n.ptnano版参数量小适合小数据集epochs200配合早停机制防止过拟合batch163060的12GB显存下比较稳妥imgsz640与预处理尺寸保持一致optimizerAdamW收敛比SGD稳定小数据集尤其明显lr00.001初始学习率不宜过大mosaic0.5马赛克增强开启但概率调低patience3030轮没提升就自动停这里重点说一下mosaic参数。YOLOv8默认的mosaic增强会把四张图拼成一张对小目标检测很友好但对情绪检测反而有副作用。因为猫的情绪信号依赖全身姿态拼图后猫的躯干经常被截断模型会学到半截猫的假特征。我把mosaic概率从默认的1.0降到0.5配合关闭部分拼图幅数精度明显回升。这个小调整在训练日志里也看得出来——降mosaic之前验证集的mAP在0.78附近震荡降了之后稳定爬到了0.83。训练过程中的另一个关键点是类别不平衡。我的数据集中放松类占了将近40%攻击类只有15%天然就有偏斜。为了缓解这个问题我在损失函数上没做特殊改动而是从数据层面下手对少量类别做额外的离线增强比如把攻击类的图片多复制一份并做水平翻转相当于人为把小类样本量放大。这个方法简单粗暴但很有效攻击类的召回率从0.61提升到了0.74。4.2 训练曲线解读与高频问题排查训练过程中最值得盯的不是最终的mAP而是训练集和验证集损失曲线的走势。我这次训练跑下来前50轮两条曲线同步下降50到90轮开始出现轻微的分叉验证集损失下降变缓到120轮左右基本平了。这是典型的模型容量配不上数据复杂度的信号——不是过拟合而是数据里的监督信号已经被榨干。如果强行继续训练只会看到验证集损失开始反弹那就是真过拟合了。我在这个项目里遇到过三个比较典型的坑排查过程值得分享第一个是类别全预测成背景。训练到第10轮时预测结果全是空框。排查了半天发现是标注文件里的坐标出了问题——有一批图片的尺寸信息在预处理时被改变了但bndbox坐标没有跟着重新归一化。解决方法是统一走一遍resize脚本所有图片和标注重新映射问题消失。第二个是混淆矩阵里放松和警惕混得很厉害。这两个类别的确在视觉上存在天然相似性耳朵竖直和耳朵微后转的边界很模糊。对策是把标注指南中这两个类别的判定规则写得更死瞳孔直径占眼球比例超过某个阈值才算警惕尾巴必须有抖动姿态才算警惕。重新标注这批模糊数据之后混淆率降了大概15%。第三个是训练中期突然出现NaN损失。这个多半是学习率设置过高或者数据里出现了异常像素值。我的解决办法是把lr0从0.01调回0.001同时检查是否有损坏的jpg图片果然查出一张截断下载的坏图删掉之后训练恢复正常。训练结束后我用测试集做了严格评估。最终mAP50达到了0.86mAP50-95在0.58左右。细看各类别的话放松类识别效果最好AP达到0.91攻击类最差只有0.79主要原因是攻击姿态的样本量最少且和玩耍姿态在动作幅度大这个维度上确实存在重叠。这个结果对于3200张的小数据集来说我是满意的至少证明了整个技术路线是成立的。5. 模型部署验证与后续可以怎么扩展5.1 部署到摄像头实时检测的完整过程训练结束只是开始模型最终要能实际用起来才算数。我用训练好的best.pt权重接入USB摄像头做了一个实时猫情绪检测的小demo。部署过程用的是YOLOv8自带的predict接口几行代码就能跑起来关键是要处理好两个实时性痛点推理速度和抽帧策略。推理速度上nano模型在3060显卡上能达到60到80 FPS瓶颈反而在摄像头读取阶段。我用的普通USB摄像头最多只能给到30 FPS所以推理侧的性能完全够用。如果要在树莓派这类边缘设备上跑建议先用onnx格式导出模型再开半精度推理速度能从2 FPS提升到8 FPS左右虽然距离实时还有距离但做定时抓拍分析足够。抽帧策略上我做了个简单的状态机默认每30帧做一次检测只有检测到猫的时候才进入高频检测模式每5帧检测一次。这样既保证了检测的实时性又避免了GPU一直满载。实际部署中还有一个意外发现把检测框与上一帧做平滑处理可以有效抑制情绪类别频繁跳变的问题。因为猫的情绪在短时间内本来就有波动但如果每帧都变界面看起来就非常神经质。加了一个简单的平滑窗口后输出稳定了很多用户体验完全不同。5.2 数据集的局限与后续扩展方向必须承认这套3200张的数据集还存在明显的局限性。最大问题是品种分布不均衡短毛猫占了大头长毛猫、无毛猫相对稀缺。无毛猫的耳朵特征特别明显但身体姿态的表达方式和普通猫不太一样模型在这类猫上的泛化能力还没有充分验证。第二个局限是情绪定义框架本身。猫的情绪其实是一个连续谱系五分类只是一个简化。实际场景里经常出现警惕中带一点好奇的混合状态这些样本在当前的硬标签体系下只能归到权重更高的那一类。后续如果要往纵深做可以考虑多标签分类或者引入行为序列建模用时间维度补充单帧图像缺失的上下文信息。第三个方向是轻量化模型在端侧设备的落地。数据集本身已经是YOLO格式天然适配各种YOLO版本后续换用YOLO11或YOLO-NAS重新训练非常方便。我个人的下一步计划是把模型换成更轻的ncnn格式塞进手机端做一个猫情绪记录App这既是对现有数据集价值的延伸也能收集到更多真实场景下的样本。最后分享一个我在整个项目里的个人体会做这种垂直场景的小数据集质量控制和任务定义比模型结构重要得多。很多朋友问我为什么不用预训练大模型直接微调我的回答是——大模型解决的是猫有没有的问题而情绪识别解决的是猫状态怎么样的问题后者对标注的一致性和类别的可区分性要求高得多。把3200张图打磨到位YOLO这种老模型一样能出不错的效果。工具永远在迭代但对数据和标注的理解才是这类项目真正的时间壁垒。
返回列表