简介:一份面向YOLOv5初学者的完整实战代码仓库,源自B站手把手课程,系统覆盖入门、拓展、进阶、部署四个篇章,适合希望从环境搭建到模型部署全流程跟学的开发者和学生。压缩包共340个文件,以Python训练/推理脚本、YAML模型配置为主,同时包含pt、ONNX、TensorRT engine等模型权重与部署产物,以及jpg样例图片、ipynb笔记、md文档和mp4讲解视频,整体约275MB。已有137人参与学习。资源内按篇章组织:入门篇覆盖环境安装、模型推理、数据集构建与训练,并演示PySide6用户界面和Gradio Web GUI;拓展篇讲解AutoDL服务器训练与IDE连接;进阶篇包含C2f结构修改、SE注意力机制、MobileNet主干替换;部署篇涉及TensorRT加速、TorchHub预测和Flask项目部署。跟随资源可同时获得完整代码、模型文件与配套说明,适合逐模块对照演练。
1. 这份 YOLOv5 实战资源:别只盯着权重,仓库里的每个文件都是课程答案
做目标检测的同行应该都有过这种经历:YOLOv5 的代码仓库看了无数遍,clone 下来就跑通了官方推理,但真到训练自己的数据集、再部署到服务端,每一步都像在黑匣子里试错。这份《手把手带你实战YOLOv5.zip》是 B 站手把手实战课程的配套代码仓库,覆盖入门、拓展、进阶、部署四个阶段,从环境安装到模型推理、数据集构建、训练调参,再到 TensorRT 加速和 Flask 部署,一条线走完。压缩包里不是一堆散乱的 py 文件,而是课程每一讲的落地产物:训练指标、TensorBoard 日志、多平台 Dockerfile、以及 TensorRT 引擎文件。适合三类人:刚跑通 YOLOv5 想训自己数据集的初学者、卡在部署环节的工程师、还有想系统梳理网络结构修改思路的进阶用户。本文按仓库文件逐个拆解,再落到训练与部署的可复现命令上。
2. 仓库文件盘点:从 results.csv 到 engine,每个文件在课程里的位置
拿到压缩包先别急着解压跑代码,这个仓库的文件是课程四个篇章的阶段性产物,理清每个文件的用途,才能知道该在哪个阶段取用哪份资源。
2.1 训练产物:results.csv 与 tfevents 日志怎么读
results.csv是模型训练过程中的指标记录表,每一行对应一个 epoch,列通常包含 epoch、train/box_loss、train/obj_loss、train/cls_loss、metrics/precision、metrics/recall、metrics/mAP@0.5、metrics/mAP@0.5:0.95、val/box_loss、val/obj_loss、val/cls_loss、x/lr 等字段。这个文件的价值在于训练结束后可以回放整个训练过程,判断模型在第几个 epoch 开始收敛、有没有过拟合。
# 查看 results.csv 的表头和关键列 head -1 results.csv | tr ',' '\n' | cat -n # 只看 mAP 和 loss 这两列,用 awk 按逗号分隔提取 awk -F',' 'NR==1 || NR%10==0 {print $1, $6, $7, $8}' results.csv第一段先看表头有多少列,第二段每 10 个 epoch 输出一次关键指标。$6、$7、$8是 precision、recall、mAP@0.5 的列位置,具体列号以你 head 看到的实际顺序为准。我一般会用 Excel 或 pandas 打开完整 CSV,重点看 val/box_loss 是否在训练后期出现回升——如果 val loss 拐头向上而 train loss 还在降,就是典型的过拟合信号。
events.out.tfevents.1678455952.DESKTOP-ME6MT04.3752.0是 TensorBoard 的二进制事件文件,文件名的数字部分是 Unix 时间戳,1678455952 转换成日期是 2023 年 3 月。这是训练过程中由 PyTorch 的 SummaryWriter 自动写入的,包含 loss 曲线、学习率变化、每张训练图的预览。
pip install tensorboard tensorboard --logdir . --port 6006在包含 tfevents 文件的目录下执行,浏览器访问http://localhost:6006就能看到标量曲线。如果 TFEvents 文件在子目录里,--logdir要指向它所在的目录。注意 TensorBoard 的版本要和训练时用的 torch 版本匹配,版本差太大会出现 "The event file could not be read" 的报错,这种一般是 protobuf 版本冲突,pip install protobuf==3.20.3能缓解。
2.2 Dockerfile 三件套:CPU、ARM64 与默认版的用途差异
仓库里有三个 Dockerfile,Dockerfile是默认的 GPU 版,基于 NVIDIA CUDA 镜像构建,用于带独立显卡的训练机和推理服务器;Dockerfile-cpu是纯 CPU 版,适合没有 GPU 的机器做推理验证;Dockerfile-arm64面向 ARM 架构设备,树莓派 5 或 Jetson 系列跑 YOLOv5 就用它。
# 构建 CPU 版镜像 docker build -f Dockerfile-cpu -t yolov5-cpu:latest . # 构建 ARM64 版镜像(在树莓派 5 上执行) docker build -f Dockerfile-arm64 -t yolov5-arm:latest .-f指定 Dockerfile 文件,-t给镜像打标签。CPU 版镜像构建时会把 PyTorch 的 CPU 版本装进去,ARM64 版则会拉取 arm64 架构的依赖包。构建过程中常见的坑是基础镜像拉取慢,建议先配好 Docker 镜像加速器再执行。需要说明的是,默认 GPU 版 Dockerfile 构建出的镜像体积通常在 8GB 以上,如果只是做 CPU 推理,没必要用这个,CPU 版镜像能省掉一半以上空间。
2.3 三个 engine 文件:TensorRT 的精度分层产物
yolov5s.engine、yolov5s-fp16.engine、yolov5s-halfsize.engine是 TensorRT 的序列化引擎文件,课程部署篇的产物。默认的yolov5s.engine是 FP32 精度,yolov5s-fp16.engine启用了 FP16 半精度推理,yolov5s-halfsize.engine是输入尺寸减半(比如 640 输入变成 320)的版本,用于追求极致吞吐的场景。
# 用 trtexec 把 ONNX 转成 TensorRT 引擎(FP16 模式) trtexec --onnx=yolov5s.onnx \ --saveEngine=yolov5s-fp16.engine \ --fp16 \ --workspace=4096--onnx指定输入模型,--saveEngine是输出文件名,--fp16开启半精度,--workspace指定构建时 GPU 显存上限,单位是 MB。这三个文件的定位是不同的部署目标:追求精度用默认版,追求速度用 FP16 版,边缘设备用 halfsize 版。在后面的部署章节会详细讲这三个引擎的使用场景和踩坑点。
3. 环境配置到模型推理:conda 与 Docker 两条路径的实操对比
课程入门篇的核心是先把环境跑通,再让模型出检测结果。环境配置最怕的就是版本不一致,YOLOv5 对 PyTorch 版本有隐含要求,torch 版本差一两个小版本可能没事,但大版本不对,直接报AttributeError: module 'torch' has no attribute 'hub'这类找不到属性的错误。这里给出两条互不干扰的路径。
3.1 conda 本地环境配置:版本对齐是关键
conda create -n yolov5 python=3.8 -y conda activate yolov5 # 安装 PyTorch 1.12 系列,CUDA 11.6 版 pip install torch==1.12.1+cu116 torchvision==0.13.1+cu116 -f https://download.pytorch.org/whl/torch_stable.html # 安装 YOLOv5 项目依赖 cd yolov5 pip install -r requirements.txt创建独立环境是为了隔离项目依赖,python 3.8 是 YOLOv5 官方推荐的版本之一。PyTorch 的安装命令里指定了 CUDA 11.6 的 wheel 源,如果你本机 CUDA 版本不同,去 PyTorch 官网选对应的安装命令。requirements.txt 里包含 numpy、opencv-python、matplotlib、seaborn 等依赖,其中 seaborn 的版本不能太新,0.11.2 及以下在画混淆矩阵时更稳妥,新版本有时会报AttributeError: 'Legend' object has no attribute 'get_window_extent'。
装完后建议先跑一个最简单的验证,导入 torch 并检查 CUDA 是否可用:
import torch print(torch.__version__) print(torch.cuda.is_available()) print(torch.cuda.get_device_name(0))cuda.is_available()返回 True 才说明 PyTorch 能调用显卡。这里 False 的常见原因是 PyTorch 版本对应的 CUDA 和驱动不匹配,驱动版本太旧时,最新版的 PyTorch 反而用不了,此时降低 PyTorch 版本比更新驱动更省事。
3.2 模型推理:detect.py 的参数与流程
环境就绪后,用官方预训练权重跑一次推理是成本最低的验证方式。
# 下载 yolov5s.pt 权重并用 detect.py 推理 python detect.py --weights yolov5s.pt --source data/images/bus.jpg --conf-thres 0.5 --iou-thres 0.45 --project runs/detect --name exp1--weights指定权重文件,--source可以是单张图片、视频文件、目录或摄像头编号,这里用的是官方自带的 bus.jpg 测试图。--conf-thres是置信度阈值,低于 0.5 的检测框会被过滤;--iou-thres是 NMS 的 IoU 阈值,控制两个重叠框是否合并。--project和--name决定输出目录,结果图会存到runs/detect/exp1下。跑通后打开结果图,能看到 bus.jpg 里的人和公交车都被画上了检测框,这就说明整个环境链路是通的。
3.3 Docker 路径:GPU 与 ARM 镜像的构建差异
不想污染本地环境的用户,容器化是更省心的选择。GPU 版镜像构建时要用 NVIDIA Container Toolkit,否则容器里看不到显卡。
# 在宿主机安装 NVIDIA Container Toolkit 后重建镜像 docker build -t yolov5-gpu . # 运行容器并挂载数据和代码目录 docker run --gpus all -it --rm -v $(pwd):/workspace yolov5-gpu python detect.py --weights yolov5s.pt --source data/images/bus.jpg--gpus all是让容器使用所有 GPU,-v把当前目录挂载到容器里的 /workspace,这样容器内外共享代码和数据。ARM64 镜像在树莓派 5 上构建时不需要--gpus参数,但树莓派的散热条件会影响推理速度,我实测跑 yolov5s 的推理帧率大概在 3-5 FPS 左右,做原型验证够用,上生产还是要用带 GPU 的设备。
4. 训练自己的数据集:从标注目录搭建到 results.csv 出现
入门篇最后一个环节是数据集构建和模型训练,这也是大多数人第一次真正碰壁的地方。YOLOv5 的数据集格式是决定训练能否启动的第一道关卡。
4.1 数据集目录结构与 YAML 配置
YOLOv5 要求图片和标签分离存放,标签是同名 txt 文件,每行是class_id x_center y_center width height,坐标是相对于图片宽高的归一化值。这个格式和 VOC 的 XML 标注完全不同,如果手头是 VOC 格式的数据,需要先转换。
# data/custom.yaml train: data/custom/images/train val: data/custom/images/val nc: 2 names: ['person', 'helmet']train和val指向图片目录的路径,nc是类别数,names是类别名列表,索引要和标签 txt 里的 class_id 对应上。这个配置文件写错是训练时报错的高频原因,常见的有路径写错导致AssertionError: train: No images found、nc 数量和标签里的 class_id 对不上导致训练完 mAP 全是 0。
4.2 训练命令与超参数的影响
python train.py --data data/custom.yaml --weights yolov5s.pt --epochs 100 --batch-size 16 --img 640 --patience 20 --project runs/train --name custom_exp--data指定上面建的 YAML 文件,--weights用预训练权重做迁移学习,这比从头训练收敛快得多。--epochs是训练轮数,--batch-size是每批图片数,显存不够的时候优先降低 batch-size,而不是降--img分辨率。--img 640是训练时输入图片的尺寸,YOLOv5 默认会在训练时做 mosaic 增强,实际喂进网络的图是多种尺寸的组合。--patience 20是早停参数,连续 20 个 epoch 验证集 mAP 没有提升就停止训练,防止浪费算力。
YOLOv5 的超参数其实藏在data/hyps/hyp.scratch.yaml里,学习率、动量、weight decay、数据增强系数都在其中。
lr0: 0.01 # 初始学习率 lrf: 0.2 # 余弦退火最终学习率系数 momentum: 0.937 weight_decay: 0.0005 warmup_epochs: 3.0默认学习率对大多数数据集是够用的,小数据集可以调低一点,比如 lr0 改成 0.005,防止前期发散。warmup_epochs 是预热轮数,前几个 epoch 学习率从很小逐渐爬升到 lr0,这个机制能避免训练初期 loss 爆炸。
4.3 中断续训与结果确认
训练过程中途可能因为断电或显存溢出中断,不需要从头再来。
python train.py --data data/custom.yaml --weights runs/train/custom_exp/weights/last.pt --epochs 100 --resume runs/train/custom_exp--resume指定训练目录,会自动读取该目录下的 last.pt 权重、epoch 状态、优化器状态和超参数,从断点继续。--weights在续训时其实可以不传,因为 last.pt 里已经包含了模型权重,如果同时指定了--weights和--resume,以--resume为准。续训前确认磁盘空间够,last.pt 和 best.pt 每个约几百 MB。
训练完后,之前提到的 results.csv 就是验证依据。我习惯先看 mAP@0.5 的最终值和 val/box_loss 的曲线形态,如果 mAP 在 0.8 以上而 loss 曲线没有明显回升,基本可以进入下一步部署。
5. TensorRT 部署避坑:engine 文件、精度与显存的踩坑实录
部署篇是整个课程的深水区。TensorRT 能把 YOLOv5 的推理提速几倍,但前提是环境、版本、硬件三者对齐。我在复现课程部署篇时踩过不少坑,用五个典型问题还原现场。
5.1 先用 trtexec 验证引擎可用性
拿到引擎文件先做链路验证,而不是直接写推理代码,能避免把问题混在一起排查。
trtexec --loadEngine=yolov5s-fp16.engine --shapes=images:1x3x640x640 --fp16--loadEngine加载引擎,--shapes指定输入张量的维度,NCHW 格式,数量是 1、通道 3、高 640、宽 640。如果这一步能跑通并输出 latency 统计,说明引擎文件没有损坏,问题大概率在后处理代码;如果报错,先看是 CUDA 错误还是 TensorRT 版本不兼容的错误信息。
5.2 坑 1:FP16 精度掉点不是玄学,是校准没做
现象:用yolov5s-fp16.engine推理,检测框位置基本对,但置信度普遍比 FP32 低 0.1-0.2,个别小目标直接漏检。
原因:FP16 模式把权重和激活值都变成半精度浮点,数值范围缩小,对动态范围敏感。不做事先的校准或补偿,靠近置信度阈值的框就会被过滤掉。
解决:转 FP16 引擎时,用训练数据的一个子集做校准。TensorRT 的--calib参数在 trtexec 里需要配合 INT8 使用,FP16 没有显式校准步骤,但实践中最有效的做法是适当降低检测时的 conf-thres,比如从 0.5 降到 0.35。如果对精度要求苛刻,建议直接用 FP32 的 engine,速度换精度。
5.3 坑 2:engine 文件和 GPU 架构强绑定
现象:在 A100 上生成的 engine 文件,拷贝到 3090 上加载报错,提示Unsupported GPU compute capability。
原因:TensorRT 引擎是深度绑定的产物,和 CUDA 版本、GPU 架构、TensorRT 版本三者都强相关。换显卡等于换架构,序列化引擎里的 kernel 无法复用。
解决:引擎文件在目标机器上现场生成,不跨机器拷贝。在部署机上装好对应版本的 TensorRT 后重新执行转引擎命令,不要贪图省事传递 engine 文件。课程仓库里提供的 engine 文件是示例产物,不是通用部署包。
5.4 坑 3:动态 batch 未开启,吞吐上不去
现象:用--shapes=images:1x3x640x640转出的引擎,每次只能推理一张图,服务端并发上来后吞吐量卡在个位数。
原因:构建引擎时固定了 batch 为 1,TensorRT 不会自动优化 batch=8 或 batch=16 的并行执行。
解决:构建引擎时把维度范围放宽。
trtexec --onnx=yolov5s.onnx \ --saveEngine=yolov5s-dynamic.engine \ --minShapes=images:1x3x640x640 \ --optShapes=images:8x3x640x640 \ --maxShapes=images:16x3x640x640 \ --fp16--minShapes、--optShapes、--maxShapes定义了动态 batch 的范围,TensorRT 会针对 8 这个最优化维度做 kernel 调优,实际推理时 batch 在 1 到 16 之间都可以,性能在 batch=8 附近最优。
5.5 坑 4:Docker 里跑 TensorRT 报显存不足或 CUDA 初始化失败
现象:在容器内加载 engine 文件时,报CUDA_ERROR_OUT_OF_MEMORY,但宿主机用 nvidia-smi 看显存是够的。
原因:容器运行时的内存隔离。TensorRT 构建引擎时要预留 workspace,之前构建时用--workspace=4096设置了 4GB 预留,如果容器启动参数限制了显存访问,预留会失败。
解决:运行容器时加--shm-size=8g并显式声明显存限额。
docker run --gpus all --shm-size=8g -it --rm yolov5-gpu python infer_tensorrt.py5.6 坑 5:halfsize 引擎速度没提升,反而更慢
现象:从yolov5s.engine换成yolov5s-halfsize.engine,预期推理时间减半,实测几乎没变化。
原因:输入从 640 减到 320,计算量降为四分之一,但 CPU 上的预处理和后处理成了瓶颈。halfsize 引擎削减的是 GPU 计算时间,如果 CPU 侧的图像缩放、归一化、NMS 占了总耗时的一半以上,整体收益就体现不出来。
解决:用--img 320对应生成引擎的同时,优化预处理流水线,把图像缩放和归一化放到 GPU 上用 CUDA kernel 做,或者用 TensorRT 的 EfficientNMS 插件把后处理也并入引擎。
6. 进阶验证:修改网络结构后,用三行命令确认改动生效
进阶篇的内容是修改网络结构和替换主干,这里很容易出现「改完代码发现训练出来的模型和没改一样」的情况。原因是网络结构变更后,没有验证改动是否真的进入了计算图。我改完 C2f 结构后的标准验证流程是固定三项。
第一,用torchsummary或 YOLOv5 自带的模型打印确认参数变化。
import torch from models.yolo import Model model = Model(cfg='models/yolov5s.yaml', ch=3, nc=2) print(model) # 统计参数量 params = sum(p.numel() for p in model.parameters()) print(f'Total parameters: {params / 1e6:.2f}M')配置文件和nc类别数要和训练时的保持一致,参数量的变化是最直观的改动证据。如果你修改的是 C2f 模块的通道数,打印结果里对应层的输出通道会变化,参数总量也会变。如果参数一模一样,说明你的改动没有生效,回去检查 YAML 文件是否正确被引用。
第二,用torch.jit.trace导出并检查特征图形状。修改网络结构后常见的一个翻车点是 concat 操作的维度对不上,训练时报The size of tensor a (32) must match the size of tensor b (64)之类的错误。用 trace 导出可以提前暴露这类问题。
model.eval() dummy_input = torch.randn(1, 3, 640, 640) traced = torch.jit.trace(model, dummy_input) traced.save('traced_model.pt')dummy_input的尺寸要和训练时的--img一致,这里用的 640 是 YOLOv5 的默认输入。trace 成功意味着前向传播没有维度问题,如果 trace 本身报错,就去检查修改模块的输出通道数。
第三,加载修改后的权重跑一张推理图对比检测结果。这是最后的端到端验证,确认改动不仅训练能跑,推理结果也是可用的。从那以后,我每次修改网络结构都强制走一遍「打印参数、trace 导出、对比推理」这三步,不在任何一步上含糊。改结构这种事,最怕的就是自我感觉改到位了,一训练才发现根本没进计算图,浪费十几个小时的算力。希望这次的实战拆解能帮你在学习这套课程时少走这些弯路。
本文还有配套的精品资源,点击获取