ARTICLE DETAIL

资讯详情

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

猫品种检测数据集构建与YOLO训练实战全流程

猫品种检测数据集构建与YOLO训练实战全流程 1. 项目概述为什么需要一套自己的猫品种检测数据集做猫品种检测之前我习惯先把开源数据集翻一遍。确实能找到Oxford-IIIT Pet Dataset、各种Kaggle宠物数据集但真要用在YOLO宠物识别项目里总会遇到几个版本对不上、类别定义模糊的问题。比如Oxford数据集里猫和狗混在一起类别虽然不少但是按品种拆开后单一品种的图片数量差别很大英短可能几百张有的冷门品种只有几十张直接用会让模型对少数类严重欠拟合。所以我决定自己收一套猫品种检测数据集顺着YOLO的标注格式做项目名叫“2400张YOLO宠物识别数据集”。这套数据集的定位很明确不是追求规模大而是追求每个品种的数量均衡、标注一致、开箱即用。这套数据集适合谁如果你正在做宠物识别App、猫咪品种科普小程序或者想入门YOLO目标检测又懒得从零整理数据可以参考我的做法。麻雀虽小五脏俱全用2400张训练一个多类别检测模型正好卡在“样本少到会欠拟合、多到跑一次太久”的甜区。而且整个过程完全不依赖特殊硬件一张普通的消费级显卡就能跑通。下面我把从选品种、找图、标注、清洗到训练、调参的全部过程拆开讲顺便把踩过的坑写在对应步骤里省得你再走一遍弯路。1.1 宠物识别场景背后的真实痛点很多人觉得宠物识别不难不就是给猫分类嘛。真做起来会发现猫品种识别和通用的猫狗分类完全是两码事。常见痛点主要有三个。第一是外观交叉严重。布偶猫和重点色英短长得非常像暹罗猫的深色脸谱也容易和某些伯曼猫混淆更不用说三花猫和玳瑁猫这种靠色块分布区分的类型。如果只做分类模型有可能靠整体颜色蒙对但一旦要求同时输出目标的边界框模型就得真正学会“猫在哪里、这只猫是哪个品种”难度直接上了一个台阶。第二是实际场景太杂。用户拍照不会像数据集那样把猫放在正中间猫可能是侧躺的、蜷成一团的、只露出半个身子的甚至一半在沙发靠垫后面。背景里可能有毛线球、猫爬架、另一只猫的尾巴。检测模型需要在这些干扰中把目标框出来再判断品种对训练数据的多样性要求很高。第三是样本分布天然不均衡。市面上英短、美短、橘猫的照片随手就是几千张但缅因猫、阿比西尼亚猫、斯芬克斯猫的照片明显少。很多公开数据集直接这样做结果模型对热门品种过拟合对冷门品种几乎放弃。所以我在构建数据的时候就立了一个规矩宁可总量少一点也得让每个品种的样本数保持在同一个量级上。1.2 为什么选YOLO和2400张的量级目标检测方案里我最终选了YOLO而不是Faster R-CNN或SSD。一个重要原因是YOLO的生态太成熟了训练、验证、导出ONNX、部署到移动端都有现成链条。另一个原因是YOLO在中等尺寸目标检测上速度优势明显宠物识别这种实时性要求较高的场景用YOLO系模型跑起来很从容。那为什么是2400张假设做10个品种平均下来每个品种240张左右对于“检测并分类”这个任务来说算是一个勉强够用的起点。再少模型很难学到品种间的细微差异再多收集和标注成本会成倍增加而且边际收益也在递减。用做菜来类比2400张不是把冰箱塞满而是保证每个品种的“食材”都够用菜谱才稳定。实际训练中我还会在YOLO内部做Mosaic等增强相当于一份食材变出多种做法所以这个量级是性价比很高的选择。2. 数据集构建的核心方案2.1 品种类别设计与数量分布选哪些品种不能拍脑袋。我参考了两个维度一是用户最常见的查询二是用户最容易拍到的猫。纯种猫和田园猫都要覆盖否则产品会在真实场景里翻车。最终我定下了10个类别英国短毛猫、美国短毛猫、布偶猫、暹罗猫、波斯猫、缅因猫、加菲猫、三花猫、奶牛猫、橘猫。后三类是田园猫里辨识度很高的花色类型用户通常会直接按颜色特征称呼它们把它们单独列为一类比强行归入“中华田园猫”要实用得多。类别确定之后我严格控制每类图片数量。最终分布大概是这样的类别ID品种图片数说明0British_Shorthair260英短图片多但尽量选不同光线场景1American_Shorthair250美短注意和狸花猫做区分2Ragdoll260布偶重点色个体单独补充3Siamese230暹罗脸部特征要清晰4Persian240波斯注意扁脸角度5Maine_Coon220缅因侧脸和站姿各占一部分6Exotic_Shorthair240加菲扁脸和波斯易混靠耳朵和毛长区分7Calico230三花白色占比高的个体也要有8Cow_Cat220奶牛猫黑白块状花纹9Orange_Tabby250橘猫浅橘和深橘都收录总量正好2400张左右每个类别最少也有220张没有明显的长尾。训练时我会再按约8:1:1拆分成训练、验证、测试集确保验证集里每个品种都占恰当比例。2.2 图片收集渠道与版权红线数据来源必须说得清楚。我主要走了三条路一是公开数据集中允许再训练的部分二是明确标注了可自由使用的图库网站三是一些宠物博主开放授权的实拍图。这里要特别强调不要为了省事直接拿某个网站的全部图片硬爬然后当自己的数据集来用。做个人学习项目问题不大但一旦要开源或商用版权麻烦比模型不收敛还头疼。拿到原始图片后我做了两轮粗筛。第一轮用脚本按分辨率过滤低于300x300的全部丢弃因为小猫脸在低分辨率下几乎没有可辨识特征。第二轮人工看缩略图把带大幅水印、严重虚焦、主体占比过小的图片删掉。这个环节没有捷径我会按类别分批刷图刷掉一批马上补充一批尽量不让单类图片数量掉下去。还有一个容易被忽略的动作去重。网络图片经常以不同尺寸、不同滤镜出现在多个来源如果只用文件名去重同一张图换个名字就漏过去了。我用了感知哈希算法把每张图缩放成8x8的灰度图比较哈希值的汉明距离距离小于5的基本判定为重复图只保留一张。这一步很关键否则同一张猫图可能同时出现在训练集和验证集看似效果很好一上真实场景就打回原形。2.3 标注规范框哪里、怎么命名、怎样算合格标注工具我推荐X-AnyLabeling或者LabelImg。前者对YOLO格式支持更顺手后者更轻量。不过真正的重点不是工具而是标注规范。第一个问题是框选范围。我踩过最大的坑就在这里。如果上一张图框了猫的全身下一张图只框了露出的头部模型会收到相互矛盾的监督信号同一个品种一会儿学“框全身”一会儿学“只框脸”。最后检测框要么大得把背景都包进去要么小得只剩一张脸。我定的规范是默认框全身也就是把躯干、四肢、尾巴都包含进去如果猫在画面里只露出半个身体就只框可见的完整部分不要凭想象把不可见的部分也补进框里如果猫和玩具有遮挡关系框要紧贴猫的可见边缘宁可稍微紧一点也不能把遮挡物框进来。第二个问题是标签怎么命名。所有类别统一用英文加下划线比如British_Shorthair不要用中文也不要用空格。中文标签在Windows系统的编码环境下很容易出乱码空格会破坏许多脚本的参数解析。txt文件里存的就是类别ID比如0代表British_Shorthairdata.yaml里面再建立ID到名称的映射。第三个问题是单张图里有多只猫怎么处理。我的原则是同品种多只猫每只都标不同品种多只猫更是每只都标这是一个天然的多目标训练样本对模型提升很有帮助。如果某只猫太小比如只有20x20像素我会把它单独放进一个“难例”文件夹留到第二轮补充而不是硬塞进训练集因为训练loss会对这种极端样本波动很大。提示标注前先在每类里挑十张样例图把规范发出去对齐。一组人标数据时至少要抽查5%的标注结果不然个人理解的分歧会直接变成模型的混淆。3. 实操把原始图片整理成YOLO可直接开训的数据集3.1 目录结构与data.yaml书写YOLO官方的目录组织方式比较固定我直接给出我用的结构cat_dataset/ ├── images/ │ ├── train/ # 约1920张 │ └── val/ # 约480张 ├── labels/ │ ├── train/ # 每张图对应一个txt │ └── val/ └── data.yaml图片和标签的对应关系靠文件名关联比如images/train/00001.jpg对应labels/train/00001.txt。如果一张图片没有目标比如空背景就不需要标签文件但训练时最好把这类图从数据集里移除因为我们的目标很明确检测猫不要训练“无猫”背景类别。data.yaml我写了这样的内容path: /home/user/cat_dataset train: images/train val: images/val nc: 10 names: 0: British_Shorthair 1: American_Shorthair 2: Ragdoll 3: Siamese 4: Persian 5: Maine_Coon 6: Exotic_Shorthair 7: Calico 8: Cow_Cat 9: Orange_Tabby注意path字段要换成你自己的绝对路径。相对路径容易在换机器训练时找不到文件这是我的一个教训。3.2 标签清洗与图片体检种图很兴奋但开训前一定要做数据体检。我写过两个小脚本一个是检查损坏图片一个是检查标签越界。检查图片是否损坏直接用PIL读一遍from PIL import Image import os for split in [train]: path fimages/{split} for f in os.listdir(path): try: img Image.open(os.path.join(path, f)) img.load() except Exception as e: print(fbad image: {f} - {e})检查标签是否越界逻辑是读取txt里每一行抽出x_center、y_center、width、height四个归一化坐标如果任意一个值小于0或大于1或者width、height小于0.01就说明这条标注有问题需要人工复查。import os def check_label(txt_path): for line in open(txt_path): parts line.strip().split() if len(parts) ! 5: return False _, x, y, w, h parts x, y, w, h float(x), float(y), float(w), float(h) if not (0 x 1 and 0 y 1 and 0 w 1 and 0 h 1): return False return True不要小看这一步。坏图片会在训练中途抛异常坏标签会让模型学出奇奇怪怪的框。更隐蔽的问题是标签里的标注框太小比如宽度只有0.005说明这只猫在图中几乎成了像素点这类样本建议直接删除或者放到单独难例集里不要混在正常样本里影响loss计算。3.3 数据增强的设置边界YOLO自带多种数据增强对2400张图片来说这几乎是必需的。Mosaic增强把四张图拼成一张显著增加了单次迭代中看到的上下文信息HSV色彩增强改变饱和度、亮度和色相模拟不同光线。但我必须提醒一句品种识别这种任务色彩增强要小心。真实案例是橘猫。橘猫的辨识几乎完全靠毛色饱和度如果调得过大橘毛会变成红棕色甚至往布偶猫的奶油色方向偏移。同理波斯猫和加菲猫的区别在于毛长和脸型如果Mosaic增强时把小脸裁掉一半模型就抓不住关键特征。所以我最终在data.yaml或训练命令里没有直接用默认全部增强而是根据验证集的表现微调先用默认增强跑一轮如果验证集loss不降或mAP波动明显再调低hsv_h到0.01、hsv_s到0.5。水平翻转我一律开着因为猫的左右对称性很强这个增强基本无损。Mosaic我也会保留但训练到后半段会关掉让模型在接近真实分布的样本上做最后收敛。4. 实战训练从一个可复现的命令开始4.1 模型选型2400张数据量怎么配模型很多初学者上来就选YOLOv8x或者YOLOv5x觉得大模型肯定准。在2400张数据上这几乎注定过拟合。训练集loss一路狂降验证集mAP原地踏步就是这个原因。我建议起步模型选YOLOv8n或者YOLOv8s。n模型参数量最小训练速度快适合先把数据处理流程、评估流程走通。s模型参数量中等精度比n有明显提升但训练时间大约多一倍。m及以上模型在2400张数据上除非加了很强的正则化否则没必要。我的实践顺序是先用n在200轮内验证数据没问题再用s做最终版本。如果s过拟合严重说明数据量确实不够回去补数据或者砍类别而不是继续换更大模型。4.2 训练命令与关键参数说明我用的训练命令如下yolo detect train \ datadata.yaml \ modelyolov8n.pt \ epochs200 \ imgsz640 \ batch16 \ patience30 \ lr00.01 \ optimizerauto逐一解释关键参数。epochs设成200但配合patience30的早停机制实际不会硬跑满200轮连续30轮验证指标没提升就自动停了省时间也防过拟合。imgsz640是YOLO的默认分辨率猫脸细节不算特别小640完全够用。如果你发现检测小猫脸总是漏检可以试试imgsz960但显存占用会明显上升机器不够就别硬上。batch16在8GB显存上比较安全12GB以上可以试32但修改batch后学习率最好也同步调整用auto优化器会让YOLO自动匹配学习率策略省心很多。用预训练权重yolov8n.pt而不是随机初始化也很关键。COCO预训练模型已经学会了通用的目标特征我们只需要在猫咪品种上做迁移学习。否则从零训练2400张数据根本不够让模型学会“什么是猫”。4.3 训练过程中的关键指标与状态判断训练过程中不要只盯着mAP。我习惯先看results.png里的三条loss曲线box_loss、cls_loss、dfl_loss。box_loss反映预测框和真实框的偏差cls_loss反映分类置信度误差dfl_loss主要影响框的边缘锐度。正常情况是三条曲线在前20个epoch快速下降然后逐渐变平。如果训练集loss降得很猛验证集loss却开始反弹就是过拟合信号。此时我优先做三件事调低增强强度、换小模型、减少epochs。如果loss在训练中途出现nan先别急着调模型回去查标签文件大概率是某个txt里混入了nan坐标或异常大的数值。评估指标我主要看四个precision、recall、mAP50、mAP50-95。mAP50是IoU阈值为0.5时的平均精度更贴近“框个大概”的体验适合快速判断模型对不对mAP50-95是多个IoU阈值的平均更严格也更接近实际部署中“框得准不准”的感觉。宠物识别场景里我一般要求mAP50到0.9以上mAP50-95到0.7以上才算一个可演示的模型。注意如果recall低说明很多猫没被框出来先补漏检样本如果precision低说明框了很多错的东西先查背景误检和类别混淆。两边同时低大概率是数据集整体质量不够不是参数问题。5. 踩坑记录与常见问题排查5.1 第一版训练最容易翻车的三个坑第一版训练我翻过三个大坑都很有代表性。第一个是类别不平衡导致的偏见。当时橘猫样本比其他类多出100多张结果模型对黄白色系的猫特别敏感连三花猫的黄色区域都被当成橘猫。解决办法很简单把橘猫样本抽到和其他类持平再观察混淆矩阵是否回落。第二个是框选标准不统一。前面说过一部分人只标脸一部分人标全身模型收敛后输出的框非常不稳定我在验证集里手动抽查时发现同一个类别的预测框有时是头肩框有时是全身框。最后返工重标了大约300张图才把标准统一。这件事给我的教训是标注规范必须写在项目文档第一页宁可多花一上午对齐也不要事后返工一整天。第三个是重复图片导致指标虚高。因为用了感知哈希去重我自认为没问题但后来发现去重阈值设置太宽松相似但不同的两张图仍然都保留了下来比如同一只猫在不同角度拍的两张照片内容高度接近在数据划分时又正好被拆到训练集和验证集导致验证集指标虚高。后来我把相似度阈值收紧同时保证相似图片尽量分到同一个集合不跨训练验证边界。5.2 用混淆矩阵定位品种混淆训练结束后YOLO会自动生成混淆矩阵图我强烈建议养成先看混淆矩阵再看mAP的习惯。mAP只是一个数字混淆矩阵能告诉你哪些品种在互相打架。我的第一版模型里最大的混淆对是暹罗猫和布偶猫。布偶猫里的重点色个体脸部和暹罗猫非常像都是深色脸谱。从混淆矩阵看大约有12%的布偶猫被识别成暹罗猫。这个信息比mAP更直接。针对这个问题我做了两件事一是增加了重点色布偶猫在数据集里的比例二是拍摄角度上多选了一些能看到布偶猫“手套白爪”特征的图片。模型学会用四肢白色斑块来区分这两种猫后混淆率明显下降。还有一组容易混淆的是波斯猫和加菲猫。波斯猫毛更蓬松脸型相对长一些加菲猫脸更扁耳朵也是典型的小圆扇。单看缩略图我也经常分不清。解决办法是在标注时额外记录备注标注人员选出那些“特征最典型的”作为基准样本再逐步扩展到模糊样本。5.3 常见问题速查表我在下表里整理了一些训练猫品种检测模型时最常碰到的问题以及排查思路。现象可能原因处理方法训练loss出现nan标签坐标异常或学习率过高检查标签txt数值降低lr0再试验证集mAP始终为0图片与标签文件名不匹配核对两张表的命名统一后重新划分检测框明显偏大标注规范不统一抽查labels返工重标两只猫同框只框出一只小目标漏检、遮挡严重提高imgsz到960补充同框样本训练集loss降、验证集loss升过拟合调低增强强度、换小模型、减少epochs某品种总是被认成另一个品种两类外观相似、样本量不均用混淆矩阵定位补足差异特征样本带水印的图片导致误检数据清洗不彻底提高过滤标准重跑数据清洗这张表不完整但覆盖了从数据清洗到模型调参的大部分经典问题。每次训练效果不好先对照这张表排查比盲目改参数有效得多。5.4 数据迭代的一点个人体会每次跑完一轮实验我固定是同一个动作顺序先看results.png里的三条loss曲线再打开confusion_matrix.png看哪里在互相打架。看完这两张图才决定下一轮数据集要补什么而不是盲目增加图片数量。按照这个节奏我从最初只有7类1200张的数据慢慢迭代到2400张验证集mAP50从0.72提高到0.91虽然离完美还远但放到预览demo里已经很能说明问题了。最后提醒一句数据集永远是项目的上限模型只是在努力逼近这个上限。如果你的猫品种检测项目效果不理想先回头审查数据再考虑换更强的模型。
返回列表