☰
YOLO猫狗检测实战:数据集详解与模型训练全流程指南
2026/10/1 8:07:04 网站建设 项目流程

猫狗检测算是我入行目标检测这块最早接触的项目之一,这几年做下来,从最早的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.yaml

data.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 python=3.9 -y conda activate yolov8 pip install ultralytics==8.2.0 pip install torch==2.1.2 torchvision==0.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范围,通常说明标注工具有问题或者有脏数据。极端情况下,如果坐标值轻微超出,比如width=1.05,训练时不一定会报错,但损失会异常偏高,影响收敛。

再做一步可视化检查,用OpenCV把标注框画到图上,人工抽检几十张图片,确认框是否贴合目标、类别是否正确。这一步虽然费点时间,但能发现很多标注工具的隐蔽错误,比如类别编号错位、框没有完全包裹目标、目标过小导致框退化成一个点等。可视化检查是训练前的最后一道防线,我几乎每次都会做。

3. 完整训练流程与核心参数调优

3.1 训练配置与启动命令

准备好数据集后,训练这块我用ultralytics的标准命令行就够了。以下是我在这套猫狗数据集上实测稳定的训练命令:

yolo train \ model=yolov8s.pt \ data=dataset/data.yaml \ epochs=150 \ imgsz=640 \ batch=16 \ device=0 \ workers=4 \ optimizer=AdamW \ lr0=0.001 \ lrf=0.01 \ patience=20 \ project=./runs \ name=cat_dog_experiment

各参数的含义和选择依据如下:

  • model=yolov8s.pt:加载预训练权重。COCO数据集上训过的权重已经学到了通用的特征表示,迁移到猫狗检测只需要微调后面的检测头即可,训练速度快很多。如果从零开始训练的话,150个epoch可能都不够收敛,而且精度明显偏低。

  • epochs=150:二分类任务不算复杂,150轮足够模型充分收敛。配合patience=20的早停机制,如果连续20轮验证集mAP没有提升,训练会自动停止,不会浪费时间。

  • imgsz=640:默认输入尺寸,和预训练权重一致。如果你希望提升小目标检测能力,可以试试imgsz=768或960,但显存消耗会增加不少,推理速度也会下降。

  • batch=16:我测试时用的是16G显存的卡,16的批大小刚好把显存吃满。显存小的卡可以调成8,不过学习率也要相应调整,后面会细说。

  • optimizer=AdamW:YOLOv8默认的优化器是AdamW,并且内置了warmup和cosine学习率调度。实测下来,AdamW在这套数据集上收敛比SGD平稳,前期不容易出现loss爆炸的情况。

  • patience=20:早停耐心值。如果训练到第70轮时模型精度就不再提升,继续硬跑150轮纯属浪费显卡寿命。早停机制能节省不少时间。

3.2 训练过程中的损失函数观察

训练过程中,终端会实时打印每个epoch的训练损失和验证指标。需要重点关注这几个指标的变化:

  • train/box_loss:边界框回归损失,数值下降说明模型预测框的位置越来越准。
  • train/cls_loss:分类损失,下降说明模型对猫狗分类的置信度越来越高。
  • train/dfl_loss:分布聚焦损失,这是YOLOv8新增的回归分支损失,趋势同样应该是下降的。
  • metrics/mAP50:IoU阈值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。具体来说,batch=4、累积4步,等效于batch=16的效果。ultralytics支持通过参数batch=4以及accumulate=4实现梯度累积:

yolo train \ model=yolov8s.pt \ data=dataset/data.yaml \ epochs=150 \ imgsz=640 \ batch=4 \ accumulate=4 \ device=0

batch大小调整时,学习率也需要跟着变。常用的经验法则是线性缩放学习率:原计划batch=16、lr0=0.001,改成batch=8时,建议把lr0调整到0.0005左右。如果你的显卡只能跑batch=4,学习率设为0.00025会更稳。我在实际调参中发现,学习率偏高时损失曲线会出现锯齿状震荡,下降过程不平滑;学习率偏低时收敛速度明显变慢,相同epoch数下mAP低1到2个百分点。找到那个“居中值”需要一点耐心,我的习惯是先跑30个epoch看趋势,再决定要不要调。

3.4 数据增强参数的实际调整

YOLOv8内置了丰富的数据增强策略,默认参数已经比较均衡。但针对猫狗检测这个特定场景,我建议对几项增强做微调。

  • hsv_h、hsv_s、hsv_v:色调、饱和度、明度的随机调整。宠物毛色差异很大,增强可以增加模型对毛色的鲁棒性。我设置hsv_s=0.5、hsv_v=0.4,能让模型不过度依赖毛色特征。

  • degrees:随机旋转角度。猫狗图片有大量竖屏拍摄的情况,如果不做旋转增强,模型对旋转目标的适应能力会很差。但我没有把degrees拉太高,因为宠物图片虽然有角度变化,但多数情况还是正向或接近正向的。设成degrees=10就差不多了,太高会造成大量无效学习。

  • perspective:透视变换强度。这个增强模拟相机角度变化,但强度太大会导致目标变形严重,反而干扰检测。我设成0.0005,只做极轻微的透视扰动。

  • mosaic:马赛克增强是YOLO系列最核心的增强方式,把四张图拼在一起训练。默认mosaic=1.0能够显著提升模型的泛化能力,尤其是小目标检测能力。但在训练后期,建议把mosaic关掉或调低,因为拼出来的图片目标尺寸和真实场景有偏差,影响最终精度的收敛。ultralytics支持在训练后段自动关闭马赛克,不需要手动干预,这是我很喜欢的一个特性。

这些增强参数怎样设置?可以在训练命令中添加如下参数,实测对这套数据集效果很好:

yolo train \ model=yolov8s.pt \ data=dataset/data.yaml \ epochs=150 \ imgsz=640 \ batch=16 \ hsv_h=0.015 \ hsv_s=0.5 \ hsv_v=0.4 \ degrees=10 \ perspective=0.0005

4. 训练后的评估分析与模型导出

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(format='onnx', opset=12) # 导出为TensorRT格式(需要GPU) model.export(format='engine', half=True, imgsz=640)

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, conf=0.5, imgsz=640, device=0, verbose=False) 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()

conf=0.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, alpha=alpha, beta=beta) return adjusted

把类似操作加到数据加载流程中,能显著提升模型对光照变化的鲁棒性。我在这套猫狗数据集上用过这个方法,夜间暗光场景的漏检率明显下降。

5.2 小目标检测效果差怎么办

宠物检测场景中,小目标指画面中占比较小的宠物。我在数据集中专门保留了一部分小目标图片,但训练过程中发现,如果小目标占总样本的比例太低,模型的注意力会被大中目标主导。

解决方向有三个:

一是提高输入分辨率。把imgsz从640增加到960,对提升小目标检测效果最直接,代价是显存占用和推理耗时上升。

二是调整anchor或使用更高分辨率的特征层。YOLOv8是Anchor-Free结构,不能直接调anchor数量,但可以修改检测头输出的特征尺度。ultralytics库的配置文件允许自定义模型结构,不过这属于进阶操作,新手建议先从imgsz入手。

三是增加小目标样本的采样权重。如果用自己的数据集,可以统计每张图中目标框的面积,把小目标占比高的图片复制几份混入训练集,强制模型多学这些样本。

我在真实项目中试过一种很有效的增强方式:整体缩放图片后再贴到黑色背景上,相当于把小目标“人为放大”之后再训练。效果的提升肉眼可见,mAP50-95大概能涨两个点。

5.3 训练不收敛或损失异常升高

训练过程中出现loss=nan或者突然升高,原因排查优先级如下:

先看学习率是否过大。学习率过高最典型的特征就是损失值在某个epoch后突然变nan。解决方法是降低lr0,同时把warmup_epochs调大,让模型在初始阶段更平稳地过渡。

再看数据是否有异常。注意标注文件里坐标值是否为0或者坐标值超界。试过一张图片的txt文件里记录了坐标以外的不规范字段,训练时模型直接把那张图的损失推到了几百,导致整体指标震荡。

然后看batch size和BN层。YOLOv8在batch很小的时候,BatchNorm的统计量非常不稳定,可能出现训练集损失正常但验证集loss异常偏高。如果batch=4还出现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张数据集上对比了YOLOv8s,mAP50-95提高了1.5个百分点,但推理速度慢了大概10%。如果对精度有比较高的要求,比如做宠物数量统计或者对边界框精度敏感的视觉检测应用,YOLOv9值得尝试。如果做实时视频流检测,YOLOv8s仍然是性价比更高的方案。

新版本模型在训练时对显存的需求也会高一些,因为模型结构更复杂。显存有限的用户,别盲目追新,先把当前版本的训练流程跑通,再逐步尝试迁移升级。

7. 写在实际操作之后

这套猫狗检测数据集我前后用过很多次,给我最大的感受是,数据集的场景多样性和标注质量,比模型结构的选择更影响最终效果。模型结构升级带来的精度提升可能只有两三个点,而数据增强和数据集扩充带来的提升动辄五六个点。

后面如果准备自己做数据集,建议从一开始就要做好标注规范的把控,YOLO格式的坐标归一化虽然简单,但很容易出错。每做完一批标注,立刻跑一遍可视化检查,别等攒了几千张图再回头改,那个成本会高到让人崩溃。

还有一个建议是,训练之前先确认目标部署场景。想好这个模型最终是用在室内摄像头、手机App还是户外机器人上,然后围绕部署场景去组织验证集,这样才能真正反映模型的实战效果。

我自己的习惯是每次训练完都会保留一份完整的实验记录,包括数据增强参数、学习率、batch大小、最终mAP和推理速度,这样下次训练时可以直接参考对比。这个习惯帮我省了很多重复调参的时间,推荐你也试试。

后续如果有时间,我打算在这套数据集基础上再扩一个猫狗品种分类的多类别版本,同时加入一些遮挡、截断情况更复杂的样本。如果你正在做相关项目,欢迎一起交流实验心得。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询