☰
YOLOv5实战指南:从环境配置到部署的完整避坑手册
2026/10/1 3:03:32 网站建设 项目流程

简介:一份面向YOLOv5初学者的完整代码仓库与实战课程配套包,源自B站系列教程,按入门、拓展、进阶、部署四个篇章组织学习路线。入门篇覆盖环境安装、模型推理、数据集构建与训练,并给出PySide6桌面界面和Gradio Web GUI的实现;拓展篇讲解AutoDL云端训练,以及PyCharm、VSCode连接远程服务器的技巧;进阶篇深入模型结构与构建原理,以C2f为例演示网络修改,以SE为例引入注意力机制,以MobileNet为例替换主干;部署篇涵盖TensorRT环境配置与推理加速、TorchHub模型预测,以及基于Flask的项目上线,适合想系统掌握YOLOv5从训练到落地的开发者。

压缩包共340个文件,包含115张jpg图片、56个Python脚本、53个yaml配置、45个txt说明,以及ipynb示例、pt/onnx权重、engine推理引擎、sh部署脚本、UI设计文件等,整体约275.62MB,目录按篇章分类,便于对照学习。当前已有138人学习浏览,包内还保留了训练日志、Dockerfile与TorchScript导出文件,可辅助复现每一步实验并快速迁移到不同部署环境。

1. YOLOv5.zip 是什么:一份能让你从零跑到部署的实战压缩包

拿到一个叫 YOLOv5.zip 的压缩包,第一反应通常是“这不就是源码包吗?”但你解压之后会发现,事情没这么简单。这份 zip 的核心并不是一堆等着你去读的 .py 文件,而是把 YOLOv5 从环境配置、数据集准备、模型训练、推理验证到部署落地的完整路径打包在了一起。你在网上搜 YOLOv5 相关问题时,最常见的就是环境配置失败、训练自己的数据集不知道怎么组织目录、超参数乱调导致模型不收敛。这个 zip 的定位,就是帮你把这些坑提前填平。

我见过很多人在 YOLOv5 上花的时间不是用在算法上,而是浪费在“装环境装了一天”“训练出来 mAP 很高但实际检测根本不能用”这些事上。这份实战笔记的价值在于:它告诉你源码里哪些文件是核心,哪些是装饰;训练自己的数据集时目录该怎么摆、yaml 该怎么写;推理时置信度和 NMS 怎么配合;部署到树莓派这类边缘设备时该走哪条路。适合的人群很明确:刚接触目标检测的本科生、要做毕设或工程项目的开发者,以及想把手头模型从 PC 挪到嵌入式平台上的硬件工程师。看完你至少能独立地训练一个可用的检测模型,而不是停留在跑通 demo 的阶段。

2. conda 环境配置与最小跑通:让 YOLOv5.zip 第一次画出检测框

2.1 先拆压缩包结构:哪些文件是真正要动的

解压 YOLOv5.zip 之后,第一件事不是急着跑代码,而是花两分钟把目录结构过一遍。YOLOv5 的目录设计相对规矩,核心文件就那几个,删掉也不影响主流程的只有一些辅助脚本。我一般建议新手先盯着这几样看:

  • detect.py:推理入口,加载训练好的权重对图片、视频、摄像头做检测。
  • train.py:训练入口,所有训练参数都从这里进。
  • models/:模型结构定义。yolov5s.yaml、yolov5m.yaml、yolov5l.yaml分别对应不同大小的网络,s 最小最快,l 最大最准。
  • data/:数据集配置模板,coco128.yaml是官方给的最小示例,教你 yaml 该怎么写。
  • utils/:训练过程中的辅助工具,比如损失计算、指标评估、日志记录。
  • weights/:存放权重文件的地方。如果 zip 里没带.pt文件,就得自己下载,或用export.py从其他格式转换。
  • requirements.txt:依赖清单,环境配置的核心依据。

这里有个容易踩的误区:很多人把models/里头的 yaml 当成网络结构定义文件,然后去乱改 depth_multiple 和 width_multiple 这两个参数。其实这两个参数是控制网络缩放比例的,新手不要动,默认值就是官方调好的。

2.2 用 conda 建一个不污染系统 Python 的环境

服务器或者自己电脑上的 Python 环境往往被各种项目搞得一团乱,所以用 conda 单独建一个虚拟环境是必须的。不要图省事直接在 base 环境里 pip install,你后面一定会后悔。我一般是这样做的:

conda create -n yolov5 python=3.8 -y conda activate yolov5 cd 解压后的YOLOv5目录 pip install -r requirements.txt

python=3.8这个版本号是经过验证的。YOLOv5 官方长期测试的版本是 3.8 到 3.10,选 3.8 是因为 PyTorch 对它的兼容性最好,后面装 torch 相关的轮子基本不会遇到“没有对应版本”的尴尬。requirements.txt里列出了 PyTorch、torchvision、opencv、numpy 等核心依赖,但这里有个问题:默认装的是 CPU 版 PyTorch,如果你有 NVIDIA 显卡,得先装 CUDA 版的 torch 再装其他依赖。

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

cu118对应 CUDA 11.8。注意先看nvidia-smi的驱动支持版本,如果驱动装得老,CUDA 12.x 的轮子可能跑不起来。装完之后用一段话验证环境是否正常:

python -c "import torch; print(torch.__version__, torch.cuda.is_available())"

如果输出是2.x.x+cuda且cuda.is_available()为 True,说明 GPU 环境通了。输出里带+cpu或者后半句是 False,那就回头检查 CUDA 版本和驱动,别急着往下走。

2.3 最小命令跑通 detect.py:验证环境和模型权重

环境装好,接下来要做的是用官方权重跑一次推理,确认整条链路是通的。这一步建议用官方预训练模型,不要一开始就用自己的数据集训练,问题定位会困难得多。最小命令长这样:

python detect.py --weights yolov5s.pt --source data/images/bus.jpg --conf-thres 0.4

如果不带--weights,YOLOv5 会自动下载 yolov5s.pt,下载时间取决于网络。要是发现下载不了,就自己找资源下载然后放到 YOLOv5 根目录。跑完之后,结果图默认输出到runs/detect/exp/下,打开看应该有人的检测框和置信度标注。

这条命令里值得解释的参数是--conf-thres。它控制的是置信度阈值,只有置信度分数超过 0.4 的框才会被保留。值设得越低,框越多,误检也越多;设得越高,框越少,漏检也越严重。新手先按 0.4 跑通,后面到调优阶段再慢慢体会。

2.4 权重文件放哪、CUDA 版本怎么对应

权重文件.pt存放位置没有硬性规定,只要你--weights参数指对路径就行。但工程上我建议统一放在项目根目录下新建weights/文件夹里,别散落得到处都是,因为训练过程中会生成一堆best.pt和last.pt,放乱了后面导出模型的时候找半天。

CUDA 版本对应是 YOLOv5 环境配置里最大的坑,热搜词里“yolov5环境配置”被搜那么多次不是没道理的。核心原则是:显卡驱动版本决定你能装什么 CUDA,torch.__version__里的 CUDA 版本和你安装的 CUDA Toolkit 版本不需要一致,只要 PyTorch 能调用驱动就行。所以你不需要去装一套完整的 CUDA Toolkit,只要装对 PyTorch 的轮子,驱动里自带 runtime,这就是为什么官方只让你用 pip 装 torch 而不是让你去折腾 CUDA Toolkit。判断驱动是否够新的方法很简单:显卡驱动越新越好,NVIDIA 官网查一下自己显卡型号对应的驱动版本,然后选择不高于驱动支持版本的最新 CUDA 轮子即可。

3. 训练自己的数据集:从标注到第一个自定义模型

3.1 数据标注与目录组织:labels 必须与 images 同名

YOLOv5 训练自己的数据集,目录结构是第一个能不能跑通的分水岭。官方要求图片和标签文件分离,且同一张图的图片路径和标签路径只有后缀不同。最标准的布局是这样:

datasets/ mydataset/ images/ train/ 0001.jpg 0002.jpg val/ 0001.jpg labels/ train/ 0001.txt 0002.txt val/ 0001.txt

labels/下每个 txt 文件与图片同名,内容每一行代表一个目标,格式是五列:

class_id x_center y_center width height

注意这四格坐标不是像素值,而是相对于图片宽度和高度的归一化比值。比如一张 640x640 的图片,目标中心在 (320, 160),宽 160,高 320,那么 txt 里写的是:

0 0.5 0.25 0.25 0.5

标注工具我一般推荐 LabelImg 或者 Labelme。LabelImg 导出的是 PASCAL VOC 格式的 XML,还需要转成 YOLO 的 txt 格式;Labelme 可以配置直接输出 YOLO 格式。实际上,用 LabelImg + 一个转换脚本仍然是大多数团队的习惯,因为 XML 格式便于二次检查。转换脚本网上很多,核心逻辑就是读 XML 里的bndbox坐标,除以图片宽高做归一化,然后按类别 ID 输出。

这里有一个很多人翻车的细节:类别 ID 必须从 0 开始连续编号。如果你有 3 个类别,ID 只能是 0、1、2,不能是 1、2、3,也不可以是 0、2、5。YOLOv5 在读取标签时如果发现类别 ID 超出你 yaml 里定义的类别数,会直接跳过该目标或者报错 DataLoader 相关异常。标注完先拿脚本检查一下有没有空标签文件,一个图片对应一个空 txt 是允许的(表示图里没有目标),但目录里混进来一个空文件会被当成单类别的“背景图”,影响训练。

3.2 写 dataset.yaml:路径、类别数、类别名

数据目录组织好之后,需要在data/下新建一个 yaml 文件,描述训练集和验证集路径及类别信息。以我常用的写法为例:

# data/mydataset.yaml path: /home/user/datasets/mydataset # 数据集根目录 train: images/train # 相对 path 的训练集图片目录 val: images/val # 相对 path 的验证集图片目录 nc: 3 # 类别总数 names: ['person', 'car', 'dog'] # 类别名,索引从 0 开始

path是根目录,train和val是相对根目录的路径。这里有个常见错误:有人把train直接写成/home/user/datasets/mydataset/images/train,然后path又写一遍根路径,导致最终路径被拼接成/home/user/datasets/mydataset//home/user/datasets/...,训练时持续报错找不到图片。YOLOv5 的 DataLoader 会把path和train/val用os.path.join拼接,所以train后面直接写相对路径就够了。

另外nc必须和标注文件里的类别 ID 最大值 +1 一致,names的顺序决定了检测结果里class_id映射的显示名称,顺序写错的话人会被识别成车,别问我是怎么知道的。

3.3 训练命令与必调参数:先跑通再调精度

数据 yaml 准备完毕,训练命令的执行方式如下。第一次跑建议直接复制这行:

python train.py --data data/mydataset.yaml --weights yolov5s.pt --epochs 100 --batch-size 16 --imgsz 640 --device 0 --name myexp

每个参数的职责需要讲清楚:

  • --epochs 100:训练轮数。100 是起步值,数据集小可以减到 50,v 的收敛曲线变化剧烈时就得跑够 200 甚至 300 轮。
  • --batch-size 16:每次迭代喂入的图片数量。显存不够就降到 8 或 4,但不要低于 2,否则 BN 层的统计量会不稳定,模型很难收敛。
  • --imgsz 640:训练时输入图片的缩放尺寸。图片不会直接暴力拉伸,会自动做等比缩放和 padding。值越大模型看到细节越多,显存占用也越大。
  • --device 0:指定使用 GPU 0。没有 GPU 就写cpu,但训练速度会慢到让你怀疑人生,500 张图可能要训一晚上。
  • --weights yolov5s.pt:迁移学习的起点。千万别从--weights ''开始随机初始化训练,小数据集很难训出像样的结果。

训练启动后终端会打印类似Epoch gpu_mem box obj cls labels img_size的表头,后面跟着一组数字。box是框回归损失,obj是置信度损失,cls是分类损失。这三个值随着训练进行应该震荡下降。不用盯着每个 batch 看,等到一个 epoch 结束后看它打印的平均值就够了。

3.4 训练日志里看什么:loss 曲线与 mAP 指标

训练过程中会在runs/train/myexp/下生成results.png,这张图是评判训练是否正常的核心依据。图里有三行关键曲线:train/box_loss、train/obj_loss、train/cls_loss,以及下方的metrics/mAP_0.5和metrics/mAP_0.5:0.95。

几个判断标准我用的是:

  1. box_loss 前 10 个 epoch 如果不下降,大概率是学习率太大或者数据集标签有误。
  2. mAP_0.5 最终能到 0.9 以上说明模型在自己数据集上表现良好;如果卡在 0.5 左右不上不下,说明特征区分度不足或者是标注本身有大量错漏。
  3. 训练结束时results.png里 train 和 val 的 loss 曲线如果开始分叉,也就是 train loss 还在降但 val loss 不再降甚至抬头,那就是过拟合了,需要加数据增强或调低学习率。

如果你用的是公司服务器训练,不可能老盯着终端,建议加上--project参数指定输出目录,然后定期去runs/train/下翻 results 图。另外,YOLOv5 在训练过程中默认每个 epoch 结束都会在验证集上跑一次评估,所以 mAP 曲线的横轴是 epoch 数,不是 iteration 数。当你看到 mAP 曲线呈现“爬坡-平台-突然下降”的形状,别紧张,平台是正常现象,突然下降往往是因为验证集里出现了标注失误或者图像尺寸异常。

4. YOLOv5 后处理与推理参数:让检测框别乱飘

4.1 置信度阈值和 NMS:两个参数不要独立看待

很多新手以为检测结果里框太多,就把--conf-thres从 0.25 往上调到 0.9,发现框少了,却漏掉了大量目标。这种粗暴调整方式不科学。目标检测输出的原始预测框远多于真实目标,后处理做了两件事:置信度筛掉一批低分框,NMS 去掉同一目标上重叠的框。这两个参数实际上是一对,需要配合调节,不能孤立的设置某一边。

以我在实践中总结出的经验为例,预训练模型跑通用场景推荐--conf-thres 0.25 --iou-thres 0.45,这是 YOLOv5 官方给的建议组合。当你的场景对误检容忍度低(比如安全帽检测报警),优先提高 conf;当你的场景对漏检容忍度低(比如缺陷检测),适当降低 conf,同时把 iou 也降低一些,去重更严格。NMS 的 IOU 阈值越高,保留的框越多,同一个目标可能出多个框;IOU 阈值越低,越倾向于合并重叠框,但目标密集时也容易把两个相近目标合并成一个。

4.2 detect.py 的推理参数:目标来源、输出目录、批次大小

推理阶段的操作比训练简单很多,但参数仍有其意义。以下是我在实际项目中常用的完整命令行格式:

python detect.py \ --weights runs/train/myexp/weights/best.pt \ --source data/images/test/ \ --conf-thres 0.3 \ --iou-thres 0.45 \ --imgsz 640 \ --save-txt \ --project runs/detect/test \ --name result

--save-txt会把检测结果的坐标输出成 txt 文件,跟标签格式一致,方便后续做数据分析或对接业务系统。--source可以是单张图片、图片文件夹、视频文件,甚至是摄像头设备号如0。在真实项目中,我一般先把一批图片放一个文件夹跑一遍,把生成的 txt 拉出来看看有没有漏检和误检,再决定要不要调参数。

这里有个细节值得留意:--imgsz推理时可以比训练尺寸大。比如训练用 640,推理用 768 或 832,小目标检出率通常会有肉眼可见的改善,代价是推理时间变长。YOLOv5 的模型结构里用了 SPPF 模块,对输入尺寸的变化并不敏感,所以推理尺寸不一定非得和训练一致。但不要差太大,从 640 直接跳到 1280 会让小目标反而消失,因为 padding 比例变了。

4.3 导出 ONNX:格式转换的三个边界坑

YOLOv5 训练完不能直接拿去部署,边缘设备上跑的是 ONNX、TensorRT 或 OpenVINO 中间表示。导出 ONNX 的命令是:

python export.py --weights runs/train/myexp/weights/best.pt --include onnx

导出成功之后,目录下多一个best.onnx。但这件事有三个边界坑,全是日常翻车重灾区:

第一,ONNX 的输入输出名在不同版本的 YOLOv5 里不一样。新版本的输出层名类似output0,是一个[1, 25200, 85]的矩阵,其中 25200 是 3 个尺度特征图的预测框总数,85 = 4 个坐标 + 1 个置信度 + 80 个类别概率。如果你用的是自己训练的模型,类别数不是 80,最后的维度要改成5 + nc。做推理部署的时候,要先打印模型输出 shape 确认这一点,别想当然用固定索引。

第二,export.py的--opset参数。默认 opset 版本在 CPU 上一般没问题,但部署到瑞芯微 RKNN 或某些 NPU 工具链时,opset 太高会不支持某些算子。我一般固定--opset 12,兼容性最好,即使损失了一点优化空间也可以接受。

第三,ONNX 里的 NMS 是放在模型外部的。YOLOv5 导出 ONNX 时默认不包含 NMS,你要么在应用层自己写非极大值抑制逻辑,要么在导出命令里加--nms让模型内部包含 NMS 算子。加了之后推理框架会更省事,但对某些只支持纯 CNN 算子的 NPU 芯片不友好。我的习惯是:部署到云端 CPU 服务用不带 NMS 的 ONNX,自己在代码里用 OpenCV 实现 NMS;部署到边缘 NPU 芯片,看工具链支持程度,默认先试不带 NMS 的版本。

5. YOLOv5 实战避坑:环境、训练、部署的 5 个血泪记录

5.1 训练到一半显存爆掉

现象:跑了几个 epoch 后,终端突然报CUDA out of memory,进程直接崩掉。有时即使把 batch-size 降到 4 还是爆显存。

原因:大多数时候不是 batch-size 的问题,而是--imgsz开的太大以及--workers数据加载进程太多。PyTorch 的 DataLoader 在 CPU 端预取图片加速,也会占用显存做缓存。另外如果同时用 GPU 做验证集评估,显存峰值会出现在验证那一刻,不是训练时刻。

解决:先调--batch-size 8 --workers 2,还有问题就把--imgsz 640降到512。再看nvidia-smi确认没有其他程序占用显存。玄学现象是,有时候重启电脑释放一下显存就恢复了,这通常是一些残留的 Python 进程占用。查ps aux | grep python,把无关进程杀掉再训。

5.2 loss 是 nan 或者开局就不下降

现象:训练第一个 epoch 打印的 box_loss 就是nan,或者 loss 一直保持一个固定值完全不降。

原因:nan最常见的是学习率太大导致的梯度爆炸,YOLOv5 默认学习率 0.01,在小规模数据集上偶尔会炸。另一种隐蔽原因是标注文件里坐标出现负数或者大于 1 的数值,归一化坐标越界,模型算 loss 时开根号产生 nan。

解决:首先检查标注文件里的数值是否都在 0 到 1 之间,出界就批量修数据。其次降低学习率,在训练命令里加--lr 0.001,再不行就换更小的模型从yolov5n.pt开始迁移学习。如果 loss 不降,检查类别 ID 是否从 0 开始、数据增强是否太凶狠(默认增强对大多数场景是友好的,不需要主动关)。

5.3 mAP 很高但实测一副惨样

现象:验证集上 mAP_0.5 能到 0.95,模型看起来完美,但拿真实场景的图片一测,漏检一堆、误检一堆,跟你训练的验证集完全是两个世界。

原因:这是数据集划分出了问题。我见过有人把同一段监控视频按帧抽了 1000 张图,随机分成 train 和 val,导致训练集和验证集里出现了大量相似度极高的“同卵图片”,评估指标虚高。真实场景的光照、角度、背景和训练集有分布差异时,模型自然就崩了。

解决:划分数据集必须按视频片段或场景划分,不能随机抽帧。比如 10 段视频,8 段进 train,2 段进 val。如果数据集本身规模只有几百张,就别指望泛化能力,老老实实去多采数据扩样本。另外在验证集之外再留一份“真实场景测试集”,每次训练完跑一遍,用这份结果决定模型是否放行。

5.4 树莓派上部署又慢又卡

现象:把 best.pt 直接在树莓派上加载 PyTorch 推理,一张 640x640 的图片耗时接近 2 秒,完全没法用。热搜词里“树莓派5上部署自己训练的yolov5模型”就是这一场景。原因很简单:Pytorch 的模型在 CPU 上跑,而且没有利用树莓派的 GPU 加速模块。

解决:先导出 ONNX,再用树莓派 5 的 NPU 工具链转换成专用格式。树莓派 5 自带的算力单元支持硬件加速,YOLOv5s 的推理速度能从 2 秒降到 100 毫秒级别。如果不想折腾 NPU 工具链,还有个折中方案:把模型剪枝成yolov5n或yolov5n6,再转 ONNX + 量化到 FP16 或 INT8。量化之后精度损失需要自己测,通常 mAP 掉 2% 到 5% 可以接受。不要指望直接在树莓派上用原版 PyTorch 跑出实时效果,这条路走不通,别浪费时间。

5.5 目标检测框偏了但置信度很高

现象:检测框画出来了,置信度 0.9 甚至 0.99,但框的中心位置和目标实际位置明显偏差,比如该框住整只猫的框只框住了猫头。

原因:训练时--imgsz 640,推理时却用了--imgsz 1280,输入分辨率变化导致目标位置归一化坐标在模型输出里被放大,后处理坐标还原时又用了错误的缩放系数。另一个常见原因是图片有 EXIF 旋转信息,OpenCV 读取图片时不会自动处理旋转,导致图片被转着输进了模型。

解决:推理用的--imgsz跟训练保持一致,不要随意加大。EXIF 旋转问题可以用 PIL 的ImageOps.exif_transpose先处理一遍再喂给模型。如果你用的是摄像头实时流,还需要注意摄像头的画面裁剪方式,常见做法是先统一letterbox缩放,再做坐标映射,否则框永远对不齐。

6. 验证模型能否真正上线:评估指标与超参数调整的一次完整复盘

训练完之后,模型最终能不能用,取决于验证阶段的评估是否扎实。我自己的习惯是这样的:训练结束第一件事,跑一次完整测试集评估:

python val.py --data data/mydataset.yaml --weights runs/train/myexp/weights/best.pt --task val

这个命令会输出每类别的 Precision、Recall、mAP_0.5、mAP_0.5:0.95 和混淆矩阵。我判断模型是否达标的标准是:Precision 和 Recall 的差距不要超过 10 个点。如果一个很高另一个很低,说明模型有严重的偏置。大部分时候我优化的目标是 mAP_0.5:0.95,而不是 mAP_0.5,因为前者的评判标准更严格,针对较小占比的目标会给出更真实的评价。

如果评估结果不理想,下一步是调超参数。YOLOv5 里有一份data/hyps/hyp.scratch-low.yaml,包含lr0(初始学习率)、momentum(动量)、weight_decay(权重衰减)、hsv_h(色调增强幅度)等。手动调参费时费力,我建议的做法是先用默认参数跑一轮作为 baseline,再用--hyp指向改了 2 到 3 个参数的 yaml 跑第二轮。别一次性动五六个参数,翻车了都不知道是谁的锅。

首选调的是lr0。数据量大(上万张图)就把默认 0.01 降到 0.005,让训练更稳;数据量小(几百张图)就提升到 0.02 配合更多 epoch,让模型更快收敛。其次是anchor相关,但这里我有个习惯:先不动它,因为 YOLOv5 有自动学习 anchor 的机制,训练时会自适应你的数据集尺寸。只有当你发现小目标明显漏检时,才考虑手动在模型 yaml 里改 anchor。最后一个冷静建议是:如果一轮训练跑完 mAP 已经到 0.9 以上,不要再纠结那 0.5 个点的提升,把精力花在部署和实际场景测试上,收益更大。

我自己做过一个让人印象深刻的教训:在完美数据集上把 mAP 调到了 0.97,结果上线遇到雨天场景直接掉到 0.6。后来我养成了每次训练数据里故意塞入一小部分光照异常、遮挡严重的图片,让模型不那么“娇气”。这种事情只有吃过亏才会重视。YOLOv5 这代模型确实不那么挑数据,但数据的多样性仍然决定了上线后体验的上限。希望你从一开始就走对方向,不要像我一样推倒重来。以上这些经验梳理自这个过程,希望帮到你。

本文还有配套的精品资源,点击获取

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

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

立即咨询