YOLOv5实战:手把手教你训练自己的目标检测模型(附数据集+代码)
YOLOv5实战:从零构建自定义目标检测模型的全栈指南
如果你刚接触计算机视觉,面对“目标检测”这个词,可能会觉得它离实际项目很远。但当你真正开始动手,用YOLOv5训练一个识别自家宠物的模型,或者为工厂流水线开发一个零件瑕疵检测系统时,那种将前沿技术落地的成就感是无与伦比的。YOLOv5的出现,极大地降低了这个门槛——它不再是一个仅供学术研究的“黑盒子”,而是一套开箱即用、文档清晰、社区活跃的工业级工具。
与那些需要你从零搭建网络、反复调试损失函数的框架不同,YOLOv5将最佳实践封装成了简洁的命令行和配置文件。但这并不意味着它简单到无需理解。恰恰相反,想要用好它,避免在数据、训练和部署的各个环节踩坑,你需要一套系统性的实战思维。这篇文章不会重复那些随处可见的算法原理,而是聚焦于如何将YOLOv5用起来,解决真实世界的问题。我们将从环境搭建、数据准备、模型训练、调优到最终部署,手把手带你走完全流程,并分享那些官方文档里不会写的“血泪经验”。
1. 环境配置:打造稳定高效的训练基地
在开始任何机器学习项目之前,一个稳定、可复现的环境是成功的基石。YOLOv5基于PyTorch,这为我们提供了极大的灵活性,但也意味着需要仔细管理依赖。
1.1 基础环境搭建
我强烈建议使用Conda来管理你的Python环境。它能完美解决不同项目间依赖冲突的噩梦。以下命令将创建一个名为yolov5的独立环境,并安装指定版本的Python。
conda create -n yolov5 python=3.8 -y
conda activate yolov5
接下来,根据你的硬件安装PyTorch。访问 PyTorch官网 获取最适合你CUDA版本的安装命令。例如,对于CUDA 11.3:
pip install torch==1.12.1+cu113 torchvision==0.13.1+cu113 torchaudio==0.12.1 --extra-index-url https://download.pytorch.org/whl/cu113
注意:务必核对你的NVIDIA驱动支持的CUDA最高版本(通过
nvidia-smi查看)。安装不匹配的CUDA版本是新手最常见的错误之一。
1.2 克隆与安装YOLOv5
YOLOv5的代码托管在GitHub上,更新非常活跃。建议克隆官方仓库并安装其依赖。
git clone https://github.com/ultralytics/yolov5.git
cd yolov5
pip install -r requirements.txt
安装完成后,运行一个简单的测试命令,验证环境是否正常。这会自动下载一个小型的预训练模型(yolov5s.pt)和一张测试图片。
python detect.py --weights yolov5s.pt --source data/images/bus.jpg
如果一切顺利,你会在 runs/detect/exp 目录下看到一张带有检测框的图片。恭喜,你的YOLOv5环境已经就绪。
1.3 硬件考量与加速技巧
你的硬件配置将直接决定实验的迭代速度。
- GPU:这是最重要的部分。YOLOv5训练可以充分利用GPU的并行计算能力。即使是GTX 1660 Ti这样的消费级显卡,也能显著快于CPU训练。对于更严肃的项目,RTX 3080/4090或Tesla V100等专业卡是更好的选择。
- CPU与内存:数据加载和预处理会占用CPU资源。建议使用多核CPU(如Intel i7或AMD Ryzen 7以上)和至少16GB内存,以避免数据加载成为训练瓶颈。
- 磁盘:数据集,特别是图像数据,可能非常庞大。使用SSD能极大加快数据读取速度。
为了最大化GPU利用率,你可以在训练命令中调整 --workers 参数(用于数据加载的进程数)和 --batch-size。--img-size 也影响显存占用和速度。一个常见的组合是:
python train.py --img 640 --batch 16 --epochs 100 --data coco128.yaml --weights yolov5s.pt --workers 4
2. 数据准备:模型性能的“七寸”
在目标检测项目中,数据准备往往占据70%以上的时间和精力。低质量的数据会直接导致模型性能的天花板极低。
2.1 数据收集与标注
你的数据需要尽可能贴近模型最终的应用场景。例如,做交通标志检测,就应该在真实的道路场景、不同的天气和光照条件下采集图片。
标注工具的选择很多,LabelImg、CVAT 和 Roboflow 是常见的选择。LabelImg简单易用,CVAT功能强大且支持协作,Roboflow则提供了从标注到增强的一站式云服务。
标注时,有几点至关重要:
- 边界框要紧贴目标物体,既不要留太多空隙,也不要切掉物体部分。
- 类别定义要清晰且互斥。例如,“汽车”和“卡车”如果有重叠,需要明确区分规则。
- 标注所有可见的目标,特别是那些被部分遮挡的。模型需要学习处理不完整的目标。
2.2 数据集格式与结构
YOLOv5要求特定的数据格式。每个图像对应一个同名的 .txt 标注文件。标注文件每行代表一个物体,格式为:
<class_id> <x_center> <y_center> <width> <height>
这里的坐标是归一化的(取值0-1),即相对于图像宽度和高度的比例。
一个典型的数据集目录结构如下:
custom_dataset/
├── images/
│ ├── train/
│ │ ├── image1.jpg
│ │ └── image2.jpg
│ └── val/
│ ├── image3.jpg
│ └── image4.jpg
└── labels/
├── train/
│ ├── image1.txt
│ └── image2.txt
└── val/
├── image3.txt
└── image4.txt
你需要创建一个YAML配置文件(如 data/custom.yaml)来告诉YOLOv5你的数据集在哪里,以及有哪些类别。
# data/custom.yaml
path: ../datasets/custom_dataset # 数据集根目录
train: images/train # 训练集图像路径(相对于path)
val: images/val # 验证集图像路径(相对于path)
# 类别数量及名称
nc: 3
names: ['person', 'car', 'dog']
2.3 数据增强:以“量”补“质”
我们很难获取覆盖所有场景的无限数据。数据增强通过对现有图像进行随机变换,来模拟未知的视觉变化,从而提升模型的泛化能力。YOLOv5内置了强大的增强策略,主要通过 hyp.scratch.yaml 或 hyp.finetune.yaml 文件控制。
其增强手段非常丰富,远超简单的翻转和旋转。以下是一些关键增强及其作用:
| 增强类型 | 作用描述 | 典型参数 |
|---|---|---|
| Mosaic | 将四张训练图像拼接为一张,让模型在单张图中学习识别不同尺度、上下文的目标。 | mosaic: 1.0 |
| MixUp | 以一定比例混合两张图像及其标签,创造平滑的过渡样本。 | mixup: 0.5 |
| 随机透视 | 模拟相机视角变化,如远近、倾斜。 | perspective: 0.001 |
| 色彩抖动 | 调整色调(H)、饱和度(S)、明度(V),模拟光照变化。 | hsv_h: 0.015 |
| 平移/缩放 | 随机平移和缩放图像,让模型不依赖目标在图像中的固定位置。 | translate: 0.2 |
对于自定义数据集,一个常见的策略是:从较小的增强强度开始。如果你的数据集本身质量高、多样性好,过强的增强反而可能引入噪声,损害性能。你可以通过 --hyp 参数指定使用不同的超参数文件。
python train.py --data custom.yaml --weights yolov5s.pt --hyp hyp.finetune.yaml
3. 模型训练与核心调优策略
有了高质量的数据,训练本身更像是一门科学实验,需要系统地观察、假设和验证。
3.1 选择正确的起点:预训练权重
YOLOv5提供了从 YOLOv5n (纳米) 到 YOLOv5x (超大) 一系列不同大小和速度的模型。-s 模型最小最快,精度最低;-x 模型最大最慢,精度最高。
永远从预训练权重开始! 这是在COCO等大型数据集上训练好的模型,其骨干网络已经学会了提取通用视觉特征(如边缘、纹理)。使用预训练权重进行迁移学习,能让你用少得多的数据和 epochs 获得更好的效果。
# 使用预训练的 yolov5s 权重在自定义数据上训练
python train.py --img 640 --batch 16 --epochs 100 --data custom.yaml --weights yolov5s.pt
3.2 监控训练过程:理解这些曲线
训练启动后,YOLOv5会在 runs/train/exp 目录下生成一系列可视化结果,最重要的是 results.png 和 val_batchX_labels.jpg。
- 损失曲线(Box, Obj, Cls):关注它们的下降趋势。一个健康的训练过程,损失应平稳下降并最终趋于平缓。如果损失剧烈震荡或很早就停止下降,可能是学习率过大、批次大小不合适或数据有问题。
- 性能指标(Precision, Recall, mAP@0.5):
- 精确率(Precision):模型预测为正的样本中,真正为正的比例。高精确率意味着“宁可错过,不可错杀”。
- 召回率(Recall):所有真实的正样本中,被模型正确找出的比例。高召回率意味着“宁可错杀,不可错过”。
- mAP@0.5:在IoU阈值为0.5时的平均精度均值,是衡量检测器综合性能的核心指标。它应该随着训练稳步上升。
如果召回率很低但精确率尚可,说明模型漏检了很多目标。这可能是因为模型置信度阈值太高,或者锚框(anchor)与你的目标尺寸不匹配。相反,如果精确率很低,说明模型产生了大量误检。
3.3 超参数调优:不是玄学
YOLOv5的 hyp.yaml 文件包含了所有重要的超参数。盲目调整它们通常收效甚微。以下是几个有明确指向性的调优思路:
- 学习率(lr0):这是最重要的超参数。太大会导致损失震荡甚至发散,太小则收敛缓慢。一个可靠的策略是使用学习率预热(warmup) 和余弦退火(cosine)调度器(YOLOv5默认启用)。如果你调整了批次大小(batch-size),通常需要按线性比例缩放学习率(例如,批次扩大4倍,学习率也大致扩大2倍)。
- 锚框(Anchors):YOLOv5会在训练开始时自动在你的数据集上运行K-means聚类,重新计算适配你目标尺寸的锚框。你可以在日志开头看到
AutoAnchor: Running kmeans for 9 anchors on 1000 targets...。如果你的目标尺寸非常特殊(如极细长的物体),可以关闭自动锚框(--noautoanchor)并手动设计。 - 数据增强强度:如前所述,根据数据集情况调整
hyp.yaml中的增强参数。小数据集需要更强的增强,大数据集可以弱一些。
提示:一次只改变一个变量,并做好实验记录。使用工具如 Weights & Biases 或 TensorBoard(YOLOv5已集成)可以更方便地对比不同实验。
4. 模型评估、推理与部署
训练完成后,你得到的 .pt 文件不仅包含了模型权重,还包含了模型结构、超参数等元数据,是一个完整的可部署单元。
4.1 全面评估模型
不要只看验证集上的mAP!用训练好的模型在一个全新的测试集上运行评估,更能反映其真实泛化能力。
python val.py --weights runs/train/exp/weights/best.pt --data custom.yaml --task test
同时,使用 detect.py 在一些具有挑战性的真实场景图片或视频上做可视化检查,看看模型在复杂背景、遮挡、小目标等情况下的表现。
# 检测单张图片
python detect.py --weights best.pt --source path/to/test_image.jpg
# 检测视频
python detect.py --weights best.pt --source path/to/video.mp4
# 使用摄像头实时检测
python detect.py --weights best.pt --source 0
4.2 模型导出:通向生产环境
PyTorch的 .pt 文件在研究和原型阶段很方便,但要部署到移动端、嵌入式设备或某些生产服务器,你需要将其转换为更高效的格式。
- TorchScript:PyTorch自带的序列化格式,可以在没有Python环境的C++中运行。
- ONNX:开放的神经网络交换格式,被众多推理引擎(如TensorRT, OpenVINO)支持。
- CoreML:用于苹果生态系统(iOS/macOS)。
- TensorRT:NVIDIA GPU上的极致推理优化引擎。
YOLOv5提供了便捷的导出脚本:
# 导出为 ONNX 格式
python export.py --weights best.pt --include onnx
# 导出为 TensorRT 格式(需要CUDA环境)
python export.py --weights best.pt --include engine --device 0
导出后,务必用 detect.py 的 --weights 参数指向导出的文件(如 best.onnx)进行验证,确保转换过程没有精度损失。
4.3 部署模式选择
根据你的应用场景,部署策略大不相同:
- 云端API服务:使用 FastAPI 或 Flask 快速搭建一个Web服务,接收图片并返回检测结果。这是最灵活的方式。
- 边缘设备:在Jetson Nano、树莓派等设备上,使用TensorRT或OpenVINO优化后的模型,追求极致的能效比和低延迟。
- 移动端App:将模型转换为CoreML(iOS)或TFLite(Android)格式,集成到应用中。
这里是一个使用FastAPI创建极简检测API的示例:
# main.py
from fastapi import FastAPI, File, UploadFile
import cv2
import torch
from yolov5.utils.general import non_max_suppression, scale_coords
from yolov5.models.experimental import attempt_load
import numpy as np
app = FastAPI()
model = attempt_load('best.pt', device='cpu') # 加载模型
@app.post("/detect/")
async def detect(file: UploadFile = File(...)):
contents = await file.read()
nparr = np.frombuffer(contents, np.uint8)
img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 预处理
img_processed = preprocess(img_rgb) # 需要实现预处理函数,如resize, normalization
# 推理
with torch.no_grad():
pred = model(img_processed)[0]
# 后处理(NMS等)
detections = postprocess(pred, img.shape) # 需要实现后处理函数
return {"detections": detections}
启动服务:uvicorn main:app --reload。现在,你就可以通过发送HTTP请求来使用你的目标检测模型了。
从环境配置到模型部署,这条路径上的每一步都有其独特的挑战和乐趣。YOLOv5的强大之处在于,它为你处理了底层绝大部分的复杂性,让你能更专注于解决业务问题本身。记住,第一个能跑通的模型只是起点,持续的数据迭代、针对性的模型优化和扎实的工程化,才是让AI真正创造价值的关键。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)