ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

猫狗检测数据集构建与YOLOv8训练部署实战——4300张图片全流程解析

猫狗检测数据集构建与YOLOv8训练部署实战——4300张图片全流程解析 做了几年目标检测项目我越来越觉得数据集的构建过程比模型训练本身更考验耐心。这次这套猫狗检测数据集总共4300张YOLO格式标注图片就是我在做宠物识别项目时从零开始攒起来的。整个过程踩过不少坑也走了很多弯路今天把从数据采集、标注规范到YOLO训练部署的完整链路整理出来希望能帮到正在做类似宠物识别、猫狗检测项目的朋友。1. 为什么我不直接用开源猫狗数据集而要自己攒这4300张1.1 公开数据集的最大问题不是数据量而是长相差太多很多人做宠物识别第一反应就是去Kaggle找个猫狗数据集下载这没错但实际跑起来你很快会发现一个问题公开数据集里的图和真实应用场景里的图完全是两个世界。Kaggle那个经典的猫狗大战数据集Dogs vs. Cats有25000张图数据量绝对够但里面的图片大部分是十几年前网友上传的,分辨率低、主体占比大、背景干净猫咪和狗基本都在画面正中间。你用这种数据训练出来的模型拿到真实的宠物自动喂食器、小区流浪猫监控或者宠物社交App的拍图识别场景里效果会明显下滑。真实场景是复杂的猫咪躲在沙发角落、狗在草地上狂奔、强逆光、晚上只有微弱灯光、多只宠物同框、部分身体被遮挡、甚至只露个屁股。所以我决定自建数据集时目标就定得很明确不求量大但求场景全、贴近真实。4300张图听起来不算多但只要能覆盖真实场景的变化训练效果会比盲目堆量好得多。1.2 这个数据集要解决什么问题这套数据集只做两个类别的检测dog和cat。检测任务和分类任务有个本质区别分类是给整张图判断这是什么检测要回答的是图里有几只宠物每只在哪是多大的框。所以我标注的时候不是给整张图打一个标签而是要框出每一只猫和狗。实际使用中这套数据可以支撑以下场景宠物自动喂食器里识别宠物靠近区分猫狗启动不同出粮策略小区或门店的宠物统计统计某段时间内出现的猫狗数量宠物社交产品用户上传照片后自动识别宠物并打上标签智能摄像头宠物异常行为警报比如猫上桌、狗扒门这类确定好这些问题之后整个数据集项目的脉络就清晰了采集什么场景的图、标注到什么粒度、训练时用什么策略、验证时重点看哪些指标全部围绕这几个应用场景来定。2. 4300张图的诞生采集筛选、标注规范与格式转换2.1 数据来源与合规意识数据来源我主要用了三类按占比排列自采图片自己用手机、相机在不同时间早中晚、夜间开灯/关灯、不同地点室内客厅、阳台、户外草地、楼道、车内拍摄的宠物照片大约占四成可商用授权的图库素材专门筛选了允许商用和修改的图片平台避免版权风险开源数据集中的精选子集从部分开放许可证的数据集中挑选图片但不盲目全收只挑场景或者画质合格的那部分注意数据合规这件事我是认真做了功课的。训练数据一旦用于商业项目图片的授权问题会直接影响产品能否上线。建议大家都按照要么自己拍、要么明确可商用授权的标准来卡数据来源。2.2 筛选标准的细化采集到原始图片后我做了三轮筛选每一轮淘汰率都不低第一轮是清晰度筛查。模糊图、严重过曝图、运动拖影图直接删。检测模型对模糊极其敏感训练数据里模糊图太多模型学到的特征是模糊的纹理推理时反而会对清晰目标不敏感。这一轮大概删了10%。第二轮是重复图去重。我用的是感知哈希pHash算法做相似度计算相似度超过0.9的只保留一张。如果不做去重训练集里会有大量近乎重复的样本模型相当于反复看同一张图数据多样性下降还容易过拟合。第三轮是语义检查。这一步很关键。公开数据集里的猫狗图片偶尔会有标签错乱比如把狐狸标成dog、把猞猁之类的标成cat。这些错误标签混进训练集会直接拉低模型精度。我手动抽查了每批图片的标签准确性对存疑的图片单独筛出来人工复核。最终4300张图的类别分布如下类别图片数张实例总数只dog23503120cat19502680单张图里多目标的样本大约占30%这个比例我个人建议要刻意保持。如果全是单宠图片模型面对多只宠物同框时很容易漏检。2.3 标注工具的选型与标注规范标注工具我对比过几个最后按项目情况选择了x-anylabeling选它的原因是操作效率高、支持自动保存、也支持YOLO/voc/pascal coco格式直接导出。LabelImg虽然经典但多年没维护了在高分屏下的体验比较一般。标注规范是保证数据质量的核心不能边标边改。我在动手前定了一套规则团队协作时严格按照这套执行目标完整可见就框全身不追求贴到极致但要保证目标主体躯干头部在框内遮挡超过70%的实例不标注属于无法判断的样本只露出头部或只露出背部的模糊半遮挡实例不标注避免给模型引入噪声两只宠物紧挨着但边界清晰时分别单独标注完全不清晰的远处目标不标注这里有个经验之谈标注框不需要往死里贴合目标边缘。YOLO的损失计算是基于预测框和真实框的IoU标注框差几个像素对最终精度影响很小但为了抠几个像素浪费大量时间就完全没有必要了。重要的是把该框的都框了、不该框的别乱框这件事做对。2.4 从标注格式到YOLO训练格式的转换标注工具导出的格式通常是VOC XML或COCO JSON而YOLO训练需要的是txt文件每行对应一个目标格式是类别ID x_center y_center width height这四个坐标值全部是归一化到0~1之间的比例值不是像素值。举个例子一张宽960、高640的图中某个目标的框左上角在(192, 128)右下角在(672, 512)那么x_center (192 672) / 2 / 960 0.45 y_center (128 512) / 2 / 640 0.5 width (672 - 192) / 960 0.5 height (512 - 128) / 640 0.6对应的txt行就是0 0.45 0.5 0.5 0.6这个转换逻辑不复杂但如果图片集比较大建议直接写脚本批量处理而不是用标注工具自带的导出功能。原因有两个一是可以顺手做数据集的随机划分二是可以在转换时统一检查坐标越界、空标注文件等问题。数据划分我用的是train/val的比例随机打乱后按9:1分配。这个比例对4300张图来说比较合理测试集拆出来太多会导致训练数据吃紧太少又很难评估真实效果。划分完确认一下每个集合里dog和cat的比例均衡避免出现验证集里全是狗的情况。3. YOLOv8训练前的目录与配置文件90%的人会在这里栽跟头3.1 版本选型为什么是YOLOv8现在说到YOLO其实社区里已经有很多分支从YOLOv5到YOLOv8、YOLOv9甚至YOLO11都在发展。我选择YOLOv8而不是其他版本主要是这三个原因生态成熟Ultralytics官方维护文档丰富安装部署简单pip装一下就能跑预训练权重丰富官方提供了n/s/m/l/x五个规格的预训练模型可以直接在COCO预训练权重基础上做迁移学习收敛速度远超从头训练验证推理灵活训练完可以方便地导出ONNX、TensorRT等格式部署到边缘设备时选择多资料下载方面YOLOv8的预训练模型权重可以直接从Ultralytics官方GitHub仓库链接下载也可以直接让代码自动下载。对国内网络环境不太稳定的情况可以手动下载后放到指定目录然后训练时指定本地权重路径。3.2 标准的目录结构与数据集配置文件YOLOv8训练要求数据集目录有非常明确的结构建议一次性搭好避免训练时报路径错误pet-dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── pet.yaml特别注意images目录和labels目录下的文件名要一一对应比如images/train/0001.jpg必须对应labels/train/0001.txt。如果出现txt缺失或者图片缺失训练时要么报错要么数据加载量会莫名变少很难排查。pet.yaml的内容如下path: ./pet-dataset train: images/train val: images/val nc: 2 names: 0: dog 1: cat这里最容易被忽略的是path字段建议用绝对路径。如果写相对路径很多新手会默认从项目根目录开始解析结果花了半小时找行程错误最后发现是路径相对位置理解错了。3.3 核心训练参数怎么定我这次训练的基准配置放在了下面大家可以作为起步参考model: yolov8s.pt data: pet.yaml epochs: 100 batch: 16 imgsz: 640 optimizer: AdamW lr0: 0.0005模型规格选了yolov8s而不是yolov8n。n虽然速度最快但小模型对小型宠物目标的特征提取能力有限s在城市级推理场景和精度之间更均衡输入分辨率640是默认选择。宠物目标绝大多数情况下不算特别小的目标640分辨率足够batch值要看显卡显存来定。个人实测在6GB显存下yolov8s640分辨率batch设为16刚好能跑如果显存紧张batch降到8再配合梯度累积效果也不错优化器选了AdamW。YOLOv8默认是SGD但AdamW在中小型数据集上收敛更稳不用太焦虑学习率设置的问题。缺点是显存占用会略高不过这个数据集规模下影响不大4. 训练曲线、混淆矩阵与三个容易翻车的细节训练真正跑起来之后比起哇AI好神奇你更需要盯着的是训练曲线和一系列评估指标。我这边训练的最终结果如下指标数值mAP0.50.961mAP0.5:0.950.872Precision0.943Recall0.927这个结果对我来说是达到预期的。但过程中其实不是一帆风顺我踩了几个坑每一个都能让训练成果打折扣下面展开说。4.1 第一个坑训练中BN层崩溃训练到大概第40轮左右我突然发现loss变成nan了。当时第一反应是学习率太大但调低之后重启训练跑到一半又会出现。排查之后发现根因是batch size偏小加上部分图片退化异常。BNBatch Normalization层在batch过小的时候统计的均值和方差波动极大一旦某次迭代的方差算出来是0BN层就会输出nan接下来所有梯度都被污染。这类问题的主要对策按优先级排列把batch size从8提升到16检查是否有个别图片文件损坏我在数据清洗时筛过一轮但偶尔还是有一两张大图解码异常如果确实只能用小batch可以把BN层的momentum调大一点减少对当前batch统计值的依赖4.2 第二个坑混淆矩阵的总和不是100%训练结束看confusion matrix的时候有人会发现每一行的比例加起来不是100%就开始怀疑是不是模型出了问题。其实这个现象在YOLO的混淆矩阵里是正常的。具体解释是YOLO的混淆矩阵在计算时每个预测框会对应一个最高置信度的类别但置信度低于阈值的目标会被归到background那一行或列。也就是说矩阵中显示的是归一化后的分布比例出现行和不为1是因为有一部分预测框被判定为了background并没有在dog或cat类别里显示出来。所以看到confusion matrix总和不为1不要慌。应该先看background那一行占了多大比例如果background占比明显偏高说明你的置信度阈值设得太高或模型存在较多漏检如果dog、cat之间的交叉误判很少模型就是正常的。4.3 第三个坑类别分布不均带来的收敛慢我最初的数据里dog和cat图片数的比例差不多是6:4虽然不算极端但训练时发现dog类收敛明显比cat慢。原因是dog类别实例多模型在每轮迭代中见到dog的样本频率更高权重更新也更频繁。这里我没有急着给cat类强行复制图片而是给损失函数里的类别权重做了调整在用Ultralytics框架训练时可以通过给数据集配置文件或者训练代码传入类别权重参数让模型在计算分类损失时对cat类的错误更加敏感。调整之后cat类别的精度在后续几个epoch里明显追了上来。5. 从验证集到真实摄像头实测效果与部署时的几个建议训练阶段指标漂亮只是一半最终能不能用要看真实场景。我训练完之后做了两轮实测。第一轮是用手机拍视频模拟真实用户使用场景。测试内容包括家里两只猫在不同房间走动楼下小区里遛狗的路人夜间走廊有微弱灯光时猫穿过猫从摄像头侧前方快速跑过第二轮是拿了一套完全没参与训练的图片大概120张由朋友帮忙拍摄做盲测。这轮测试非常有价值暴露了单纯看mAP看不到的问题。盲测中我发现的一个明显短板是当宠物在画面中占比非常小的时候比如画面宽度640像素中宠物只占80像素漏检率明显上升。这个不是标注问题而是模型天然对小目标不敏感。如果你也要做类似场景给几个实际建议部署时尽量让宠物在画面中的比例大一些镜头安装角度不要太高推理分辨率不要低于训练分辨率我用640训练推理也尽量保持640不要为了速度随便降到416如果是低算力设备部署我建议导出ONNX后用TensorRT做INT8量化精度损失可以控制在2%以内但速度提升往往非常明显推理侧还有一个让我印象很深的问题NMS阈值不要轻易动。我把NMS的IoU阈值从默认的0.7改到0.5之后原本两条狗紧挨着的场景检测框会突然消失一个。原因很简单两个框重叠面积大NMS直接把低置信度那个框抑制掉了。所以非必要不动NMS阈值动之前先在真实数据上测过再说。6. 数据集不会一次做完版本迭代与错误样例复盘6.1 收集失败case才是数据迭代的起点模型部署到真实环境后你会发现误检和漏检的出现模式很有规律。比如我碰到的几个典型错误案例毛绒玩具狗被识别成dog置信度还不低猫背包、猫窝上的印花猫被判成cat逆光情况下把垃圾桶旁边的一团塑料袋误判成cat这些错误案例如果只是看一眼就完事那数据集永远止步于4300张。正确做法是把每一个错误case都收集到一个专门的目录里隔一段时间人工复核并补充标注然后以增量训练的方式更新模型。我自己的迭代节奏是每两周收集一次错误case每次补充100-200张图。经过三轮迭代之后模型对毛绒玩具、印花图案这类伪目标的抗干扰能力提升明显误检率几乎降了一半。这一步投入的时间不多但收效非常可观。6.2 给数据版本留好记录后续会疯狂感谢自己数据集做了3个月之后你就明白版本管理不是可选项而是必需品。我见过有人数据集文件重命名后又找不到旧版最后只能重新标注白白浪费了几十个小时。按我现在的习惯每次数据调整都会记录三件事改动的时间、改动的文件范围、改动的原因。比如v2.1 2025-03-12新增120张夜间场景图修复17张标签坐标偏移删除8张重复图这样等模型出了问题需要回滚数据版本时你手里永远有一本清清楚楚的账。6.3 数据增强要不要加加多狠才合适训练YOLO时官方默认会开启mosaic、翻转、色彩变换等数据增强。一开始我为了防止过拟合把mosaic概率调得比较高但后来发现宠物目标如果被mosaic切得太碎模型在小目标上的表现反而变差。特别是猫这种喜欢缩成一团的动物身体本来就不大被Mosaic一裁切标注框可能就剩原来的一半了。最终我把mosaic概率从默认的1.0降到了0.5同时把copy_paste增强概率适度调高一点。调整之后模型对完整目标的检测效果更稳定因为模型终于能看到完整的猫了。这个参数的调整原理其实很简单数据增强的目的是增加多样性但如果增强手段破坏了目标本身的完整性模型学到的就只是残缺特征。这一步调参花了大概三天时间做对比实验但效果是实实在在的。我建议你做类似项目时一定要自己跑几组增强参数对比别嫌麻烦默认参数在宠物这种非刚性目标上并不一定是最佳选择。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表