
简介本资源面向计算机视觉方向的开发者与研究人员提供YOLO11目标检测从训练到TensorRT加速部署的完整实战项目帮助读者打通模型训练、格式转换与推理优化的全链路适合具备一定深度学习基础、希望掌握工程化落地技巧的中高级学习者。压缩包共67个文件约2.82MB以Python脚本、Shell执行脚本、模型配置yaml、示例图片及说明文档为主涵盖训练、导出ONNX、构建TensorRT引擎与推理等环节并附一键执行脚本降低上手门槛。项目基于coco_minitrain_10k小型数据集训练兼顾效果验证与资源开销同时提供README与完整流程教程便于按步骤复现并理解各模块作用。目前已有1286人学习下载读者可借此掌握YOLO11原理、ONNX跨框架迁移及TensorRT推理加速的实践方法并参考排错思路快速应用于自动驾驶、视频监控等实时视觉场景。1. 从 PyTorch 权重到 TensorRT 引擎这套 YOLO11 实战包到底解决了什么大多数做目标检测的工程师都经历过这个割裂训练脚本跑得挺顺mAP 看着也还行但一到部署环节就卡住——PyTorch 的.pt文件在服务器上推理一张图要几十毫秒放到边缘设备上更是慢得没法看。YOLO11 作为目标检测系列里较新的版本在精度和速度的平衡上做了不少优化但真正要让它在生产环境跑起来绕不开 TensorRT 这层加速。问题在于从训练到 ONNX 导出再到 TensorRT 引擎构建中间涉及环境配置、版本匹配、精度对齐、动态 shape 处理一堆事每一步都有翻车的可能。这套0002_yolo11_train_pytrt_infer.zip的价值就在于把这条链路完整串起来了。它包含训练脚本train_yolo11.py、预测脚本predict_yolo11.sh、ONNX 导出脚本export_onnx.py、TensorRT 推理脚本infer_trt.py以及从环境下载到引擎构建的全套 shell 脚本。数据集用的是 coco128 小样本适合快速验证流程。如果你正在找一套能直接跑通 YOLO11 训练加 TensorRT 部署的参考实现不想在环境配置上耗三天这个包值得拆开看看。2. 环境搭建与训练流程从 0_download_env.sh 到权重落盘2.1 环境依赖与一键脚本的边界项目根目录下的0_download_env.sh是整条流水线的起点。它的职责是拉取 Python 依赖和预训练权重但要注意——这个脚本不会帮你装 CUDA 和 cuDNN这两样得自己提前搞定。requirements.txt里列的是 Python 层面的包常见做法是先用 conda 建一个干净环境再跑这个脚本。# 创建独立环境避免和系统 Python 冲突 conda create -n yolo11_trt python3.10 -y conda activate yolo11_trt # 执行环境下载脚本安装依赖和权重 bash 0_download_env.sh这里有个参数需要留意requirements.txt里对torch的版本约束。如果你机器上的 CUDA 是 11.8那torch得选对应编译版本否则后面导出 ONNX 时可能报算子不支持。我一般会先确认nvcc -V的输出再决定装哪个版本的 PyTorch。0_download_env.sh默认走的是比较通用的配置但你的驱动版本如果偏老可能需要手动调整。权重下载部分脚本会从wgts目录拉取 YOLO11 的预训练.pt文件。这个文件后面既用于训练初始化也用于直接导出 ONNX 做推理验证。如果你有自己的数据集可以跳过预训练权重但建议至少跑一遍 coco128 确认流程通畅。2.2 训练脚本 train_yolo11.py 的关键参数train_yolo11.py是训练入口底层调的是 Ultralytics 的 API。数据集配置在datasets/coco128.yaml里指向 coco128 的图片和标注路径。这个数据集只有 128 张图训练几个 epoch 就能看到 loss 下降适合验证代码能不能跑通。# train_yolo11.py 核心训练逻辑简化示意 from ultralytics import YOLO # 加载预训练权重指定模型规模 model YOLO(wgts/yolo11n.pt) # 开始训练 results model.train( datadatasets/coco128.yaml, # 数据集配置文件路径 epochs100, # 训练轮数coco128 上 50-100 足够看趋势 imgsz640, # 输入分辨率和后续 TensorRT 引擎保持一致 batch16, # 批大小根据显存调整 device0, # GPU 编号多卡用 0,1 projectruns/train, # 输出目录 nameyolo11n_coco128, # 实验名称 exist_okTrue # 允许覆盖同名实验 )几个参数值得展开说。imgsz设成 640 是 YOLO 系列的常规操作但如果你后面 TensorRT 推理时想用 1280那训练时最好也用 1280 或者至少做多尺度增强否则精度会掉。batch根据显存来8G 显存跑yolo11n用 16 差不多再大就 OOM。epochs在 coco128 这种小数据集上不用设太大100 轮足够观察收敛情况真正要出精度得换完整 COCO 或自己的数据集。训练完成后权重会落在runs/train/yolo11n_coco128/weights/best.pt。这个文件是后续导出 ONNX 的输入。2_run_train_yolo11.sh是对训练脚本的封装里面预设了一些命令行参数直接跑也行但建议先看懂train_yolo11.py里的默认值再决定要不要改。2.3 训练过程中的显存与日志排查训练时最容易遇到的是显存不够。现象是程序直接抛CUDA out of memory原因通常是batch设大了或者imgsz太高。解决办法有两个一是把batch降到 8 甚至 4二是开启梯度累积模拟大 batch。Ultralytics 的 API 里没有直接的梯度累积参数但可以通过调小batch加多步更新来近似。另一个常见问题是 dataloader 卡住。如果看到日志停在Scanning阶段不动多半是coco128.yaml里的路径写错了。这个文件里path字段指向数据集根目录train和val指向图片子目录。路径用相对路径时基准是train_yolo11.py所在目录不是datasets目录。我一般会改成绝对路径避免歧义。日志方面Ultralytics 默认会在runs/train下生成results.csv里面记录了每轮的 loss 和 mAP。用 pandas 读一下就能画曲线import pandas as pd df pd.read_csv(runs/train/yolo11n_coco128/results.csv) print(df[[epoch, train/box_loss, metrics/mAP50]].tail())如果 mAP50 一直不涨先检查标注格式对不对。YOLO 系列要求标注是归一化的class x_center y_center width height不是 VOC 的xmin ymin xmax ymax。格式错了 loss 会异常但程序不一定报错属于典型的玄学问题。3. ONNX 导出与 TensorRT 引擎构建3_export_onnx.sh 和 4_build_trt_engine.sh 拆解3.1 export_onnx.py 的导出逻辑与动态维度处理训练完拿到best.pt之后下一步是转 ONNX。export_onnx.py封装了 Ultralytics 的export方法核心就几行# export_onnx.py 核心逻辑 from ultralytics import YOLO # 加载训练好的权重 model YOLO(runs/train/yolo11n_coco128/weights/best.pt) # 导出为 ONNX 格式 model.export( formatonnx, # 目标格式 imgsz640, # 输入尺寸必须和训练时一致 opset12, # ONNX 算子集版本TensorRT 8.x 建议用 12 simplifyTrue, # 启用图简化去掉冗余算子 dynamicFalse # 是否启用动态 batch/尺寸 )opset这个参数很关键。TensorRT 不同版本对 ONNX opset 的支持不一样8.x 系列对 opset 12 支持最稳opset 17 在某些旧版本上会报Unsupported operator。如果你用的 TensorRT 是 10.xopset 可以放宽到 17但 12 依然是最保险的选择。dynamic设成False意味着导出的 ONNX 是固定 batch 和固定尺寸。这样做的好处是 TensorRT 构建引擎时能做更激进的优化推理速度更快。代价是 batch 不能变如果你需要动态 batch得设成True但 TensorRT 构建时要额外指定 optimization profile。导出完成后会在同目录生成best.onnx。用onnxsim可以进一步压缩模型但simplifyTrue已经做了大部分工作。验证 ONNX 是否正常可以用onnxruntime跑一张图import onnxruntime as ort import numpy as np sess ort.InferenceSession(best.onnx) input_name sess.get_inputs()[0].name dummy np.random.randn(1, 3, 640, 640).astype(np.float32) outputs sess.run(None, {input_name: dummy}) print([o.shape for o in outputs])如果输出 shape 是[1, 84, 8400]这种说明导出成功。84 是4 个坐标 80 个类别8400 是候选框数量。3.2 build_trt_engine.sh 的参数配置与精度选择4_build_trt_engine.sh调用trtexec把 ONNX 转成 TensorRT 引擎。trtexec是 TensorRT 自带的命令行工具路径通常在/usr/src/tensorrt/bin/下。脚本里的核心命令大概长这样# 4_build_trt_engine.sh 核心命令 trtexec \ --onnxbest.onnx \ --saveEnginebest.engine \ --fp16 \ --workspace4096 \ --minShapesimages:1x3x640x640 \ --optShapesimages:1x3x640x640 \ --maxShapesimages:1x3x640x640 \ --verbose--fp16是开启半精度推理速度能提升 30% 到 50%精度损失通常在 1% 以内。如果你的 GPU 支持 INT8 并且做了校准可以换成--int8但校准过程比较麻烦新手建议先用 FP16。--workspace4096是给 TensorRT 分配的显存工作空间单位是 MB。设太小会导致某些层无法用最优算法设太大浪费显存。4096 对 YOLO11n 这种规模够用了如果是 YOLO11x 得加到 8192 甚至更多。--minShapes、--optShapes、--maxShapes这三个参数在固定尺寸时设成一样就行。如果 ONNX 导出时用了dynamicTrue这里就得指定范围比如minShapesimages:1x3x640x640、maxShapesimages:8x3x640x640让 TensorRT 为不同 batch 准备不同的 kernel。构建完成后会生成best.engine文件。这个文件是序列化后的 TensorRT 引擎加载时不需要重新解析 ONNX启动速度很快。但要注意引擎文件和 GPU 架构绑定在 A100 上构建的引擎不能直接拿到 4090 上用得重新构建。3.3 ONNX 到 TensorRT 的版本匹配与常见报错版本匹配是这条链路里最容易翻车的地方。TensorRT 8.6 配 CUDA 12.x 没问题但配 CUDA 11.8 就需要装对应编译版本。如果trtexec报libcudart.so找不到多半是LD_LIBRARY_PATH没设对。另一个高频错误是Unsupported ONNX operator: Resize。YOLO11 的上采样层用了Resize算子某些旧版 TensorRT 对它支持不好。解决办法有两个一是升级 TensorRT 到 8.5 以上二是导出 ONNX 时把opset降到 11 并启用simplify让onnxsim把Resize替换成Upsample。还有一种情况是构建成功但推理结果全错。这通常是预处理没对齐——PyTorch 训练时用的是 RGB 通道、归一化到 0-1、再减均值除方差TensorRT 推理时如果忘了做同样的预处理输出就是乱的。infer_trt.py里应该包含了预处理逻辑但如果你自己写推理代码这一步不能省。4. TensorRT 推理与效果验证infer_trt.py 怎么跑、结果怎么看4.1 infer_trt.py 的推理流程与后处理infer_trt.py是 TensorRT 推理的入口它加载best.engine对输入图片做预处理跑推理然后做 NMS 后处理最后画框保存。核心流程分四步# infer_trt.py 推理流程简化示意 import tensorrt as trt import pycuda.driver as cuda import numpy as np import cv2 # 1. 加载 TensorRT 引擎 logger trt.Logger(trt.Logger.WARNING) with open(best.engine, rb) as f, trt.Runtime(logger) as runtime: engine runtime.deserialize_cuda_engine(f.read()) # 2. 分配输入输出显存 context engine.create_execution_context() input_shape (1, 3, 640, 640) output_shape (1, 84, 8400) d_input cuda.mem_alloc(np.prod(input_shape) * 4) d_output cuda.mem_alloc(np.prod(output_shape) * 4) # 3. 预处理resize 归一化 NCHW img cv2.imread(imgs/bus.jpg) img_resized cv2.resize(img, (640, 640)) img_norm img_resized[:, :, ::-1].transpose(2, 0, 1).astype(np.float32) / 255.0 img_input np.ascontiguousarray(img_norm[np.newaxis, ...]) # 4. 推理 后处理 cuda.memcpy_htod(d_input, img_input) context.execute_v2([int(d_input), int(d_output)]) output np.empty(output_shape, dtypenp.float32) cuda.memcpy_dtoh(output, d_output) # NMS 后处理省略具体实现项目里已封装预处理里的[:, :, ::-1]是 BGR 转 RGB因为 OpenCV 读图默认是 BGR而 YOLO 训练时用的是 RGB。这个细节如果搞反了检测框会偏移甚至完全失效。归一化除以 255 之后没有再减均值这是因为 YOLO11 的训练配置里没有用 ImageNet 均值直接 0-1 归一化就行。后处理部分主要是 NMS。TensorRT 输出的[1, 84, 8400]里前 4 个通道是cx, cy, w, h后面 80 个是类别置信度。需要先按置信度阈值过滤再按类别做 NMS最后把框映射回原图尺寸。infer_trt.py里应该封装了这些逻辑但如果你要改阈值得找到对应的变量。4.2 效果对比PyTorch 推理 vs TensorRT 推理项目里提供了trt_res.jpg和val_batch2_pred.jpg两张效果图前者是 TensorRT 推理结果后者是 PyTorch 验证集预测结果。从检测框的位置和类别来看两者应该基本一致差异主要在置信度分数上——FP16 推理的分数会比 FP32 略低一点但排序不变。速度方面在相同 GPU 上TensorRT FP16 推理通常比 PyTorch FP32 快 2 到 4 倍。具体倍数取决于 GPU 型号和 batch 大小。用trtexec可以测出纯推理耗时# 测试引擎推理速度 trtexec --loadEnginebest.engine --batch1 --iterations100 --avgRuns10输出里的GPU Compute Time就是平均推理耗时。如果这个值比你预期的高先检查是不是用了 FP32 而不是 FP16再看workspace是不是设小了。4.3 一键脚本 5_infer_trt.sh 的使用与参数覆盖5_infer_trt.sh是对infer_trt.py的封装里面预设了输入图片路径、引擎路径、置信度阈值等参数。直接跑bash 5_infer_trt.sh默认会对imgs/bus.jpg做推理结果保存在同目录。如果你想换图片改脚本里的--image参数就行。置信度阈值默认是 0.25调高会减少误检但可能漏检调低则相反。这个值没有绝对标准得根据你的场景在验证集上试。1_run_predict_yolo11.sh是 PyTorch 版本的预测脚本用来和 TensorRT 版本做对比。两个脚本的输出应该高度一致如果差异很大说明 ONNX 导出或 TensorRT 构建环节出了问题。5. 避坑与排查从环境到推理的五个血泪教训5.1 坑一CUDA 版本和 PyTorch 不匹配导致导出失败现象export_onnx.py跑到一半报RuntimeError: CUDA error: no kernel image is available for execution on the device。原因PyTorch 编译时用的 CUDA 架构和当前 GPU 的计算能力不匹配。比如装的是cu118版本的 PyTorch但 GPU 是 40 系需要cu121才能支持。解决先查 GPU 计算能力nvidia-smi看型号再对照 NVIDIA 文档然后去 PyTorch 官网找对应 CUDA 版本的安装命令。别用pip install torch默认装那个版本不一定对。5.2 坑二ONNX 导出时 opset 设太高导致 TensorRT 不认现象trtexec报Unsupported ONNX operator: GridSample或类似错误。原因opset 17 引入了一些新算子旧版 TensorRT 没实现。YOLO11 的某些版本在导出时会用到这些算子。解决把export_onnx.py里的opset改成 12并确保simplifyTrue。如果还不行降到 11 试试。代价是某些优化用不了但至少能跑通。5.3 坑三TensorRT 引擎构建成功但推理结果全错现象infer_trt.py跑完输出的框位置完全不对或者所有框都堆在左上角。原因预处理没对齐。常见的是 BGR/RGB 搞反、归一化方式不一致、或者 resize 时用了不同的插值算法。解决把 PyTorch 推理的预处理代码和 TensorRT 推理的预处理代码逐行对比。重点检查三个地方通道顺序、归一化除数、resize 的interpolation参数。YOLO 训练时用的是cv2.INTER_LINEAR推理时也得用这个。5.4 坑四显存不足导致 trtexec 构建中断现象trtexec跑到某个层报Cuda Error in allocate: 2 (out of memory)。原因--workspace设太大或者 GPU 上还有其他进程占着显存。解决先把--workspace降到 2048 试试同时用nvidia-smi确认没有其他进程。如果还不行换一张显存更大的卡或者把imgsz从 640 降到 416。5.5 坑五引擎文件跨设备直接拷贝导致加载失败现象在 A 机器上构建的best.engine拷到 B 机器上infer_trt.py报Error Code 1: Serialization。原因TensorRT 引擎和 GPU 架构绑定A100 上构建的引擎在 4090 上加载不了。解决每台设备上重新跑一遍4_build_trt_engine.sh。如果部署环境没有 ONNX 导出环境可以把 ONNX 文件拷过去在目标机器上只跑构建和推理两步。6. 进阶技巧用 trtexec 做精度校准与多精度引擎对比跑通基础流程之后下一步是压榨性能。TensorRT 提供了几种精度模式FP32、FP16、INT8。FP32 最准但最慢FP16 速度和精度平衡得最好INT8 最快但需要校准。我一般会先用trtexec把三种模式都构建一遍对比推理耗时和精度损失再决定用哪个。构建 INT8 引擎需要校准数据集。trtexec支持--calib参数指定校准缓存文件但生成校准缓存得用 TensorRT 的 Python API 写脚本。常见做法是从验证集里抽 500 张图跑一遍校准流程把校准表存下来。这个过程比较耗时但一次生成可以反复用。# 构建 FP16 引擎并测试 trtexec --onnxbest.onnx --saveEnginebest_fp16.engine --fp16 --workspace4096 # 构建 INT8 引擎需要校准缓存 trtexec --onnxbest.onnx --saveEnginebest_int8.engine --int8 --calibcalib.cache --workspace4096 # 对比两种引擎的推理耗时 trtexec --loadEnginebest_fp16.engine --batch1 --iterations200 --avgRuns20 trtexec --loadEnginebest_int8.engine --batch1 --iterations200 --avgRuns20精度验证方面可以用infer_trt.py跑一遍验证集把检测结果和 PyTorch 版本做对比。重点看 mAP50 的差异FP16 通常掉 0.5 个点以内INT8 可能掉 1 到 2 个点。如果掉太多说明校准集代表性不够得换一批图重新校准。还有一个容易被忽略的点是 batch size 对推理速度的影响。batch1 时 GPU 利用率低batch8 或 16 能显著提升吞吐量。但 batch 大了显存占用也大得在速度和显存之间找平衡。我一般会测 batch1、4、8、16 四档画一条吞吐量曲线选拐点附近的 batch 值。从那以后我每次拿到新的模型权重都会先跑一遍 FP32 推理确认精度基线再逐步切 FP16 和 INT8每一步都对比 mAP 和耗时。这个习惯帮我避免了好几次“速度上去了但精度崩了”的事故。希望帮到你。本文还有配套的精品资源点击获取