☰
YOLOv5实战:从数据集训练到TensorRT部署全流程解析
2026/10/1 22:17:31 网站建设 项目流程

简介:面向YOLOv5学习者的完整实战代码仓库,内容按入门、拓展、进阶、部署四篇编排,从环境安装、模型推理、数据集构建、模型训练,到界面开发、网页演示、云端服务器训练、推理加速部署等均有涉及,适合零基础起步、逐步进阶的开发者。压缩包共三百四十个文件,大小约二百七十六兆,主要包含训练与推理脚本、模型配置、图像样本、可视化笔记、标签与说明文件、预训练权重以及推理引擎,另有容器化与自动化脚本便于搭建环境。代码结构清晰,内容按篇章组织,可对照配套视频按需取用;进阶内容还覆盖网络结构修改、注意力机制引入、主干网络替换,以及接口化项目部署与模型调用等扩展方向。目前已有约一百三十八人学习,无论是入门YOLOv5还是做工程化部署,都能从这份资源中获得可直接运行的代码和完整操作链路。

1. 这份YOLOv5实战zip包值得花十分钟拆开:它把训练到部署的路都铺好了

很多做目标检测的同行都下载过YOLOv5源码,但真正能把自己的数据集跑通、再把模型部署到服务里的人不多。这份“手把手带你实战YOLOv5.zip”是B站配套课程的完整代码仓库,里面不只有YOLOv5源码,还包括训练过程生成的results.csv和 TensorBoard 事件文件events.out.tfevents...,以及已经转换好的yolov5s.engine系列 TensorRT 引擎文件。也就是说,你解压之后既能回看训练日志,也能直接用 TensorRT 推理。适合刚接触目标检测、想从环境安装一路走到 Flask 部署的从业者;也适合已经跑通训练、但对engine推理和 Web 封装还不熟的人。整个课程分入门、拓展、进阶、部署四个篇章,代码仓库把这些篇章对应的文件都收在一起,省去到处找源码的时间。


2. 环境安装与数据集构建:先把YOLOv5跑起来再谈别的

2.1 从zip解压到conda环境:版本匹配是第一道坎

拿到这个zip包,第一步不是急着跑训练,而是先把压缩包解压干净。这里有个容易被忽视的点:zip包内部目录如果带权限或软链,在 Windows 上解压可能会丢可执行权限,在 Linux 上则要注意解压后文件属主。我一般习惯用命令解压而不是双击,这样能避免文件名编码问题。

unzip 手把手带你实战YOLOv5.zip -d yolov5_project cd yolov5_project conda create -n yolov5 python=3.8 -y conda activate yolov5 pip install -r requirements.txt

逻辑说明:unzip的-d参数指定解压目标目录,避免把一堆文件散落在当前目录;conda create创建独立环境,防止和系统 Python 互相污染。requirements.txt是 YOLOv5 官方仓库自带的依赖清单,里面包含了 torch、opencv-python、pyyaml 等运行所需库。

参数说明:Python 版本建议 3.8 或 3.9,太新的 3.11/3.12 可能遇到部分算子兼容问题。如果你本机 CUDA 版本是 11.x,torch 安装建议用pip install torch==1.13.1这类匹配版本;具体以你nvidia-smi显示的 CUDA 版本为准,不要盲装最新版。这个zip包里的Dockerfile也给出了另一条路:如果你不想污染本机环境,直接用 Docker 镜像跑更干净。

2.2 用自己的数据集训练:目录结构决定训练脚本能不能找到图

把YOLOv5跑起来之后的第一个正经任务,是训练自己的数据集。很多人栽在数据集目录结构上。YOLOv5 默认要求 images 和 labels 分开,并且 train/val 子目录放图片,标签文件按同名 txt 放在 labels 下。课程里的“YOLOv5 数据集构建”环节就是干这个。

# 以你的自定义数据集为例 mkdir -p datasets/mydata/images/train mkdir -p datasets/mydata/images/val mkdir -p datasets/mydata/labels/train mkdir -p datasets/mydata/labels/val # 标签格式:class_id x_center y_center width height(归一化坐标)

逻辑说明:YOLOv5 的Dataset类会按datasets/mydata路径去找images和labels,如果你把自己的图片放在别的别名目录下,train.py的 data 参数指向的 YAML 文件里写的path必须精确匹配。这里的labels目录下每个 txt 文件和图片同名,里面一行代表一个目标。

参数说明:坐标是归一化到 0~1 的浮点数,不是像素坐标。如果你用 LabelImg 或 labelme 导出的是像素框,需要写个转换脚本。常见做法是:

def convert(x1, y1, x2, y2, img_w, img_h): c_x = ((x1 + x2) / 2) / img_w c_y = ((y1 + y2) / 2) / img_h w = (x2 - x1) / img_w h = (y2 - y1) / img_h return c_x, c_y, w, h

这段脚本把 VOC 格式的左上右下坐标转成 YOLO 需要的中心点加宽高,转换后要检查w和h是否大于 0,部分标注软件导出时可能出现反向坐标,那会导致训练 loss 直接 NaN。

2.3 检查训练数据:标签和图像数量必须对得上

每张图片对应一个 txt 文件,但允许 txt 为空(即没有目标)。常见翻车点是图片有而标签文件缺失,或者标签文件有而图片缺失。训练脚本会在加载时报错,但有时报错信息不直观。

# 快速检查:统计图片和标签文件数量 find datasets/mydata/images/train -name "*.jpg" | wc -l find datasets/mydata/labels/train -name "*.txt" | wc -l

逻辑说明:两个数字应该一致,但如果存在没有目标的图片,标签文件仍然会生成空 txt,所以数量一致是必要条件,不代表全部正确。更严苛的做法是用yolov5/utils/里的脚本逐个解析标注是否在边界内。

参数说明:find的-name "*.jpg"只匹配 jpg,如果你的图片是 png 或 bmp,改成对应后缀。B站课程里老师用的是标准 coco 数据集结构,你替换成自己的数据集后,必须同步修改.yaml里的nc类别数。


3. 模型训练与超参数调整:读懂results.csv和TensorBoard日志

3.1 训练指令里的关键参数:不要全盘照抄默认值

YOLOv5 的训练入口是train.py,课程“YOLOv5 模型训练”一节会讲到最精简的命令。实际训练时我一般会在默认参数基础上做三处调整:batch-size要匹配显存、epochs要够但别过拟合、workers要按 CPU 核心数设。

python train.py --data mydata.yaml --weights yolov5s.pt \ --batch-size 16 --epochs 100 --workers 8 --device 0

逻辑说明:--weights yolov5s.pt是用 COCO 预训练权重做迁移学习,这比从零训练收敛快得多。--device 0指定用第一张 GPU;如果你只有 CPU,把--device cpu但训练速度会慢到让人怀疑人生。--data mydata.yaml指向你自己写的数据集配置文件。

参数说明:batch-size 16在 8GB 显存上对 yolov5s 是安全的,但如果你用 4K 分辨率图片,16 可能爆显存,改成 8 或 4。epochs 100是经验值,我的习惯是先跑 50 轮看看 loss 曲线,如果验证集 mAP 还在上升,就继续跑;如果已经平台期,早停。workers是数据加载线程数,Windows 上建议设 4 以下,Linux 可以设 8 或更高,但不要超过 CPU 物理核心数。

3.2 从results.csv里读训练健康度:别只看loss

训练结束后,根目录会生成results.csv,这个zip包里自带了一份历史训练结果。下面这个表格是results.csv里最常见的列:

列名含义健康值参考
epoch当前轮数单调递增
train/box_loss训练集框损失前 30 轮下降快,后期平缓
val/box_loss验证集框损失和训练损失同步下降,不应反弹
metrics/precision精确率越高越稳
metrics/recall召回率和 precision 平衡
metrics/mAP_0.5IoU=0.5 的 mAP最终目标
metrics/mAP_0.5:0.95严格 mAP一般比上面低 20~30 个点

常规操作是每跑 10 轮瞄一眼val/box_loss,如果它先降后升,而train/box_loss还在降,说明过拟合了。这时候你该做的是调--patience早停,而不是继续跑。

python train.py --data mydata.yaml --weights yolov5s.pt \ --batch-size 16 --epochs 100 --patience 10

参数说明:--patience 10表示验证集指标连续 10 轮不提升就自动停止训练。这个参数在课程进阶篇里有演示,可以省掉你守夜的精力。但要注意,如果数据集小且噪声大,mAP 可能有波动,patience 设太小会导致过早停止,我一般设 15~20。

3.3 用TensorBoard回放训练历史:events.out.tfevents文件的正确理解

zip 包里的events.out.tfevents...是 TensorBoard 的事件文件。你不需要重新训练就能看到当时那次训练的过程曲线,前提是环境里装了 tensorboard。

tensorboard --logdir=.

然后浏览器打开http://localhost:6006,左侧选到对应 run,就能看到 loss、mAP、learning rate 曲线。注意:如果你的tfevents文件名里带着DESKTOP-XX这样前缀,说明原训练是在 Windows 机器上跑的,不影响读取。

参数说明:--logdir=.指当前目录,它不会自动递归所有子目录,如果你把 events 文件放在runs/exp目录,要写成--logdir=runs。如果在远程服务器上,还要加--host 0.0.0.0才能用本地浏览器访问。


4. TensorRT部署加速:yolov5s.engine系列文件的正确打开方式

4.1 为什么要转成engine:从PyTorch到TensorRT的变换

课程部署篇的核心是 TensorRT。PyTorch 模型在 GPU 上推理虽然是动态图灵活,但实际生产环境里我们只关心吞吐和延迟。TensorRT 会把训练好的模型做层融合、精度校准、内核自动调优,生成一个engine文件。这个 zip 包里给你的是yolov5s.engine、yolov5s-halfsize.engine、yolov5s-fp16.engine三个版本,对应不同精度和输入尺寸。

文件精度输入尺寸特点适用场景
yolov5s.engineFP32原始 640x640精度要求高,容忍延迟
yolov5s-fp16.engineFP16原始 640x640精度小降,速度提升明显
yolov5s-halfsize.engineFP32/FP16可能是 320x320 或自定义小尺寸带宽有限,追求极致速度

注意:engine文件不是跨平台通用的。你在这台机器的 GPU 和驱动环境下生成的 engine,换到另一张卡上可能加载失败或报错。所以拿到这个 zip 里的 engine 文件,第一时间用加载脚本试跑,如果报错,再重新转换。

4.2 用engine做推理:TensorRT的API没那么可怕

加载 engine 做推理的标准姿势是先反序列化,然后绑定输入输出 buffer。

import tensorrt as trt import pycuda.driver as cuda import pycuda.autoinit import numpy as np logger = trt.Logger(trt.Logger.WARNING) with open("yolov5s.engine", "rb") as f, trt.Runtime(logger) as runtime: engine = runtime.deserialize_cuda_engine(f.read()) context = engine.create_execution_context() # 输入输出 buffer h_input = np.empty((1, 3, 640, 640), dtype=np.float32) h_output = np.empty((1, 25200, 5 + num_classes), dtype=np.float32) d_input = cuda.mem_alloc(h_input.nbytes) d_output = cuda.mem_alloc(h_output.nbytes)

逻辑说明:deserialize_cuda_engine把引擎文件读取为可执行的推理计划,create_execution_context创建推理上下文。输入张量用numpy初始化,然后用cuda.mem_alloc在显卡上分配显存。推理时要先执行cuda.memcpy_htod把图片拷入显存,再调用context.execute_v2,最后把输出拷回内存。

参数说明:预处理的归一化方式要和训练时一致。YOLOv5 训练时是除以 255 归一化到 0~1,很多人在这一步偷懒直接喂 0~255 的原始像素,导致 mAP 低得离谱。num_classes是你的类别数,如果你在 zip 自带的分类上测试,就是 COCO 的 80 类,但一旦用自己数据集重新训练,这个数必须改。

4.3 后处理:engine输出的是裸张量,不是检测框

从 engine 拿到的25200是 640x640 下三个尺度特征图拼接后的候选框数量。每个候选框有5 + num_classes个值,前 4 个是坐标,第 5 个是置信度,后面是类别概率。

def postprocess(output, conf_thres=0.25, iou_thres=0.45): # output shape: (1, 25200, 85) boxes = output[0] # 去掉 batch 维 # 按置信度筛选 mask = boxes[..., 4] > conf_thres boxes = boxes[mask] if len(boxes) == 0: return [] # 类别置信度 = 目标置信度 * 类别概率 class_conf = boxes[..., 4:5] * boxes[..., 5:] class_id = class_conf.argmax(axis=-1) conf = class_conf.max(axis=-1) # NMS keep = nms(boxes[:, :4], conf, iou_thres) return boxes[keep], class_id[keep], conf[keep]

逻辑说明:25200这个数字来自 YOLOv5 的 anchors 设计——3 个尺度乘以 3 个 anchor,再乘以特征图网格数。后处理的核心是阈值筛选和非极大值抑制。课程里专门有“YOLOv5 后处理”一集,建议动手实现一遍,不要直接用utils.general.non_max_suppression,因为你要理解 engine 输出和 PyTorch 模型输出的区别。

参数说明:conf_thres和iou_thres是后处理的两个关键阈值。工程上我一般把conf_thres设 0.3,iou_thres设 0.45,前者卡目标置信度,后者控制重叠框的消除力度。阈值设太低会出大量误检,设太高又漏检。


5. 实战避坑:五个YOLOv5配置与部署的常见问题

5.1 现象:conda环境装好,但 torch.cuda.is_available() 返回 False

原因:你的 CUDA 驱动版本和 PyTorch 内部编译时的 CUDA 版本不匹配。最常见是nvidia-smi显示 CUDA 12.x,但装的是torch==1.13配套的 CUDA 11.7。另一个原因是在 base 环境里装了 CPU 版 torch,然后又用conda create建了新环境,但pip指向了旧环境的 site-packages。

解决:先彻底退出环境,再重新创建环境,用 PyTorch 官网的安装命令重新装。

conda activate yolov5 python -c "import torch; print(torch.__version__, torch.cuda.is_available())" # 如果 False,卸载重装 pip uninstall torch torchvision -y pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118

注意:不要用conda install pytorch,那个源可能会给你装 CPU 版。装完再跑检查脚本,看到True再继续。

5.2 现象:训练前 20 轮 loss 就降到接近 0,验证集 mAP 却一直在低位

原因:数据集标注有错误,比如类别 id 从 1 开始而不是 0,导致标签和模型输出对不上;或者图片里有大量空标签,模型学会了把所有目标都忽略。典型特征是train/box_loss正常,但metrics/recall极低。

解决:先检查 label 文件。写一段脚本遍历每张图片的 txt,看 class_id 是否在[0, nc-1]范围内,再看坐标是否超出图片宽高。

python -c " from pathlib import Path for f in Path('datasets/mydata/labels/train').glob('*.txt'): for line in f.read_text().strip().splitlines(): cls = int(line.split()[0]) if cls < 0 or cls >= 5: # 假设 5 类 print(f.name, 'bad class', cls) "

5.3 现象:加载 yolov5s.engine 报错 "TensorRT version mismatch"

原因:zip 里的 engine 是用某个特定 TensorRT 版本转换的,你的环境里 TensorRT 版本不兼容。engine是二进制产物,包含算子内核选择,跨版本几乎不可能通用。

解决:换成自己的环境重新转换。转换脚本常见是:

python export.py --weights yolov5s.pt --include engine --device 0 --half

参数说明:--half表示导出 FP16 engine。如果你想导出 FP32,去掉--half。但注意export.py是 YOLOv5 自带的脚本,zip 包里没有的话要去官方仓库单独下载。转换时 TensorRT 版本要和推理环境完全一致,否则刚才的报错会复现。

5.4 现象:Gradio页面能打开,但上传图片后推理报错 "shape mismatch"

原因:Gradio 输入的图片被PIL打开后是 HxWxC 的 uint8 数组,而你检测函数期望的是 1x3x640x640 的 float32 张量。很多人直接把 image 传给模型,忘记做 letterbox 和 BGR/RGB 转换。

解决:在送入模型前做标准化预处理。

import cv2 img = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) # Gradio 给的是 RGB img = letterbox(img, new_shape=(640, 640), stride=32)[0] img = img[:, :, ::-1].transpose(2, 0, 1) # BGR -> RGB img = np.ascontiguousarray(img, dtype=np.float32) / 255.0 img = np.expand_dims(img, axis=0)

5.5 现象:Dockerfile 构建时下载依赖卡在 pip install 阶段

原因:基础镜像源是国外源,国内网络访问慢或者被墙。zip 包里带了Dockerfile-cpu和Dockerfile-arm64,如果是 arm 设备,还要注意基础镜像本身是否支持该架构。

解决:在 Dockerfile 里换 pip 源和 apt 源。常见做法是在pip install前加一行:

RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt

另外,如果你在 arm64 设备上跑,建议看Dockerfile-arm64的内容,不要用通用的Dockerfile,因为很多预编译轮子没有 arm 版本。


6. 把训练好的模型变成Web服务:Gradio快速验证,Flask正式部署

6.1 用Gradio搭一个可交互的检测Demo

课程“YOLOv5 Gradio搭建Web GUI”给出了快速验证的方法。Gradio 能在几分钟内把检测函数包装成网页,适合给团队看效果。

import gradio as gr from detect import run_detection # 你自己的推理函数 def detect_and_show(image): result_img = run_detection(image) return result_img gr.Interface(fn=detect_and_show, inputs="image", outputs="image", title="YOLOv5 Demo").launch()

参数说明:inputs="image"会返回一个numpy.ndarray,注意颜色通道顺序是 RGB。如果你的检测函数内部用的是 OpenCV 的 BGR,需要在函数入口做一次转换。launch()默认为server_name="127.0.0.1",如果要局域网访问,改成launch(server_name="0.0.0.0", server_port=7860)。

6.2 进阶:Flask部署时的后处理与返回结构

如果要把模型嵌进现有系统,Flask 是更常被要求改造的方向。课程“基于Flask的YOLOv5项目部署”里会把模型加载放入 Flask 应用初始化阶段,避免每个请求都重复加载模型。

from flask import Flask, request, jsonify import cv2, numpy as np app = Flask(__name__) # 全局加载模型,只加载一次 model = load_tensorrt_engine("yolov5s.engine") @app.route("/detect", methods=["POST"]) def detect(): file = request.files["image"] img = cv2.imdecode(np.frombuffer(file.read(), np.uint8), cv2.IMREAD_COLOR) results = model.detect(img) return jsonify({"boxes": results["boxes"].tolist(), "labels": results["labels"].tolist(), "confs": results["confs"].tolist()})

逻辑说明:模型加载放在 Flask 模块顶部,进程启动后会常驻显存,不需要每次请求重新读 engine 文件。imdecode从字节流解码图片,避免用cv2.imread因为路径问题出 Bug。检测函数内部必须包含 letterbox、推理、后处理,这一整套在课程部署篇有专门章节。

参数说明:request.files["image"]是前端以multipart/form-data上传的文件对象。返回的 JSON 里boxes是二维列表,每行[x1, y1, x2, y2]是原始图片坐标系下的像素坐标,不是归一化坐标。前端拿过去画框时要确认坐标系一致。

这里有一个我每次必踩的坑:用 TensorRT engine 推理时,输入的 letterbox 填充颜色必须是灰色(114, 114, 114),而你训练时预处理脚本可能填的是黑色。这个灰度值影响背景填充区域的响应,虽然不至于全错,但会让边缘目标检测精度下降一两个点。

从那以后,我每次在本地跑通推理,都会顺手做一次「同一张图、PyTorch 模型 vs TensorRT engine」的输出对比,确保坐标和置信度误差在 1e-3 以内,再交出去部署。也希望这份 zip 里的笔记和 engine 文件能帮你少走这些弯路,希望帮到你。

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

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

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

立即咨询