猫狗检测算是我入行目标检测这块最早接触的项目之一这几年做下来从最早的VOC格式手工标注到现在用YOLO系列训一套猫狗识别模型流程已经非常成熟了。手头这套4300张的YOLO宠物识别数据集是我整理出来专门给YOLO系列模型训练用的覆盖了猫和狗两个大类标注格式统一为YOLO txt格式直接解压放到项目里就能开始训练不需要再做格式转换。这篇文章我就把这套数据集的内容构成、标注特点、训练配置、踩坑记录一次性说清楚从目录结构到训练参数从损失函数观察到模型部署全流程过一遍还在做宠物识别或者想跑通YOLO训练流程的朋友可以直接照着手里的数据集来操作。1. 数据集构成与标注格式说明1.1 图像来源与场景分布这套数据集一共有4300张图片猫和狗的图片比例大致均衡猫的图片大概2200张狗的图片大概2100张剩下的几十张是同时包含猫和狗的混合场景图。图片的来源主要是公开数据集筛选、网络爬虫整理、以及一部分日常拍摄补充做过去重和模糊剔除保证每张图都有实际训练价值。场景分布会比较贴近真实应用包括室内居家环境、街道户外、公园草地、宠物医院、笼舍等。光照条件也有意保持了多样性有白天强光、傍晚暗光、夜晚灯光、逆光剪影等不同情况。这个设计是故意的因为宠物检测在真实落地时最怕的就是环境变化导致模型掉点。如果数据集全是在明亮室内拍的模型一到户外或者晚上就直接罢工这在实战里是很大的坑。还有一个细节图片里宠物的体型跨度很大有占满整个画面的特写也有远处小目标的身影。小目标占比大概在10%左右这部分图片虽然数量不多但对模型泛化能力的提升帮助很大。我建议训练时不要因为小目标样本少就做欠采样反而可以通过适当的重复采样或马赛克增强强化模型对小目标的敏感度。1.2 标注格式与类别定义标注格式统一用的是YOLO系列标准的txt格式每张图片对应一个同名txt文件每一行代表一个目标框格式为class_id center_x center_y width height其中class_id是整数类别编号center_x、center_y、width、height都是归一化坐标取值在0到1之间分别表示目标框中心点的x坐标、y坐标、框的宽度和高度相对于图片宽高的比例。这套数据集的类别定义很简洁就两类0: cat 1: dog如果场景中有其他动物或者干扰对象没有做额外标注。这里解释一下原因目标检测模型的类别越少每个类别的特征区分度就越容易学。猫和狗虽然看起来有些相似但耳朵形状、脸型、体型等特征差异足够大两个类别的设置既保证任务有意义又不会给模型增加额外负担。很多新手做猫狗检测喜欢顺手标上“person”“chair”之类的无关类别想着让模型多学点背景信息。我实测过这个想法效果反而变差因为背景类别样本不平衡会干扰主类别的梯度更新训练收敛变慢mAP还有轻微下降。1.3 训练集验证集测试集划分数据集在打包时已经按照8:1:1的比例划分好了。训练集3440张验证集430张测试集430张。划分时做了同场景去重意思就是说同一只猫在不同角度、不同光照下的照片不会同时出现在训练集和测试集里会尽量分散。这一步很重要否则模型在训练时已经见过测试集的“近似样本”测试分数虚高部署到真实环境直接打回原形。目录结构如下dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yamldata.yaml文件内容path: dataset/ train: images/train val: images/val test: images/test nc: 2 names: [cat, dog]这里有一个需要特别留意的坑path字段建议写绝对路径或者相对于执行命令目录的相对路径。如果你把YOLO项目跑在服务器上数据集路径频繁变动建议训练时统一用绝对路径避免出现File not found的报错。如果是在本地自己玩相对路径就够了。2. YOLO模型选型与训练前环境准备2.1 为什么选择YOLOv8作为主力模型猫狗检测这个任务我自己测试过YOLOv5、YOLOv7、YOLOv8甚至还试过用RT-DETR跑了一版。综合训练速度、显存占用、部署便利性YOLOv8是最均衡的选择。YOLOv8在C2f模块、Anchor-Free检测头、Decoupled Head这些设计上做了针对性优化训练收敛速度快小目标召回率比v5有明显提升而且ultralytics这个库封装得极其友好几行代码就能跑训练对新手极其友好。当然现在YOLOv9、YOLOv10这些新版本也出来了我在后面章节会专门讲一下如何把数据集适配到新版本上。核心的txt格式和数据划分方式完全通用换版本只需要改配置参数不需要动数据。还有一个选择是YOLOv8n、YOLOv8s、YOLOv8m这些不同规模的预训练权重。规模越大的模型精度越高但显存要求也越高。猫狗识别这种二分类任务模型不需要特别深我实测下来YOLOv8s性价比最高精度跟YOLOv8m差距不大但推理速度快了将近一倍。如果你用的显卡是GTX 1060这种老卡YOLOv8n也能跑出不错的效果就是小目标的召回率差一些。2.2 环境搭建与依赖版本锁定训练环境推荐使用Miniconda创建独立虚拟环境避免污染系统Python。创建环境并安装核心依赖conda create -n yolov8 python3.9 -y conda activate yolov8 pip install ultralytics8.2.0 pip install torch2.1.2 torchvision0.16.2 --index-url https://download.pytorch.org/whl/cu118这里要强调一下版本锁定的重要性。ultralytics库更新很频繁有一次我不小心升级到了新版结果数据集加载方式变了之前好好的yaml配置报了一堆参数错误。所以建议装好环境后记录好版本号训练脚本里也可以固定版本避免环境漂移。硬件要求方面如果只是训练YOLOv8n或YOLOv8s显存6GB以上的显卡就够用。图片输入尺寸默认640x640训练的批大小如果显存不够可以调低到8或4。没有GPU的话也能训练用CPU也能跑但会慢得离谱一个epoch可能就要半小时不建议尝试。2.3 数据校验与可视化检查数据拿到手之后别急着开训先做数据完整性校验。YOLO训练最怕是标注文件跟图片文件对不上号。我写了一个快速校验脚本检查每一张图片是否都有对应的txt标注文件以及txt文件里的坐标值是否都在0到1之间import os img_dir dataset/images/train label_dir dataset/labels/train img_files [f.split(.)[0] for f in os.listdir(img_dir)] label_files [f.split(.)[0] for f in os.listdir(label_dir)] missing_labels set(img_files) - set(label_files) orphan_labels set(label_files) - set(img_files) print(f缺失标注数量: {len(missing_labels)}) print(f孤立标注数量: {len(orphan_labels)}) if missing_labels: print(缺失标注示例:, list(missing_labels)[:10])除了文件配对检查还要做坐标范围检查。YOLO格式里坐标值超出0到1范围通常说明标注工具有问题或者有脏数据。极端情况下如果坐标值轻微超出比如width1.05训练时不一定会报错但损失会异常偏高影响收敛。再做一步可视化检查用OpenCV把标注框画到图上人工抽检几十张图片确认框是否贴合目标、类别是否正确。这一步虽然费点时间但能发现很多标注工具的隐蔽错误比如类别编号错位、框没有完全包裹目标、目标过小导致框退化成一个点等。可视化检查是训练前的最后一道防线我几乎每次都会做。3. 完整训练流程与核心参数调优3.1 训练配置与启动命令准备好数据集后训练这块我用ultralytics的标准命令行就够了。以下是我在这套猫狗数据集上实测稳定的训练命令yolo train \ modelyolov8s.pt \ datadataset/data.yaml \ epochs150 \ imgsz640 \ batch16 \ device0 \ workers4 \ optimizerAdamW \ lr00.001 \ lrf0.01 \ patience20 \ project./runs \ namecat_dog_experiment各参数的含义和选择依据如下modelyolov8s.pt加载预训练权重。COCO数据集上训过的权重已经学到了通用的特征表示迁移到猫狗检测只需要微调后面的检测头即可训练速度快很多。如果从零开始训练的话150个epoch可能都不够收敛而且精度明显偏低。epochs150二分类任务不算复杂150轮足够模型充分收敛。配合patience20的早停机制如果连续20轮验证集mAP没有提升训练会自动停止不会浪费时间。imgsz640默认输入尺寸和预训练权重一致。如果你希望提升小目标检测能力可以试试imgsz768或960但显存消耗会增加不少推理速度也会下降。batch16我测试时用的是16G显存的卡16的批大小刚好把显存吃满。显存小的卡可以调成8不过学习率也要相应调整后面会细说。optimizerAdamWYOLOv8默认的优化器是AdamW并且内置了warmup和cosine学习率调度。实测下来AdamW在这套数据集上收敛比SGD平稳前期不容易出现loss爆炸的情况。patience20早停耐心值。如果训练到第70轮时模型精度就不再提升继续硬跑150轮纯属浪费显卡寿命。早停机制能节省不少时间。3.2 训练过程中的损失函数观察训练过程中终端会实时打印每个epoch的训练损失和验证指标。需要重点关注这几个指标的变化train/box_loss边界框回归损失数值下降说明模型预测框的位置越来越准。train/cls_loss分类损失下降说明模型对猫狗分类的置信度越来越高。train/dfl_loss分布聚焦损失这是YOLOv8新增的回归分支损失趋势同样应该是下降的。metrics/mAP50IoU阈值0.5时的平均精度猫狗检测这类任务这个指标一般能达到0.95以上才算合格。metrics/mAP50-95更严格的指标IoU从0.5到0.95逐步计算取平均。这个值会比mAP50低不少大面积的特写图比较占便宜小目标明显吃亏。我在训练过程中发现一个常见情况mAP50在训练初期上升很快大概20轮左右就能到0.9但mAP50-95还在0.5附近徘徊。这说明模型对“大致定位”已经学会了但精细的边界框回归还不够好。这时候别急着停止训练继续往下跑mAP50-95还有上升空间。另外还有个细节如果训练集损失在下降但验证集损失不降甚至升高这就出现了过拟合的迹象。猫狗数据集类别少、特征明显过拟合通常发生在epoch后期。解决方式很简单增加数据增强强度或者提前早停。3.3 梯度累积与学习率联动调整小显存显卡用户经常遇到一个问题batch设成4结果训练效果明显比batch16差。原因很简单batch越小每个batch的梯度估计越不准确训练过程越震荡同等epoch数下的最终精度会偏低。解决方案是用梯度累积模拟更大的batch。具体来说batch4、累积4步等效于batch16的效果。ultralytics支持通过参数batch4以及accumulate4实现梯度累积yolo train \ modelyolov8s.pt \ datadataset/data.yaml \ epochs150 \ imgsz640 \ batch4 \ accumulate4 \ device0batch大小调整时学习率也需要跟着变。常用的经验法则是线性缩放学习率原计划batch16、lr00.001改成batch8时建议把lr0调整到0.0005左右。如果你的显卡只能跑batch4学习率设为0.00025会更稳。我在实际调参中发现学习率偏高时损失曲线会出现锯齿状震荡下降过程不平滑学习率偏低时收敛速度明显变慢相同epoch数下mAP低1到2个百分点。找到那个“居中值”需要一点耐心我的习惯是先跑30个epoch看趋势再决定要不要调。3.4 数据增强参数的实际调整YOLOv8内置了丰富的数据增强策略默认参数已经比较均衡。但针对猫狗检测这个特定场景我建议对几项增强做微调。hsv_h、hsv_s、hsv_v色调、饱和度、明度的随机调整。宠物毛色差异很大增强可以增加模型对毛色的鲁棒性。我设置hsv_s0.5、hsv_v0.4能让模型不过度依赖毛色特征。degrees随机旋转角度。猫狗图片有大量竖屏拍摄的情况如果不做旋转增强模型对旋转目标的适应能力会很差。但我没有把degrees拉太高因为宠物图片虽然有角度变化但多数情况还是正向或接近正向的。设成degrees10就差不多了太高会造成大量无效学习。perspective透视变换强度。这个增强模拟相机角度变化但强度太大会导致目标变形严重反而干扰检测。我设成0.0005只做极轻微的透视扰动。mosaic马赛克增强是YOLO系列最核心的增强方式把四张图拼在一起训练。默认mosaic1.0能够显著提升模型的泛化能力尤其是小目标检测能力。但在训练后期建议把mosaic关掉或调低因为拼出来的图片目标尺寸和真实场景有偏差影响最终精度的收敛。ultralytics支持在训练后段自动关闭马赛克不需要手动干预这是我很喜欢的一个特性。这些增强参数怎样设置可以在训练命令中添加如下参数实测对这套数据集效果很好yolo train \ modelyolov8s.pt \ datadataset/data.yaml \ epochs150 \ imgsz640 \ batch16 \ hsv_h0.015 \ hsv_s0.5 \ hsv_v0.4 \ degrees10 \ perspective0.00054. 训练后的评估分析与模型导出4.1 混淆矩阵与失败样本分析训练结束后ultralytics会在runs/detect/cat_dog_experiment/目录下生成结果文件包括confusion_matrix.png、results.csv、val_batch*.jpg等。混淆矩阵是分析模型性能的利器。理想情况下混淆矩阵的对角线元素应该接近1非对角线元素接近0。猫狗检测常见的混淆错误是猫被识别成狗或者反过来。如果出现这种情况看图分析具体原因通常是这类错误集中出现在某些特定毛色或姿态的个体上。有一段时间我的模型总把“无毛猫”误检成“狗”这是因为数据集中无毛猫样本太少模型把“有毛”学成了猫的强特征。后来我在训练集中补充了其他品种的猫并针对性加入了无毛猫的图片这个混淆就明显缓解了。所以说当混淆矩阵里某一对类别错误明显偏高时最直接的改进方向是补充对应类别的样本而不是换模型结构。失败样本分析同样重要。val_batch图片上会画红框表示预测结果红框旁边标注了类别和置信度。我每一轮实验都会看一下这些图特别注意模型漏检的目标。最常见的漏检原因是目标过于模糊或目标极小这类样本在真实场景中也会是检测难点如果业务场景比较在意就需要针对性优化。4.2 模型导出与TensorRT加速训练完成后模型的pth权重可以直接用于Python推理。但如果要落地到实际产品中通常需要转换成更适合部署的格式。from ultralytics import YOLO model YOLO(runs/detect/cat_dog_experiment/weights/best.pt) # 导出为ONNX格式 model.export(formatonnx, opset12) # 导出为TensorRT格式需要GPU model.export(formatengine, halfTrue, imgsz640)ONNX格式通用性最强可以加载到ONNX Runtime或者OpenVINO等推理框架里。TensorRT格式在NVIDIA GPU上的推理速度最快尤其是开启FP16半精度后推理速度能比PyTorch原生模式快2到3倍。项目落地时我基本都会用TensorRT做推理加速。自己跑这一步的时候注意一个坑TensorRT引擎文件跟GPU型号和CUDA版本强绑定。在A卡或者没有GPU的机器上导出engine格式会直接报错。如果要在多台机器上部署更稳妥的方案是每台机器分别导出对应格式或者直接分发ONNX文件在目标机器上再编译。4.3 实时推理脚本编写参考导出的模型做实时推理非常简单以下是一个摄像头实时检测猫狗的示例import cv2 from ultralytics import YOLO model YOLO(runs/detect/cat_dog_experiment/weights/best.pt) cap cv2.VideoCapture(0) while True: ret, frame cap.read() if not ret: break results model(frame, conf0.5, imgsz640, device0, verboseFalse) for result in results: boxes result.boxes for box in boxes: x1, y1, x2, y2 box.xyxy[0].tolist() cls_id int(box.cls[0].item()) conf box.conf[0].item() label f{result.names[cls_id]} {conf:.2f} color (0, 255, 0) if cls_id 0 else (0, 0, 255) cv2.rectangle(frame, (int(x1), int(y1)), (int(x2), int(y2)), color, 2) cv2.putText(frame, label, (int(x1), int(y1) - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2) cv2.imshow(CatDog Detection, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()conf0.5是置信度阈值如果检测结果频繁出现漏检可以适当降低到0.3如果误检变多就调高阈值。这个参数在视频流场景中需要根据实际效果动态调整是一个很实用的调试入口。5. 常见痛点问题与调优经验汇总5.1 模型在不同光照条件下泛化不足很多用户训练完模型后发现测试集上表现不错但拿到真实户外环境就掉链子。这个问题的根子在于训练集的多样性不够。前面章节提过这套数据集特意涵盖了不同光照场景但如果你的自定义数据集光照单一就需要靠数据增强来补。更有效的方法是做一个简单的在线数据增强扩展在训练前对图片做随机亮度、对比度调整模拟不同环境光。OpenCV里可以直接操作import cv2 import numpy as np def adjust_brightness_contrast(image): alpha np.random.uniform(0.7, 1.3) # 对比度系数 beta np.random.uniform(-30, 30) # 亮度增益 adjusted cv2.convertScaleAbs(image, alphaalpha, betabeta) return adjusted把类似操作加到数据加载流程中能显著提升模型对光照变化的鲁棒性。我在这套猫狗数据集上用过这个方法夜间暗光场景的漏检率明显下降。5.2 小目标检测效果差怎么办宠物检测场景中小目标指画面中占比较小的宠物。我在数据集中专门保留了一部分小目标图片但训练过程中发现如果小目标占总样本的比例太低模型的注意力会被大中目标主导。解决方向有三个一是提高输入分辨率。把imgsz从640增加到960对提升小目标检测效果最直接代价是显存占用和推理耗时上升。二是调整anchor或使用更高分辨率的特征层。YOLOv8是Anchor-Free结构不能直接调anchor数量但可以修改检测头输出的特征尺度。ultralytics库的配置文件允许自定义模型结构不过这属于进阶操作新手建议先从imgsz入手。三是增加小目标样本的采样权重。如果用自己的数据集可以统计每张图中目标框的面积把小目标占比高的图片复制几份混入训练集强制模型多学这些样本。我在真实项目中试过一种很有效的增强方式整体缩放图片后再贴到黑色背景上相当于把小目标“人为放大”之后再训练。效果的提升肉眼可见mAP50-95大概能涨两个点。5.3 训练不收敛或损失异常升高训练过程中出现lossnan或者突然升高原因排查优先级如下先看学习率是否过大。学习率过高最典型的特征就是损失值在某个epoch后突然变nan。解决方法是降低lr0同时把warmup_epochs调大让模型在初始阶段更平稳地过渡。再看数据是否有异常。注意标注文件里坐标值是否为0或者坐标值超界。试过一张图片的txt文件里记录了坐标以外的不规范字段训练时模型直接把那张图的损失推到了几百导致整体指标震荡。然后看batch size和BN层。YOLOv8在batch很小的时候BatchNorm的统计量非常不稳定可能出现训练集损失正常但验证集loss异常偏高。如果batch4还出现BN崩溃的情况建议先用预训练权重跑或者直接用YOLOv8默认的batch参数不要低于8。特别提醒一下YOLOv8训练过程中偶尔会出现“诡异”的验证集指标跳变比如某个epoch后mAP从0.95突然掉到0.7但下一个epoch又涨回来了。这种现象多数是因为验证图片里恰好有极端难例。不用太焦虑继续训练观察整体趋势就行模型权重保存看的是最佳mAP不会因为一个epoch的波动就丢失好权重。5.4 数据集扩充策略4300张的训练集对一个二分类检测任务来说已经能出不错的效果但如果想进一步提升精度扩充数据集是最直接的手段。扩充方式按性价比排序第一优先是补充“难例”也就是模型在验证集上检测失败的图片把这些图片加入训练集做第二轮训练这是典型的hard example mining做法。第二优先是增加场景多样性特别是你最终部署场景中的环境比如要在室内监控场景部署就多采集室内不同房间、不同角度的猫狗图片。第三才是网上抓取更多猫狗图片因为泛化提升缓慢却容易引入大量相似样本。我自己做过一个对比实验用4300张原数据集训练mAP50-95是0.82补充了300张硬例图片后重新训练mAP50-95提升到了0.85。这个提升幅度已经非常可观了而且只花了很少的人工标注时间。6. 向YOLOv9和YOLOv10等新版本迁移6.1 新老版本数据格式兼容性YOLO系列的数据格式一脉相承txt标注文件长得都一样。我把这套猫狗数据集直接跑过YOLOv6、YOLOv7、YOLOv8、YOLOv9、YOLOv10只要data.yaml配置正确完全不需要改动标注格式。各种版本的data.yaml配置略有区别但核心字段是一样的。如果需要适配新版本最简单的操作是先更新ultralytics库然后把官方提供的yaml配置拷贝过来改一下path和nc、names的值就行。YOLOv9在ultyalytics的README里提供了完整的配置示例YOLOv10同样可以直接用同样的data.yaml。6.2 新版本模型结构带来的性能提升YOLOv9引入了可编程梯度信息PGI和广义高效层聚合网络GELAN增强特征提取能力在小目标检测上有一定优势。YOLOv10则在训练效率上做了优化引入了一致匹配度量等设计训练收敛更轻松省去了NMS后处理环节推理更简单。我实测用YOLOv9c在相同4300张数据集上对比了YOLOv8smAP50-95提高了1.5个百分点但推理速度慢了大概10%。如果对精度有比较高的要求比如做宠物数量统计或者对边界框精度敏感的视觉检测应用YOLOv9值得尝试。如果做实时视频流检测YOLOv8s仍然是性价比更高的方案。新版本模型在训练时对显存的需求也会高一些因为模型结构更复杂。显存有限的用户别盲目追新先把当前版本的训练流程跑通再逐步尝试迁移升级。7. 写在实际操作之后这套猫狗检测数据集我前后用过很多次给我最大的感受是数据集的场景多样性和标注质量比模型结构的选择更影响最终效果。模型结构升级带来的精度提升可能只有两三个点而数据增强和数据集扩充带来的提升动辄五六个点。后面如果准备自己做数据集建议从一开始就要做好标注规范的把控YOLO格式的坐标归一化虽然简单但很容易出错。每做完一批标注立刻跑一遍可视化检查别等攒了几千张图再回头改那个成本会高到让人崩溃。还有一个建议是训练之前先确认目标部署场景。想好这个模型最终是用在室内摄像头、手机App还是户外机器人上然后围绕部署场景去组织验证集这样才能真正反映模型的实战效果。我自己的习惯是每次训练完都会保留一份完整的实验记录包括数据增强参数、学习率、batch大小、最终mAP和推理速度这样下次训练时可以直接参考对比。这个习惯帮我省了很多重复调参的时间推荐你也试试。后续如果有时间我打算在这套数据集基础上再扩一个猫狗品种分类的多类别版本同时加入一些遮挡、截断情况更复杂的样本。如果你正在做相关项目欢迎一起交流实验心得。