010、从零跑通第一个 YOLO 项目:猫狗检测全流程,踩坑记录与避坑指南

010、从零跑通第一个 YOLO 项目:猫狗检测全流程,踩坑记录与避坑指南 010、从零跑通第一个 YOLO 项目猫狗检测全流程踩坑记录与避坑指南开篇一个让人想砸键盘的报错上周五晚上我准备给新来的实习生演示YOLOv8的猫狗检测。笔记本上装的是Ubuntu 22.04显卡是RTX 3060CUDA 11.8一切看起来都很正常。我熟练地敲下pip install ultralytics然后跑官方demo——结果直接给我来了个RuntimeError: CUDA error: out of memory。我盯着终端看了三秒心想就一张640x640的图batch size1怎么可能爆显存后来发现是PyTorch偷偷给我装了个CPU版本CUDA根本没启用。这种坑我猜你迟早也会踩到。这篇文章不是教科书是我从零开始跑通YOLO猫狗检测的完整记录包括那些让我熬夜到凌晨两点的报错。我会把每个坑的现场还原出来告诉你当时我是怎么排查的以及现在我会怎么避过去。环境搭建别信“一键安装”Python版本陷阱YOLOv8官方说支持Python 3.8-3.11但如果你用3.12torchvision的某些依赖会直接编译失败。我见过有人用conda装了个3.12然后pip install ultralytics跑了一小时最后报No module named torchvision.ops。建议直接用Python 3.10这是目前最稳的版本。别问我为什么不是3.11问就是踩过坑——3.11下onnxruntime的某些算子会报NotImplementedError。CUDA版本匹配这里踩过坑很多人直接pip install torch torchvision torchaudio然后发现torch.cuda.is_available()返回False。原因很简单PyPI默认装的是CPU版本。正确做法是去PyTorch官网选对应CUDA版本的安装命令。比如CUDA 11.8就用pipinstalltorch2.1.0torchvision0.16.0torchaudio2.1.0 --index-url https://download.pytorch.org/whl/cu118别这样写pip install torch除非你确定你的环境已经配好了CUDA。我建议装完后立刻跑一行python -c import torch; print(torch.cuda.is_available())如果输出False直接停手先修环境再往下走。ultralytics版本别追新YOLOv8刚出的时候我第一时间装了0.0.16结果model.predict()的参数名跟文档对不上。后来发现是API还在改。现在稳定版是8.0.x建议直接pip install ultralytics8.0.200。别追最新版除非你想当小白鼠。YOLOv11出来之后ultralytics的API又变了一次如果你用v11的代码去调v8的模型会报KeyError: model。数据集准备猫狗大战的起点数据集结构官方文档没说的细节YOLO要求的数据集结构是这样的dataset/ ├── images/ │ ├── train/ │ │ ├── cat_001.jpg │ │ └── dog_001.jpg │ └── val/ │ ├── cat_002.jpg │ └── dog_002.jpg └── labels/ ├── train/ │ ├── cat_001.txt │ └── dog_001.txt └── val/ ├── cat_002.txt └── dog_002.txt注意图片和标签的文件名必须完全一致包括扩展名。我见过有人把图片命名为cat_001.jpg标签命名为cat_001.txt但图片是.jpg标签是.txt这没问题。但如果你图片是.jpeg标签是.jpg.txt那就等着报FileNotFoundError吧。标签格式别手写会疯YOLO的标签格式是class_id x_center y_center width height所有坐标都是归一化到[0,1]的。比如一张640x480的图一个猫框左上角(100, 50)右下角(300, 200)那么x_center (100 300) / 2 / 640 0.3125 y_center (50 200) / 2 / 480 0.2604 width (300 - 100) / 640 0.3125 height (200 - 50) / 480 0.3125所以标签文件里写0 0.3125 0.2604 0.3125 0.3125。这里踩过坑我一开始手算坐标结果小数点后四位没对齐模型训练出来检测框全偏了。后来直接用labelImg或者roboflow导出省心。数据集划分别用随机很多人直接sklearn.model_selection.train_test_split随机划分但这样会导致同一个视频帧序列里的图片被分到训练和验证集造成数据泄露。正确做法是按时间戳或者文件名前缀划分。比如猫狗数据集可以按文件名中的数字奇偶分奇数进训练偶数进验证。或者直接用ultralytics自带的dataset_split.py脚本。训练配置第一个坑在配置文件里data.yaml别漏了路径YOLO需要一个data.yaml文件来指定数据集路径和类别。比如train:/home/user/dataset/images/trainval:/home/user/dataset/images/valnc:2names:[cat,dog]这里踩过坑路径必须用绝对路径或者相对于你执行训练命令的路径。如果你用相对路径比如train: dataset/images/train但你在/home/user/下执行yolo train那它会在/home/user/dataset/images/train下找。如果你在/home/user/project/下执行那就找不到了。建议直接用绝对路径或者把data.yaml放在数据集根目录下然后路径写成./images/train。超参数别用默认YOLOv8的默认超参数是针对COCO数据集调的猫狗检测这种小数据集直接套用会出问题。比如lr00.01对于小数据集来说太大了容易发散。我一般这样调lr0:0.001# 小数据集用小学习率lrf:0.01# 余弦退火到初始学习率的1%momentum:0.937weight_decay:0.0005warmup_epochs:3.0warmup_momentum:0.8warmup_bias_lr:0.1别这样写lr0: 0.01除非你的数据集有10万张以上。猫狗检测一般几百张图学习率大了直接lossnan。batch size显存不够怎么办如果你显存只有4GBbatch size设成16会直接OOM。我试过RTX 3050跑YOLOv8nbatch size8都勉强。解决方案用--batch 4或者更小。用--device cpu但训练速度会慢10倍以上。用--cache把图片缓存到内存减少磁盘IO但会占用更多内存。这里踩过坑我一开始设batch size16然后报OOM我以为是模型太大换成了YOLOv8n还是OOM。后来发现是--workers设成了8数据加载线程太多每个线程都缓存了图片。改成--workers 2就解决了。训练过程那些让你怀疑人生的报错报错1RuntimeError: CUDA error: out of memory这个报错最常见但原因可能不是显存不够。我遇到过的情况PyTorch版本不对CUDA没启用但模型被加载到了CPU然后训练时试图转移到GPU但GPU显存被其他进程占了。数据加载时--workers太大每个worker都复制了一份模型参数。图片尺寸太大YOLO默认resize到640x640但如果你输入的是4K图resize后显存占用会暴增。排查方法先跑nvidia-smi看显存占用如果已经满了kill掉其他进程。如果没满试试torch.cuda.empty_cache()。如果还不行把batch size降到1看能不能跑。能跑的话就是batch size问题。报错2AssertionError: labels not found in dataset这个报错说明YOLO没找到标签文件。检查点标签文件是否存在文件名是否和图片一致。data.yaml里的路径是否正确。标签文件内容是否为空。YOLO不允许空标签文件如果你有图片没有目标标签文件里也要写一个空行或者干脆删掉那张图。这里踩过坑我用labelImg标注时有些图片没标任何目标labelImg生成了空标签文件。YOLO训练时直接报错。后来我写了个脚本把所有空标签文件对应的图片移出数据集。报错3ValueError: Expected more than 1 value per channel这个报错出现在Batch Normalization层原因是某个batch里只有一个样本batch size1或者某个类别的样本太少。解决方案增大batch size至少2以上。如果数据集不平衡比如猫有100张狗只有10张可以考虑数据增强或者过采样。用--nosave和--noplots减少日志输出有时候能绕过这个bug但治标不治本。报错4lossnan训练发散这个我遇到过两次。一次是学习率太大一次是标签坐标超出了[0,1]范围。排查方法检查标签文件看坐标是否在0-1之间。我见过有人把像素坐标直接写进去比如0 300 200 100 100这会导致loss爆炸。降低学习率比如从0.01降到0.001。检查数据增强参数hsv_h,hsv_s,hsv_v这些值太大也会导致颜色失真模型学不到特征。推理与可视化终于看到结果了推理命令别用默认参数训练完后用yolo predict modelruns/detect/train/weights/best.pt sourcetest.jpg推理。但默认的conf0.25可能太低会输出很多假阳性。我一般设成conf0.5猫狗检测这种简单任务0.5足够了。这里踩过坑我一开始用默认的conf0.25结果一张图里检测出5个猫实际上只有1个。后来调高阈值才正常。可视化别用OpenCV直接显示YOLO的results.show()会调用OpenCV的imshow但如果你在远程服务器上跑没有显示器会报cv2.error: OpenCV(4.8.0) :-1: error: (-5:Bad argument) in function imshow。解决方案用results.save()保存到文件。用results.plot()返回numpy数组然后用matplotlib显示。或者用--save参数自动保存结果图片。性能评估别只看mAPYOLO训练完会输出mAP50和mAP50:95但猫狗检测这种二分类任务mAP50:95可能虚高。我一般还看F1-score和混淆矩阵。可以用yolo val modelruns/detect/train/weights/best.pt datadata.yaml然后看输出的confusion_matrix.png。如果猫和狗经常互相误检说明特征区分度不够需要增加数据或者调整模型。踩坑总结我的个人经验环境是第一生产力。花一小时配环境比花一天debug值得。我现在的做法是用conda创建一个干净环境Python 3.10然后按PyTorch官网的CUDA版本装torch最后装ultralytics。装完立刻验证CUDA可用。数据集质量决定上限。我见过有人用网上爬的猫狗图很多是表情包、卡通图模型训练出来根本没法用。建议用公开数据集比如Oxford Pets、CIFAR-10的猫狗子集或者自己拍。标注时边界框要贴合目标别留太多背景。从小模型开始。YOLOv8n只有3.2M参数训练速度快适合调试。等模型能收敛了再换YOLOv8s或m。别一上来就YOLOv8x显存不够不说训练时间也长。日志是debug的钥匙。训练时用--verbose参数看每个epoch的loss变化。如果loss不下降检查学习率和数据。如果loss震荡检查batch size和梯度裁剪。别怕重来。我跑第一个YOLO项目时重装了三次环境改了五次数据集训练了十几次才出结果。每次失败都记下来下次就快了。最后如果你跑通了第一个YOLO项目恭喜你你已经迈过了最难的坎。接下来就是调参、优化、部署这些我会在后面的专栏里继续写。如果你在跑的过程中遇到我没提到的坑欢迎留言我会尽量回复。毕竟每个工程师都是从踩坑中成长起来的。