简介面向目标检测学习者和AI工程实践者的Yolov5Pytorch自定义数据集训练完整教程包覆盖环境安装、数据标注与预处理、数据集划分、模型配置、训练参数调整、结果评估与部署全流程并涉及数据增强、模型微调、多GPU训练等进阶话题。压缩包为ZIP格式约13.81MB共69个文件20个Python脚本负责训练、推理与数据处理9个YAML文件定义模型结构和数据配置另有JPG/PNG/JPEG示例图片及MD/Readme/PDF说明文档目录按weights、data、models、runs等模块划分便于对照查阅。已有302人学习适合希望快速跑通目标检测训练流程并将Yolov5应用到自定义场景的开发者。借助其中的权重下载脚本、数据检查工具和训练/推理示例可快速完成从数据准备到模型部署的实战验证并基于自身项目修改配置做二次开发。1. 这个压缩包标题在讲什么用 Yolov5 Pytorch 跑通自有数据集的完整链路这个压缩包标题把目标检测入门最刚需的那条链路说透了Yolov5 负责模型和训练逻辑Pytorch 负责算力调度你要补的只剩自己的数据集和标注。“超详细”指向的是每个参数都要讲、每个报错都要有对策“优质项目实战”说的不是看不见的成果包而是“跟着做完真能跑出自己的权重”这件事。它适合两类人一类是刚接触目标检测、纯小白连 PyTorch 环境都没搭过另一类是有检测任务但不想从零写网络的工程师只想把数据集换成自己那批图。一句话判断只要你要检测的不是 COCO 那 80 类而是安全帽、车牌、船舶、产品缺陷这类专用场景这套流程就是投入产出比最高的路线。下面按环境、数据、训练、排查、验证五步拆解每一步都能照着敲。2. 环境先行PyTorch 版本与 Yolov5 代码包的匹配逻辑很多人在环境这一步就翻车了根因不是装不装得上而是版本错配。Yolov5 代码本身对 PyTorch 比较友好但 torch 的版本又和显卡驱动、CUDA 运行时绑在一起这三者只要有一个对不上后面训练日志里就会出现一堆看不懂的报错。这一章我把环境搭建拆成三步先查驱动选 torch 版本再拉代码装依赖最后用一次推理验证环境。2.1 先查驱动再装 torchCUDA、cu118 与 cu121 怎么选第一步永远是查显卡驱动nvidia-smi这个命令会输出显卡驱动版本和驱动支持的最高 CUDA 版本。比如看到 NVIDIA-SMI 537.42、CUDA Version 12.3说明这块显卡驱动能支撑到 CUDA 12.3那么装 torch 的 cu121 或 cu118 版本都没问题。很多教程会让你直接去装最新版 torch其实没必要PyTorch 的 CUDA 版本只要求不高于驱动支持的最高版本向下兼容。我一般建议装 cu118 这一版torch 2.0.1 torchvision 0.15.2。原因是它的生态最成熟Yolov5 大量测试就在这套组合上跑过网上报错案例也最多搜起来快。装法如下conda create -n yolov5 python3.9 -y conda activate yolov5 pip install torch2.0.1 torchvision0.15.2 --index-url https://download.pytorch.org/whl/cu118这里用 conda 而不是直接 pip 装是为了隔离环境。python 选 3.9是因为 3.10 以上在某些旧版依赖上会有兼容小坑3.8 以下又太老。装完后立刻验证一下python -c import torch; print(torch.__version__, torch.cuda.is_available())如果输出 2.0.1cu118 True说明 GPU 通道是通的如果输出 cpu 后缀或者 False别急着换驱动大概率是 pip 默认装到了 CPU 版重装一遍指定 cu118 的 torch 就行。这里有个血泪经验不要用 conda 默认源装 pytorch默认源的 CUDA 版经常是旧编译装上后 torch.cuda.is_available() 返回 False排查半天才发现是源的问题。2.2 拉取 Yolov5 代码包release 分支与依赖安装环境准备好后拉代码。常见做法是从官方 GitHub 仓库 clonegit clone https://github.com/ultralytics/yolov5.git cd yolov5 git checkout v7.0 pip install -r requirements.txt这里为什么从 master 切到 v7.0master 分支现在处于维护模式代码还在持续变动训练结果和很多老教程对不上v7.0 是 yolov5 生命周期里最后一个大版本网络结构、训练脚本、权重格式都是网上最多人验证过的。你再对比 Yolov11 那套 ultralytics 全家桶会发现训练入口已经统一成 yolo train 命令目录结构也变了教程抄起来更费劲。所以纯小白入门选 v7.0阻力最小。requirements.txt 会自动装好 opencv-python、matplotlib、seaborn、pandas 这些依赖。opencv 负责图像读取matplotlib 负责绘制训练曲线。如果安装过程中有个别包下载慢常见做法是把 pip 换成国内镜像源在命令后加 -i 加镜像地址即可。装完依赖后把 yolov5s.pt 放到项目根目录这个权重后面训练和验证都要用。2.3 首次推理验证环境是不是真的通了依赖装完不代表代码没问题最快的验证方式是用官方自带的图和官方权重跑一次推理python detect.py --weights yolov5s.pt --source data/images/bus.jpg如果一切正常会在 runs/detect/exp 下生成一张画了框的 bus.jpg。这一步是整套流程的冒烟测试同时验证三件事模型权重能加载、图像预处理链路正常、后处理画框逻辑正常。跑完再去跑训练就不会把环境问题和训练参数问题混在一起排查了。这里补一条判断标准detect.py 跑成功之后再用 Python 确认 GPU 已经被 Pytorch 接管import torch print(torch.cuda.is_available()) print(torch.cuda.get_device_name(0))能打出 GPU 名字说明显卡通道没问题打不出来就回到 2.1 重装 torch。很多新人跳过了这一步后面训练时发现速度很慢、显存从来不涨最后才回头找原因白白浪费半天时间。3. 把数据集变成 YOLO 格式标注、目录结构、划分与 data.yaml数据准备是整个流程里最花时间、最容易被低估的一步。模型结构是现成的训练命令是固定的唯一完全由你决定的就是数据质量。这一章解决三件事怎么标注出 YOLO 格式的 txt怎么把图片和标签按规则摆放以及怎么写 data.yaml 让 train.py 找到它们。3.1 LabelImg 标注直接输出 YOLO 格式的 txt标注矩形框最常用的工具是 LabelImg它支持直接输出 YOLO 格式。安装和启动很简单pip install labelimg labelimg打开界面后先在左侧把保存格式切到 YOLO再用 Create RectBox 沿着目标边缘画框每个框选一个类别最后保存。保存后每张图片会对应生成一个同名 txt里面每一行是一个框的信息格式是 class_id x_center y_center width height四个坐标值都是 0 到 1 之间的归一化值。这个格式的含义是框的中心点坐标和宽高都除以了图片本身的宽高。一张 1920x1080 的图里中心在 (960, 540)、宽 192、高 108 的框写出来就是 0 0.5 0.5 0.1 0.1。训练时 Yolov5 会按归一化坐标去还原框如果你标注前把图片 resize 过再标框就全错了。标注时有一个细节容易被忽略图片里那些模糊、被遮挡一部分的目标也要尽量标出来尤其是你想检测的目标。漏标等于给模型喂了这个不算目标的负样本后面 mAP 上不去一半原因是漏标太多一半才是网络的问题。如果你用公开数据集比如 CCPD 车牌数据集、HRSC2016 船舶数据集它们自带标注但往往不是 YOLO 格式最常见的是 VOC 的 XML 或 COCO 的 JSON需要先转成 txt 再用。3.2 标准目录结构images 与 labels 的排队规则Yolov5 的 train.py 在读取数据时默认按图片目录和标签目录同级、文件名一一对应的规则找数据。最标准的布局是datasets/ |-- images/ | |-- train/ | |-- val/ |-- labels/ |-- train/ |-- val/训练时 data.yaml 只需要写到 images 那一层Yolov5 会自动把路径里的 images 替换成 labels 去找标注。这个约定是代码写死的不要自己改目录名。train 和 val 的比例常规是 9:1 或 8:2如果你的数据总量少于 100 张建议先别急着训练而是想办法扩充数据。几百张图跑出来的模型换一张没见过的图就可能漏检这在安全帽、车牌这类场景里是很现实的问题。我见过不少人把图片放一个文件夹、标签放另一个完全不相关的文件夹然后在 data.yaml 里试图用绝对路径强行拼接这样跑是能跑但数据校验时经常报找不到标签文件排查起来很痛苦。按默认规则来最省事。还要注意图片格式统一jpg、png 都能用但不要混着来尤其要小心手机拍的 jpg 带 EXIF 旋转信息Yolov5 读取时不会自动纠正方向框会偏移。统一转成标准 jpg 能省掉这个隐患。3.3 数据集划分脚本固定随机种子保证可复现手动把一两百张图分到 train 和 val 还能接受数据到上千张就必须写脚本了。下面这个划分脚本我一直在用核心是复制而不是移动源文件保留一份原始备份避免误删import os import random import shutil random.seed(42) src_img raw_images # 原始图片目录 src_lab raw_labels # 原始标签目录 train_img datasets/images/train val_img datasets/images/val train_lab datasets/labels/train val_lab datasets/labels/val os.makedirs(train_img, exist_okTrue) os.makedirs(val_img, exist_okTrue) os.makedirs(train_lab, exist_okTrue) os.makedirs(val_lab, exist_okTrue) files [f for f in os.listdir(src_img) if f.lower().endswith((.jpg, .png))] random.shuffle(files) split int(len(files) * 0.9) for i, name in enumerate(files): label name.rsplit(., 1)[0] .txt img_dst train_img if i split else val_img lab_dst train_lab if i split else val_lab shutil.copy(os.path.join(src_img, name), os.path.join(img_dst, name)) shutil.copy(os.path.join(src_lab, label), os.path.join(lab_dst, label)) print(train:, split, val:, len(files) - split)脚本作用是把 90% 的数据放进 train10% 放进 val。random.seed(42) 保证了每次运行划分结果一样这对实验可复现很重要。如果你要改比例动 split 那一行就行。划分完成后顺手做一个校验打印 train 和 val 下 jpg 的数量与 txt 数量是否相等不等就先别进下一步。这个校验能挡掉后面训练时的绝大部分数据路径问题。3.4 data.yaml 写法nc、names 与路径的坑Yolov5 不会自动识别你的类别必须用一个 yaml 文件告诉它你的任务。这个文件一般放在项目根目录或 datasets 目录下train: datasets/images/train val: datasets/images/val nc: 2 names: [cat, dog]train 和 val 建议写相对路径路径的基准是运行 train.py 时的当前工作目录不是 data.yaml 所在目录。千万别写绝对路径换机器或换目录结构后必挂。nc 是类别总数names 是类别名列表顺序必须和标注时 classes.txt 的顺序完全一致如果标注时 cat 是 0、dog 是 1names 就必须 [cat, dog]写反了模型不会报错但训练出来的类别含义是反的这种错最隐蔽。有人会把 nc 写错成 3 但 names 只有两个train.py 在数据校验阶段会直接报 class number 相关的错误。如果你是单类检测比如只检安全帽nc 就是 1names 写 [helmet]。用公开数据集时先确认类别是单类还是多类再定 nc 和 names。data.yaml 写好后可以用一条命令快速检查配置能否被正确读到python train.py --data data.yaml --weights yolov5s.pt --epochs 1 --batch-size 2 --img 640如果能跑完一个 epoch 并输出类别数和图片数数据和配置就没问题。4. 用 Yolov5 训练自有数据集train.py 参数全解与首个模型数据就位之后训练命令本身反而是最简单的部分。这一章先把模型选择讲清楚再逐项拆 train.py 的参数最后说训练过程中哪些输出值得看、哪些不用看。第一次训练的核心目标不是拿高分而是确认整套流水线是通的。4.1 选哪个预训练权重s/m/l/x 与输入尺寸的取舍Yolov5 官方提供了 s/m/l/x 四种规格区别是网络深度和宽度不同。选型参考下表权重参数量速度精度适合场景yolov5s.pt约 7.2M快够用入门、边缘设备、实时视频yolov5m.pt约 21.2M中等较强通用场景、中等算力yolov5l.pt约 46.5M较慢高服务器、追求精度yolov5x.pt约 86.7M最慢最高小目标、难分类场景我的建议是直接从 yolov5s.pt 开始。s 在 640 输入下能跑得动大部分 6G 显存以内的卡训练时间可控从 s 跑通流程后再换 m 或 l只需要改 --weights 参数数据和命令都不用动。不要一上来就用 x训练时间翻好几倍新手阶段没有意义。输入尺寸 --img 默认 640。如果你的目标是遥感船舶或者远处的鸟这类小目标可以试 --img 1280代价是显存明显上涨、训练时间变长。反过来如果目标是安全帽这种大目标480 甚至 416 也能保持不错精度。Yolov5 网络结构图里的 CSPDarknet 骨干就是通过这个输入尺寸决定最终特征图大小的改 img 是调精度和速度最直接的杠杆。第一个模型先用 640 跑基线后面再对比 480 或 1280不要上来就调各种 yolov5 超参数。4.2 train.py 必调参数epochs、batch-size、img、workers 与缓存环境就位、数据格式正确后训练命令长这样python train.py \ --data datasets/data.yaml \ --weights yolov5s.pt \ --epochs 100 \ --batch-size 16 \ --img 640 \ --device 0这一行命令里的每个参数都值得理解。--data 指向上一章写好的 yaml--weights 是预训练权重路径Yolov5 会基于它做迁移学习。--epochs 是训练轮数第一次建议 50 到 100 之间数据量小的时候 100 轮足够收敛数据量大再往上加。--batch-size 受显存限制16 是稳妥的中位值6G 显存降成 84G 显存降到 4。训练时显存占用率最好控制在 90% 以下否则偶尔一个峰值就会触发 CUDA out of memory。--img 是输入尺寸--device 0 表示用第一张 GPU。几个容易被忽略的辅助参数python train.py --data datasets/data.yaml --weights yolov5s.pt \ --epochs 100 --batch-size 16 --img 640 \ --device 0 --workers 4 --cache ram --patience 30 \ --project runs/train --name first_run--workers 是数据加载线程数Windows 上设成 0 更稳设成 4 以上偶尔会报 DataLoader worker 崩溃这是老生常谈的坑。--cache ram 会把图片预加载进内存明显减少每个 epoch 的等待时间但内存少于 16G 时慎用可以改成 --cache disk 把缓存写到磁盘。--patience 是早停参数30 表示连续 30 轮 val mAP 没有提升就自动停止省时间也防过拟合。--project 和 --name 控制输出目录跑了多个实验时一定要分开命名否则权重会被互相覆盖。4.3 训练过程中看什么results.png、mAP 与一个正负样本细节训练启动后终端会滚动输出每一轮的信息包括 box_loss、obj_loss、cls_loss 和 mAP0.5、mAP0.5:0.95。这里最关键的是看 loss 是否在下降、mAP 是否在上升。Yolov5 会把整条曲线画进 runs/train/first_run/results.png训练结束直接打开这张图比盯终端日志直观得多。第一次训练如果你的 mAP0.5 能到 0.5 以上说明流程没问题到 0.9 以上说明数据和标注都不错长期在 0.2 以下先回第 3 章检查数据不要纠结超参。训练结束后weights 目录下会有两个文件best.pt 和 last.pt。best.pt 是在验证集上 mAP 最高的一轮last.pt 是最后一轮推理和部署都用 best.pt。还有一个常见疑问要不要调超参首次训练不需要hyp.scratch.yaml 里的学习率、mosaic 概率这些官方默认就是覆盖多数场景的均衡值调超参是个玄学事情用同一批数据跑上几轮对比才有意义。先跑通一次再谈优化。yolov5 后处理阶段的 NMS 阈值、conf-thres 也先保持默认后面验证环节再根据实际误检调。5. 训练翻车排查六个最常见的问题与处理办法训练流程跑通是一回事训练过程遇到报错是另一回事。下面六条基本都是真实环境里反复出现的我按现象、原因、解决的顺序写你遇到类似报错直接按步骤排查比翻完整份日志强。5.1 torch.cuda.is_available() 为 False环境装成 CPU 版现象检测不到 CUDA训练日志里显示 device cpu显存占用始终为 0。原因多数情况是安装 torch 时没有指定 CUDA 版pip 默认装了 CPU 版另一种是系统 CUDA 驱动版本太旧低于 torch 编译时的要求。解决先跑 nvidia-smi 确认驱动再按第 2 章的指定 index-url 命令重装对应 cu118 的 torch。注意不要只装 torchtorchvision 的版本也要和 torch 匹配否则 import 时会报 mismatch 警告甚至直接失败。如果你用的是笔记本双显卡还要确认不是独显没被调用把 --device 0 改成 --device 1 试试。5.2 CUDA out of memorybatch 和 img 都压了还是爆显存现象训练到某一步时弹出 RuntimeError: CUDA out of memory有时是刚开始就报有时是跑了几百张图后突然爆。原因显存占用是 batch-size、输入尺寸、模型规格三者的乘积任何一个偏大都会爆。常规步骤是调小 batch但如果已经调到 2 还爆就要看是不是 --img 设了 1280或者用了 yolov5x。解决把 --img 降到 640 或 480把 --weights 换回 yolov5s再把 --workers 设成 0。加载预训练权重时优化器状态也会占显存如果还不行关掉其他占用显存的程序浏览器硬件加速经常被忽略。用 nvidia-smi 实时看显存占用峰值长期顶到 99% 就是快爆的前兆。5.3 图片与标签对不上数据校验阶段提示 no labels现象训练启动后提示 train: No labels in xxx或者打印的图片数量和标签数量差距很大训练也在走但 mAP 基本为 0。原因标注文件的路径没放对或者文件名和后缀和图片不匹配。最常见的是图片是 .JPG 大写后缀脚本里只匹配 .jpg还有的标注工具导出多了前缀或空格。解决先把图片统一转成小写 .jpg再跑一段对账脚本import os img_dir datasets/images/train lab_dir datasets/labels/train imgs [f for f in os.listdir(img_dir) if f.lower().endswith(.jpg)] missing [f for f in imgs if not os.path.exists(os.path.join(lab_dir, f[:-4] .txt))] print(total:, len(imgs), missing labels:, len(missing)) print(missing[:10])这段脚本会把缺标签的图片名打出来。缺几个就补标注或删对应图片如果 missing 是大几十多半不是漏标而是目录结构错了回看 3.2 的标准布局。5.4 类别 id 与 names 顺序不一致训练不报错但结果全乱现象训练过程一切正常loss 也在降但看混淆矩阵预测的类别和真实类别错位。A 类的目标被反复识别成 B 类而且不是精度问题是稳定的错。原因标注的时候 classes.txt 里 A 是 0、B 是 1但 data.yaml 的 names 写成了 [B, A]模型学习到的索引和名称对不上输出结果就被错误映射。解决打开任意一张标注 txt看第一列的数字范围再对照 data.yaml 的 names。txt 里的数字只认索引名字是你最后解释用的凡是标注环节换过类别顺序都要重新确认一遍。这个错很难靠训练调参解决只能改 data.yaml 然后重新训练。5.5 loss 一直在降但 mAP 不涨是过拟合还是数据太少现象训练到后半段 train loss 还在降甚至接近零但 val mAP 稳定不再升或者还往下掉。原因典型的过拟合信号尤其数据集只有一两百张图、目标单一、场景相似时最容易出现。另一个隐蔽原因是验证集图片和训练集有重复比如划分脚本没固定随机种子或者数据来自同一个视频帧验证集看着是新的实际内容差不多。解决固定随机种子重新划分数据把 epochs 降到 50 左右开 --patience 30 让它自己停。先排除验证集混入的问题再尝试调整数据增强强度比如把 hyp.scratch.yaml 里的 flipud 从 0.5 降到 0.1看 val mAP 是否稳住。这里最容易走的弯路是去调学习率学习率不是这个问题的根因。5.6 换机器后加载 best.pt 报错PyTorch 版本不匹配现象同一份权重在自己机器上推理正常换到另一台机器加载时报错常见的是 Error(s) in loading state_dict 或找不到某些 key。原因PyTorch 版本跨度太大或者另一台机器的 torch 是 CPU 版模型结构里某些层的权重名称对不上。Yolov5 换环境最容易忽略的就是 requirements.txt 版本约束。解决新机器上按第 2 章完整装一遍依赖尽量保持和训练时一致的 torch 主版本。如果报错依然存在还有一个快速通道把权重重新导出成更通用的格式比如先在本机用 torchscript 导出再拷走或者导出 ONNX对方机器直接跑 ONNX 推理绕开 PyTorch 版本差异。这个后悔药在第 6 章展开写。6. 从 best.pt 到正式使用val.py、detect.py 与 ONNX 导出6.1 val.py 验证先看 mAP 再看 P/R训练完别急着上 detect。先用 val.py 在验证集上算一次标准化指标python val.py --data datasets/data.yaml --weights runs/train/first_run/weights/best.pt --img 640输出里 mAP0.5 是主要参考P 和 R 分别代表精确率和召回率。业务更在意漏检就多关注 R更在意误检就多关注 P。输出里还有每个类别的 AP 列表哪个类弱一眼就清楚优先补那个类的数据。6.2 detect.py 推理与 conf-thres / NMS 后处理验证通过后把模型用在真实图片或视频上python detect.py --weights runs/train/first_run/weights/best.pt \ --source test_videos/01.mp4 --conf-thres 0.25--conf-thres 是置信度阈值它和 yolov5 后处理里的 NMS 参数一起决定最终输出的框。阈值调低框变多、误检也变多调高则相反。对运动模糊、遮挡多的视频我会把 conf-thres 放到 0.15 再配一个低 NMS宁可多几个误检也不愿意漏掉一次关键目标。这个阈值本质是业务取舍不是越大越好。6.3 export.py 导出 ONNX从权重到部署的第一步如果你的项目最终要跑在 RK3568、树莓派或者 K210 这类边缘设备上PyTorch 权重不能直接用要先导出python export.py --weights runs/train/first_run/weights/best.pt --include onnx导出后再用 onnxruntime 推理或转成 RKNN、TensorRT 等格式做部署。这一步要注意导出的 ONNX 输入尺寸是训练时的 img 大小部署端的预处理也必须按同样尺寸做 letterbox否则结果偏移。我自己的习惯是每次训练完先打开 results.png 确认 best 点在曲线上的位置再用 val.py 看一遍每个类别的 AP最后才导出。建议你也养这个习惯能少走很多弯路。希望帮到你。本文还有配套的精品资源点击获取