ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

YOLOv5自定义模型训练全流程:从数据标注到部署实战

YOLOv5自定义模型训练全流程:从数据标注到部署实战

1. 项目概述:从零到一掌握YOLOv5模型训练

最近在项目里用YOLOv5做了一批定制化的目标检测模型,从简单的物品识别到复杂的工业场景都有涉及。每次有朋友问起怎么训练自己的模型,我总得从头讲一遍,索性把整个流程和踩过的坑系统性地整理出来。目标检测这个领域,YOLO系列绝对是绕不开的,而YOLOv5以其出色的平衡性——速度快、精度不错、生态友好——成为了很多工程师和研究者入门乃至商用的首选。这篇文章的目的很直接:假设你手头有一批自己的图片,比如你想识别车间里的零件瑕疵、果园里的成熟水果,或者自己收集的某种特定物品,我将带你一步步完成数据准备、环境搭建、模型训练、评估优化的全过程,最终得到一个能实际跑起来的、属于你自己的检测模型。整个过程我会尽量说人话,把原理和实操结合起来,让你不仅知道怎么“点按钮”,更明白背后“为什么这么点”。

2. 核心思路与方案选型:为什么是YOLOv5?

在动手之前,我们得先搞清楚为什么选YOLOv5,以及面对自己的任务时,整个技术方案应该如何规划。目标检测的模型很多,从老牌的Faster R-CNN到后来的SSD,再到YOLO系列本身就有v1到v8等多个版本。选择YOLOv5,是基于几个非常实际的考量。

2.1 YOLOv5的核心优势与版本选择

首先,YOLOv5并非官方YOLO作者的作品,而是Ultralytics公司的开源项目,但这丝毫不影响它的流行。它的优势在于“工程化”做得极好。相比早期的YOLOv4配置复杂、环境依赖棘手,YOLOv5用PyTorch框架重写,环境配置一条pip install -r requirements.txt基本就能搞定,对新手极其友好。其次,它提供了从轻量到高精度的多个预训练模型(n, s, m, l, x),你可以根据你的硬件条件和精度要求灵活选择。比如在RTX 3060上,用YOLOv5s训练一个模型可能只需要几小时,而YOLOv5x则可能需要几天,但精度通常会更高。

注意:网络上常有关于YOLOv5和YOLOv8孰优孰劣的讨论。我的经验是,对于大多数自定义数据集训练的场景,尤其是数据量不大(几千张图片)时,YOLOv5的成熟度、社区资源和教程丰富度依然有巨大优势,更容易成功跑通并部署。YOLOv8在特定任务上可能有提升,但YOLOv5是一个经过充分实战检验的、更稳妥的起点。

2.2 自定义训练的整体工作流

训练自己的模型,本质上是一个“迁移学习”的过程。我们不会从随机初始化的权重开始训练(那需要海量数据和计算资源),而是站在巨人的肩膀上——使用在COCO等大型通用数据集上预训练好的模型权重作为起点。我们的任务,就是用自己特定的、带标注的数据,去微调(Fine-tune)这个模型,让它“忘记”一些通用的东西,转而“记住”我们关心的特定目标。

因此,整个流程可以拆解为以下几个核心阶段:

  1. 数据准备与标注:收集图片,并用标注工具框出目标,生成模型能读懂的标注文件。
  2. 环境配置与项目搭建:配置Python、PyTorch、CUDA等环境,克隆YOLOv5代码仓库。
  3. 数据格式整理与配置:将自己的数据集整理成YOLOv5要求的目录格式,并编写配置文件告诉模型你的数据在哪、有哪些类别。
  4. 模型训练与调参:启动训练,监控训练过程,根据情况调整超参数。
  5. 模型评估与测试:训练完成后,在验证集和新的图片上测试模型效果,分析性能。
  6. 模型导出与部署:将训练好的PyTorch模型转换为ONNX、TensorRT等格式,以便在不同平台(如Jetson Nano、移动端)上高效运行。

下面,我们就深入每一个环节,看看具体怎么做,以及有哪些需要特别注意的“坑”。

3. 数据准备:从图片到标准标注文件

数据是模型的“粮食”,粮食的质量直接决定模型的上限。这一步往往最耗时,但也最不能马虎。

3.1 图像数据采集的核心原则

你的图片从哪里来?可以是手机拍摄、网络爬取、公开数据集混合,或是工业相机采集。无论来源如何,都要遵循几个原则:

  • 多样性:目标物体要在不同的光照(强光、弱光、背光)、角度(正面、侧面、俯视)、背景、尺度和遮挡情况下出现。如果你的训练数据全是阳光明媚下的正面照,模型在阴天或侧面视角下很可能失效。
  • 代表性:图片必须覆盖你未来应用场景中可能出现的所有情况。比如做安全帽检测,就要包含远近不同、佩戴方式不同(甚至未正确佩戴)、与其他物体颜色相近的图片。
  • 数量与平衡:每个类别的图片数量不宜相差太远。如果一个类别有1000张图,另一个只有50张,模型会严重偏向数量多的类别。对于新手项目,每个类别准备200-500张质量较高的图片是一个不错的起点。
  • 分辨率一致:虽然YOLOv5训练时会自动将图片缩放到统一的尺寸(如640x640),但建议原始图片的长宽比不要差异过大,并且分辨率不宜过低,否则小目标的信息会丢失严重。

3.2 标注工具选择与实操要点

有了图片,就需要告诉模型目标在哪里。这需要用到标注工具,在图片上画出包围框(Bounding Box)并打上标签。目前最主流的是LabelImgRoboflow

  • LabelImg:开源免费,本地运行,支持PASCAL VOC(XML格式)和YOLO(TXT格式)两种输出。对于个人或小团队项目,它足够用了。
  • Roboflow:在线平台,提供了数据增强、版本管理、团队协作等更多功能,免费版有一定额度,适合更复杂的项目或团队使用。

这里以LabelImg为例,标注时要注意:

  1. 框要尽可能紧贴目标物体,但不要切入物体内部。框得太大会引入过多背景噪声,太小则会丢失物体边缘信息。
  2. 对于被遮挡的物体,只要可见部分超过50%,通常建议标注整个物体的预估位置。如果遮挡严重,可视情况舍弃或仅标注可见部分。
  3. 统一标注规范:比如“人”这个类别,是标注整个人体还是只标注头部?在项目开始前团队内部必须统一,并形成简单的标注文档。

标注完成后,LabelImg选择YOLO格式,会为每张图片生成一个同名的.txt文件。文件内容格式如下:

<class_id> <x_center> <y_center> <width> <height>

例如:0 0.5 0.5 0.2 0.3。这里的坐标是归一化后的,即中心点x坐标/图片宽度,中心点y坐标/图片高度,框宽度/图片宽度,框高度/图片高度。所有值都在0到1之间。

3.3 数据集目录结构规范

YOLOv5对数据集的目录结构有明确要求。一个清晰的结构能避免后续很多路径错误。建议按如下方式组织:

your_dataset/ ├── images/ │ ├── train/ # 训练集图片 │ │ ├── image1.jpg │ │ └── ... │ └── val/ # 验证集图片 │ ├── image100.jpg │ └── ... └── labels/ ├── train/ # 训练集标签 (与train/图片一一对应) │ ├── image1.txt │ └── ... └── val/ # 验证集标签 (与val/图片一一对应) ├── image100.txt └── ...

你需要手动将总图片按一定比例(如8:2或9:1)分割为训练集(train)和验证集(val),并分别放入对应的imageslabels文件夹下。验证集用于在训练过程中评估模型性能,防止过拟合,绝对不能与训练集重合。

实操心得:在划分数据集前,可以先对所有图片进行一遍简单的清洗,删除模糊、完全不相关或质量极差的图片。一个小技巧是,可以写个简单的Python脚本,利用哈希值去除完全重复的图片,避免数据泄露。

4. 环境配置与项目初始化

数据准备好了,接下来搭建训练环境。YOLOv5的环境配置相对简单,但仍有几个关键点。

4.1 基础环境搭建

首先确保你安装了Python(3.8或3.9版本兼容性较好)和pip。然后,强烈建议使用Conda或Venv创建独立的虚拟环境,避免包版本冲突。

# 使用Conda创建环境 conda create -n yolov5 python=3.8 conda activate yolov5

接下来,从GitHub克隆YOLOv5的官方仓库,并安装依赖。

git clone https://github.com/ultralytics/yolov5.git cd yolov5 pip install -r requirements.txt

requirements.txt里包含了PyTorch、torchvision、opencv-python等核心依赖。如果网络不畅,可以尝试更换pip源(如清华源、阿里源)。

4.2 PyTorch与CUDA的匹配

这是最容易出问题的一步。YOLOv5依赖PyTorch,而PyTorch需要与你的CUDA版本匹配才能调用GPU加速训练。首先,查看你显卡支持的CUDA版本(通过nvidia-smi命令查看)。然后,去 PyTorch官网 获取对应的安装命令。

例如,你的CUDA版本是11.8,可以这样安装:

pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118

安装完成后,在Python中运行以下命令验证GPU是否可用:

import torch print(torch.__version__) # 查看PyTorch版本 print(torch.cuda.is_available()) # 应为True print(torch.cuda.get_device_name(0)) # 显示你的GPU型号

如果torch.cuda.is_available()返回False,说明PyTorch未能正确识别你的CUDA环境,需要检查CUDA、cuDNN的安装以及PyTorch版本是否匹配。

4.3 准备数据集配置文件

我们需要创建一个YAML配置文件,告诉YOLOv5我们的数据集在哪里、有哪些类别。在yolov5/data/目录下,新建一个文件,例如my_custom_data.yaml

# 数据集配置文件:my_custom_data.yaml # 训练和验证图像的路径(可以是相对路径或绝对路径) train: ../your_dataset/images/train/ val: ../your_dataset/images/val/ # 类别数量 nc: 2 # 例如,我只有两个类别:'cat' 和 'dog' # 类别名称列表 names: ['cat', 'dog']
  • trainval路径:指向你之前创建的images/trainimages/val文件夹。
  • nc:你的目标类别总数。
  • names:类别名称列表,顺序很重要,它会与标注文件中的class_id(0, 1, 2...)一一对应。

5. 模型训练:参数解析与过程监控

万事俱备,可以开始训练了。训练命令看似简单,但里面的参数决定了训练的效率和最终模型的质量。

5.1 启动训练命令与核心参数

最基本的训练命令如下:

python train.py --img 640 --batch 16 --epochs 100 --data data/my_custom_data.yaml --cfg models/yolov5s.yaml --weights yolov5s.pt --name my_first_train

我们来拆解每个参数:

  • --img 640:输入图像的大小,会被自动缩放到长边为640的正方形。更大的尺寸(如1280)可能提升小目标检测精度,但会显著增加显存消耗和训练时间。
  • --batch 16:批处理大小(Batch Size)。一次迭代送入模型的图片数量。越大训练越稳定、越快,但受限于GPU显存。如果出现“CUDA out of memory”错误,首先降低batch大小(如改为8、4)。
  • --epochs 100:训练轮数。所有训练数据被完整遍历一次称为一个epoch。轮数太少模型学不够,太多可能导致过拟合。通常从100-300开始,根据验证集指标变化决定是否早停。
  • --data:指向我们刚创建的数据集配置文件路径。
  • --cfg:模型结构配置文件。yolov5s.yaml对应YOLOv5s小模型。你也可以选择yolov5m.yaml,yolov5l.yaml等。
  • --weights yolov5s.pt:指定预训练权重。yolov5s.pt会自动从Ultralytics的服务器下载。使用预训练权重是迁移学习的关键,能极大加速收敛并提升最终性能。
  • --name my_first_train:本次训练的实验名称。所有输出(模型权重、日志、图表)都会保存在runs/train/my_first_train目录下。

5.2 训练过程监控与日志解读

执行命令后,训练开始。控制台会输出类似以下信息:

Epoch gpu_mem box_loss obj_loss cls_loss Instances Size 0/99 3.21G 0.1xxxx 0.0xxxx 0.0xxxx 32 640: 100%|█████| 100/100 [01:23<00:00, 1.20it/s] Class Images Instances P R mAP50 mAP50-95: 100%|█████| 10/10 [00:05<00:00, 1.80it/s] all 100 500 0.850 0.780 0.820 0.550
  • 损失(Loss)box_loss(边界框回归损失)、obj_loss(目标置信度损失)、cls_loss(分类损失)。训练初期这些值会较高,随着训练进行应呈下降趋势。如果损失剧烈波动或长时间不降,可能是学习率过大、数据有问题或模型结构不适合。
  • 性能指标:每个epoch结束后会在验证集上计算。
    • P(Precision):精确率,模型预测为正的样本中,真正为正的比例。越高说明误报越少。
    • R(Recall):召回率,所有真实的正样本中,被模型预测出来的比例。越高说明漏报越少。
    • mAP50:以IoU(交并比)阈值为0.5计算的均值平均精度。这是衡量检测模型精度的核心指标,值在0~1之间,越高越好。
    • mAP50-95:IoU阈值从0.5到0.95(步长0.05)的平均mAP,是更严格的指标。
  • 可视化工具:训练结束后,在runs/train/my_first_train目录下,会生成一系列重要的可视化文件:
    • results.png:损失和指标随epoch变化的曲线图。这是分析训练过程最重要的工具。
    • confusion_matrix.png:混淆矩阵,查看各类别间的误检情况。
    • val_batchX_labels.jpgval_batchX_pred.jpg:验证集批次的实际标签和模型预测对比,直观看到检测效果。

5.3 超参数调优初探

YOLOv5有一个默认的超参数文件data/hyps/hyp.scratch-low.yaml。对于自定义数据集,微调超参数能进一步提升效果。最常调整的两个是学习率(lr0)和动量(momentum)。

  • 学习率(lr0):控制模型参数更新的步长。太大可能导致震荡不收敛,太小则收敛慢。一般可以从默认值(如0.01)开始,如果训练不稳定(损失NaN),可以尝试降低到0.001或0.0001。你可以通过--hyp参数指定自定义的超参数文件。
  • 数据增强:YOLOv5默认开启了Mosaic、MixUp等强力的数据增强,这能有效提升模型泛化能力,防止过拟合。如果你的数据集非常小,可以保持或增强;但如果你的数据集已经很大且多样,有时适度减弱增强(如降低旋转、缩放的程度)反而可能让模型更快收敛到更好的位置。

实操心得:第一次训练时,建议先用小模型(如YOLOv5s)、较少的epoch(如50)跑一个“快速实验”,目的是验证整个数据流水线(数据格式、路径、标注)是否正确。看到损失在正常下降,验证集上有一定的mAP后,再换大模型、延长epoch进行“正式训练”,这样可以节省大量时间。

6. 模型评估、测试与导出

训练完成后,我们得到了保存在runs/train/my_first_train/weights/下的最佳权重(best.pt)和最后权重(last.pt)。接下来就是检验成果的时候了。

6.1 模型性能评估

使用val.py脚本,在验证集上对训练好的模型进行正式评估:

python val.py --weights runs/train/my_first_train/weights/best.pt --data data/my_custom_data.yaml --img 640

这会输出详细的评估表格,包含每个类别的精确率、召回率、mAP等。仔细分析这些数据:

  • 如果某个类别的P很低但R很高,说明模型对这个类别“宁可错杀不可放过”,误检很多。
  • 如果某个类别的R很低,说明模型漏检了很多这个类别的目标。
  • 通过混淆矩阵,可以看是否经常把A类别误检为B类别,这可能是两者外观相似,需要补充更多区分性的训练数据。

6.2 使用模型进行推理测试

用训练好的模型对新图片或视频进行检测,使用detect.py脚本:

python detect.py --weights runs/train/my_first_train/weights/best.pt --source test_image.jpg # 检测单张图片 python detect.py --weights runs/train/my_first_train/weights/best.pt --source test_video.mp4 # 检测视频 python detect.py --weights runs/train/my_first_train/weights/best.pt --source 0 # 调用摄像头实时检测

检测结果会保存在runs/detect/exp/目录下。这是最激动人心的环节,看看你的模型在“实战”中表现如何。如果发现某些场景下检测不好,可以有针对性地补充这些场景的数据到训练集中,进行下一轮训练(增量训练)。

6.3 模型导出为部署格式

要在生产环境(如服务器、嵌入式设备Jetson Nano、手机)中高效运行模型,通常需要将PyTorch模型(.pt)转换为其他格式。

  • 导出为ONNX:ONNX是一种开放的模型交换格式,被很多推理引擎支持。
    python export.py --weights runs/train/my_first_train/weights/best.pt --include onnx
  • 导出为TensorRT:如果你在NVIDIA GPU上部署,TensorRT能提供极致的推理速度加速。
    python export.py --weights runs/train/my_first_train/weights/best.pt --include engine --device 0
    注意导出TensorRT引擎需要本地有TensorRT环境。

导出时,务必注意模型的输入输出尺寸(--img)要与训练和推理时保持一致。导出的模型就可以被集成到C++、Python或其他语言的应用程序中了。

7. 常见问题与排查技巧实录

在实际操作中,你几乎一定会遇到各种问题。这里我整理了最典型的几个及其解决方法。

7.1 训练过程中的常见错误

问题现象可能原因解决方案
CUDA out of memory1.Batch Size太大。2. 模型太大(如用了YOLOv5x)。3. 输入图片尺寸太大。1. 减小--batch参数。2. 换用更小的模型(如从l换到m)。3. 减小--img参数(如从640到320)。
Loss为NaN1. 学习率过高。2. 数据标注有严重错误(如坐标超出0-1范围)。3. 数据中存在损坏的图片。1. 降低学习率(修改hyp文件中的lr0)。2. 检查标注文件格式。3. 使用verify=True参数在训练前验证数据集。
mAP一直为0或很低1. 数据集路径或配置文件错误,模型根本没读到数据。2. 类别ID与names列表不匹配。3. 数据质量极差或任务本身太难。1. 检查my_custom_data.yaml中的路径是否正确。2. 确认标注文件中的class_id是从0开始,且小于nc。3. 可视化一些训练样本(train_batch0.jpg),看图片和标注框是否正常显示。
训练很快过拟合1. 训练数据太少。2. 数据增强不够。3. 模型复杂度远高于任务需求。1. 收集更多数据,或使用数据增强。2. 在hyp文件中调整增强参数(如增加mosaic,mixup的概率)。3. 换用更小的模型。

7.2 推理部署时的典型问题

  • 检测框置信度阈值选择detect.py默认使用--conf-thres 0.25。如果发现很多误检,可以调高这个值(如0.5);如果发现漏检多,可以调低这个值(如0.1)。这是一个需要在精确率和召回率之间权衡的参数。
  • 在Jetson Nano等边缘设备上速度慢
    1. 务必使用TensorRT加速。先在x86机器上导出TensorRT引擎(.engine文件),再部署到Jetson。
    2. 降低推理时的输入图像分辨率(--img 320)。
    3. 使用最轻量的模型(YOLOv5n或YOLOv5s)。
    4. 确保Jetson Nano运行在最大功率模式(sudo nvpmodel -m 0)。
  • 检测不到小目标
    1. 增加训练时的输入尺寸(--img 1280),但这会大幅增加计算负担。
    2. 在模型结构上,可以尝试修改models/yolov5s.yaml中的detect层前的上采样方式,或引入注意力机制(如SimAM、ECA)来提升小目标特征提取能力。但这属于进阶修改,需要一定经验。
    3. 最根本的,确保你的训练数据中包含足够多、标注清晰的小目标样本。

7.3 数据层面的技巧与陷阱

  • 标注一致性:多人标注时,即使有规范,对“模糊目标”的判断也可能不同。建议定期进行交叉检查,或者由一个人进行最终审核,确保标准统一。
  • 负样本:YOLO本身不严格需要负样本(不含任何目标的图片),但加入一些背景图片(即不含任何待检测目标的图片)可以帮助模型降低将背景误判为目标的概率。只需将这些图片放入images/train/images/val/,并创建对应的空标签文件(.txt内容为空)即可。
  • 数据增强的度:过强的数据增强(如大角度的旋转、极端的色彩抖动)可能会让模型学习到不真实的模式,特别是对于方向、颜色有明确意义的物体(如交通标志)。需要根据具体任务调整增强策略。

训练自己的YOLOv5模型是一个迭代的过程,很少有一次就达到完美效果的情况。通常的流程是:准备一版数据 -> 训练一个基线模型 -> 在测试集上评估 -> 分析错误案例(哪些没检测到、哪些误检了)-> 针对性地补充或修正数据 -> 重新训练。经过几轮这样的循环,模型的性能会得到稳步提升。这个过程本身,就是对问题和数据理解不断加深的过程,也是机器学习项目中最有价值的部分。

返回列表