
前阵子在给一个项目做目标检测方案的部署模型在 PyTorch 里训练出来效果不错但一到现场 IoT 设备上跑就卡成幻灯片。折腾了一圈发现真正卡脖子的不是模型精度而是模型导出这步。当时用的正是 YOLO26从 PyTorch 权重一路导出到 ONNX、TensorRT踩了不少坑也把整个流程彻底摸透了。这篇就把 YOLO26 模型导出的完整思路、操作步骤和排坑经验整理出来给正要走上模型部署这条路的同学做个参考。不论你是搞计算机视觉大作业还是做人员入侵检测、单相机测距这些实际项目模型导出几乎都是绕不开的一关。训练出再好的权重导不出去、部署不上一切都是白搭。这篇文章适合刚接触 YOLO26、正在准备训练自己数据集、或者已经训练完但卡在导出环节的同学内容覆盖从环境准备到多平台导出的完整闭环。1. 模型导出到底在解决什么问题1.1 训练框架和推理引擎之间的鸿沟先聊一个最容易被忽视的基础问题为什么训练好的模型不能直接拿到生产环境用PyTorch 这类训练框架的设计目标是方便研究者快速搭建网络、调整结构、计算梯度方便程度是第一位。但部署场景恰好相反追求的是极致速度和资源占用。一个几百 MB 的 PyTorch 权重文件内存占用高、加载慢而且非常依赖 Python 运行环境这在边缘设备上基本是不可接受的。模型导出做的事情本质上就是把训练框架里的模型转换成推理引擎能高效运行的中间表示。以 YOLO26 为例训练时用的是 PyTorch导出后可能变成 ONNX、TensorRT engine、OpenVINO IR 或者 CoreML 格式。这个过程不是简单的换壳而是经历了算子映射、图优化、精度校准、内存布局调整等一系列操作。我曾经做过一次对比同样的 YOLO26s 模型直接用 PyTorch 做推理单张图片耗时约 120ms导出成 ONNX 后用 ONNXRuntime 跑耗时降到 60ms 左右再进一步构建成 TensorRT FP16 engine耗时只有 20ms。这个差距就是模型导出的价值而且项目越大、设备越边缘这个差距越致命。1.2 不同导出格式到底该怎么选YOLO26 官方提供了一个非常方便的export接口一行命令就能导出到各种格式。但很多同学对着一长串格式列表完全不知道选哪个。这里我给一个基于实际场景的选择逻辑ONNX通用性最强的中间格式几乎所有推理框架都能直接或间接支持。如果你只是做实验验证、或者不确定最终部署环境先导出 ONNX 是最稳妥的选择。TensorRTNVIDIA GPU 平台的专属加速方案能把 FP16 甚至 INT8 量化后的模型跑到极致速度。如果你的部署环境是 Jetson 或者带 NVIDIA 显卡的服务器这个是首选。OpenVINOIntel CPU、核显、VPU 平台的优化方案在 Intel 平台上比裸 ONNX 快不少。NCNN / MNN移动端和嵌入式端的轻量级推理框架适合手机、树莓派这类资源受限设备。CoreMLApple 生态专用iPhone 和 Mac 上跑模型必须用它。选择的原则很简单先确定你的部署硬件再反推该用什么格式。硬件定了格式基本就锁死了。别在格式选择上纠结太久大多数情况下先导出 ONNX 总能打通流程之后再做平台专属优化。1.3 YOLO26 导出功能的前置条件导出前需要确认几件事都准备到位了。首先是环境YOLO26 基于 Ultralytics 框架需要安装好ultralytics包而且版本不能太旧。建议直接用最新版老版本在导出 YOLO26 时会缺算子支持。其次是权重文件你得有一个训练好的.pt文件。这里我多说一句很多人喜欢直接用官方提供的预训练权重测试导出流程这是完全可以的但要注意如果你在自己的数据集上微调过导出时一定要确认权重路径正确别导出成别人家的模型了。最后是导出目标格式对应的依赖库。比如导出 ONNX 需要onnx和onnxsim导出 TensorRT 需要安装 TensorRT 的 Python 包。Ultralytics 在导出时会检查这些依赖缺了会直接报错。我的做法是提前把所有依赖装好避免导出中途被打断。2. 从 PyTorch 权重到 ONNX 的完整导出流程2.1 环境准备与依赖安装先说环境。我目前的推荐配置是 Python 3.10 以上、PyTorch 2.x、CUDA 11.8 或 12.1这个组合在 YOLO26 的导出上表现比较稳定。依赖安装的命令如下pip install ultralytics onnx onnxsim onnxruntime-gpu这里要注意onnxruntime-gpu和onnxruntime二选一别同时装会互相冲突。如果只想在 CPU 上验证结果装onnxruntime就够了。TensorRT 的安装稍微麻烦一点需要先安装 NVIDIA 的 TensorRT 库再装对应的 Python 包版本必须和 CUDA 版本匹配否则运行时直接报错。2.2 使用官方 export 接口完成导出Ultralytics 框架把导出过程封装得很简洁三行代码就能完成导出from ultralytics import YOLO model YOLO(yolo26n.pt) model.export(formatonnx, imgsz640, simplifyTrue, dynamicFalse)这段代码做的事是把 YOLO26n 模型导出为 ONNX 格式输入尺寸设为 640x640开启算子简化关闭动态输入。执行完成后当前目录下会出现一个yolo26n.onnx文件这就是我们要的部署格式。如果你想在命令行里直接操作也有对应的命令yolo export modelyolo26n.pt formatonnx imgsz640 simplifyTrue我建议新手先从 Python 接口入手因为报错信息更友好出问题也好定位。命令行方式适合已经跑通流程后做批量导出时用。2.3 关键导出参数逐个拆解只说“能用”太肤浅了这里把最关键的几个参数掰开揉碎讲清楚。imgsz 参数决定输入分辨率。640 是默认值也是速度和精度比较均衡的选择。如果检测目标很小可以考虑 960 甚至 1280但推理时间会成倍增加。我的建议是先按 640 导出跑通流程确认模型效果满足要求后再根据实际场景调整。simplify 参数建议始终开启。这个参数的作用是用 ONNX Simplifier 对计算图做冗余消除和算子融合能显著减少模型大小和推理耗时。实测下来开启 simplify 后模型体积能减少 10% 到 30%而且精度几乎不受影响。既然白拿的好处没有理由不开。dynamic 参数控制动态输入尺寸。默认是关闭的意味着模型只能接受固定尺寸的输入。如果开启模型就能处理任意尺寸的图像灵活性更高但代价是部分推理框架无法用上针对静态尺寸的优化速度会受到影响。对大多数项目来说固定输入尺寸完全够用不建议轻易开 dynamic。opset 参数指定 ONNX 算子集版本。默认值是 12但很多新算子需要更高版本才支持。如果要导出到 TensorRT建议设置为 17 或更高否则某些算子转换时容易出问题。2.4 用 Netron 验证导出结果导出完成后强烈建议用 Netron 看一眼模型结构。Netron 是一个开源的模型可视化工具支持 ONNX、TensorRT、CoreML 等几乎所有格式直接在浏览器里打开.onnx文件就能看到完整的网络结构。验证时重点看三样东西输入节点的名称和维度输出节点的名称和维度以及整体结构是否符合预期。正常情况下输入节点应该是一个[batch, 3, 640, 640]的四维张量输出节点有多个分别是检测框、分类得分和对象置信度相关的结果。这一步很多人会跳过但我真心建议别省。导出这步如果出了问题用 Netron 一眼就能看出来省下的排查时间远超可视化花掉的几分钟。3. 导出后的高性能部署方案落地3.1 ONNXRuntime 推理一把梭拿到 ONNX 文件后最快验证结果的方式就是用 ONNXRuntime 跑推理。这个框架支持 CPU 和 GPU 两种后端API 设计也比较简洁。import onnxruntime as ort import numpy as np import cv2 sess ort.InferenceSession(yolo26n.onnx, providers[CUDAExecutionProvider, CPUExecutionProvider]) input_name sess.get_inputs()[0].name input_shape sess.get_inputs()[0].shape print(f模型输入: {input_name}, 形状: {input_shape}) img cv2.imread(test.jpg) img_resized cv2.resize(img, (640, 640)) blob img_resized.astype(np.float32) / 255.0 blob np.transpose(blob, (2, 0, 1))[None] outputs sess.run(None, {input_name: blob})这里有个细节需要注意YOLO26 输入图像的预处理和后处理官方代码里有一整套逻辑包括 BGR 转 RGB、归一化、letterbox 填充等。如果你直接用上面这段简化代码跑结果大概率不对。一个偷懒但有效的办法是直接用 Ultralytics 提供的预测接口传入 ONNX 文件路径它会自动做全套预处理from ultralytics import YOLO model YOLO(yolo26n.onnx) results model(test.jpg) results[0].show()这样跑出来的结果和 PyTorch 原始模型误差极小可以用来验证 ONNX 导出是否有问题。等验证通过后再根据自己的需求实现定制化的预处理和后处理逻辑。3.2 TensorRT 加速从 FP32 到 FP16 的实测收益如果你的部署环境有 NVIDIA GPU那 TensorRT 几乎是必须做的优化。TensorRT 能把 ONNX 模型编译成高度优化的 engine 文件这个文件是专门针对特定 GPU 型号和 CUDA 版本生成的换台机器就得重新生成。用 Ultralytics 导出 TensorRT 很简单from ultralytics import YOLO model YOLO(yolo26n.pt) model.export(formatengine, imgsz640, halfTrue, dynamicFalse)halfTrue表示启用 FP16 精度。我实测过一组数据YOLO26s 在 RTX 3060 上FP32 的 ONNX 推理耗时约 18msFP16 的 TensorRT engine 推理耗时约 9ms速度提升一倍精度损失肉眼几乎看不出来。如果再激进一点可以做 INT8 量化速度还能再快 30% 到 40%但需要准备校准数据集而且精度损失明显处理小目标时容易出现漏检。我的建议是默认用 FP16只在推理速度实在不达标时才考虑 INT8并且一定要在自己的数据集上做充分的精度验证。TensorRT 导出的 engine 文件只能用于特定硬件和驱动版本这一点务必牢记。在开发机上生成 engine 后拷贝到部署机上用经常因为环境不一致导致加载失败。稳妥的做法是在部署机上重新生成 engine或者先用 ONNX 在部署机上验证流程再编译 TensorRT engine。3.3 轻量化部署NCNN 与移动端落地聊到轻量化部署正好呼应一下“YOLO26轻量化”这个说法。如果你的目标是手机、树莓派或者嵌入式 Linux 设备那 NCNN 是一个非常成熟的推理框架腾讯开源在移动端做了大量优化。from ultralytics import YOLO model YOLO(yolo26n.pt) model.export(formatncnn, imgsz640)导出的 NCNN 模型包含.param和.bin两个文件前者存网络结构后者存权重参数。使用 NCNN 的 C 接口加载模型时这两个文件缺一不可。这里有个经验分享YOLO26n 本身已经是轻量级模型但如果设备性能太弱可以尝试减小输入分辨率比如从 640 降到 320推理速度能提升近 3 到 4 倍精度虽然下降但在简单场景下完全够用。这比换用更复杂的模型压缩方法来得直接有效。3.4 OpenVINO 在 Intel 平台上的特殊优势如果你用的是 Intel CPU 或者集显OpenVINO 是一个性能上限很高的选择。它的优化思路和 TensorRT 类似只是针对的是 Intel 平台。model.export(formatopenvino, imgsz640, halfTrue)导出的 OpenVINO 模型包含一个.xml文件和一个.bin文件。用 OpenVINO 的 Runtime 加载时可以指定设备的优先级比如 CPU、GPU 或 VPU。实测在 Intel i5 处理器上OpenVINO 的推理速度比裸 ONNX 快 1.5 到 2 倍而且安装配置比 TensorRT 简单得多。如果项目既有 NVIDIA GPU 又有 Intel CPU一个比较实用的策略是开发环境用 TensorRT 做性能验证生产环境按实际硬件选择最优推理引擎。不要试图找一个万金油方案平台专属优化往往带来远超预期的性能收益。4. 各类工程问题排查与避坑记录4.1 算子和精度问题模型输出完全不对怎么办导出后最常遇到的问题就是模型输出结果和 PyTorch 原模型不一致甚至完全错误。排查这个问题我有一套固定流程。第一步检查预处理是否一致。YOLO 系列模型对输入图像的归一化方式非常敏感是除以 255 还是除以 256、是用[0,1]区间还是[-1,1]区间都会直接影响输出结果。最稳妥的方式是先用 Ultralytics 自带的预测接口验证 ONNX 结果确认没有问题后再动手写自己的预处理代码。第二步检查输入张量的维度顺序。YOLO 系列模型期望的输入格式是[batch, channel, height, width]也就是 NCHW 格式。很多人用 OpenCV 读图后直接reshape得到的是 NHWC 格式结果肯定不对。需要先transpose再expand维度。第三步检查输出解析逻辑。不同版本的 YOLO 输出格式不一样有的输出是 4 个张量分别代表边界框和各类别分数有的输出是单个合并张量。解析逻辑必须和导出模型的输出定义匹配这一块最容易出错也最难排查最好参考 Ultralytics 官方源码里的后处理实现。4.2 TensorRT 专属的踩坑修复记录TensorRT 在导出过程中最烦人的问题是环境版本不匹配。TensorRT 8.x 和 9.x 的 API 有一些不兼容的变化导致代码在开发机上运行正常部署到现场设备后直接报版本错误。我的建议是把环境版本固定下来不仅 TensorRT 版本要固定CUDA、cuDNN 的版本也要固定。最好将版本信息写在一个环境说明文件里换机器时照着装就不会错。另一个非常隐蔽的问题是动态 shape 和静态 shape 混用。如果你在导出时用了dynamicTrue但加载 engine 时又指定了静态 batch size推理时就会报维度不匹配的错误。这个问题的排查思路很明确始终明确导出和运行时是否使用相同的输入尺寸配置。另外TensorRT 对 ONNX 中某些不常用算子的支持并不完整。如果你的模型结构比较特殊比如在 YOLO26 里加了自定义注意力模块或自定义激活函数导出 ONNX 时很可能是成功的但构建 TensorRT engine 时就会报出“unsupported operation”的错误。这种情况有两个处理方向一是修改模型结构用 TensorRT 支持的算子替换自定义部分二是在导出 ONNX 时将某些算子用复合算子替代避免直接使用不支持的算子。4.3 常见问题速查表问题表现可能原因解决方案导出时提示缺少 onnx 包未安装 onnx 及其依赖pip install onnx onnxsimONNX 推理结果全为 0输入预处理或归一化错误用官方预测接口验证后用统一预处理逻辑TensorRT 加载 engine 失败GPU 型号或 CUDA 版本不匹配在部署机上重新生成 engine 文件导出 NCNN 时算子不支持模型结构包含特殊算子尝试simplifyTrue或换格式OpenVINO 导出后推理速度反而变慢输入尺寸设置不当检查imgsz并考虑开启halfTrue动态尺寸推理时报维度错误dynamic 配置与运行时不一致统一导出和推理时的尺寸策略FP16 精度导致漏检严重目标过小或对比度低改回 FP32 或采用 INT8 量化加校准集4.4 精度对比与性能评估的正确姿势导出后一定要做一次系统性的精度对比不建议只跑一两张图看一眼就完事。我的做法是准备一个至少几百张图片的测试集覆盖不同光线、角度、目标大小在原始 PyTorch 模型和导出后模型上分别跑一遍统计 mAP 或 mAP50 的差异。如果差异在 1% 以内基本可以认为导出无损如果超过 3%就得排查是哪些类别掉精度再针对性调整。性能评估方面需要关注的不只是单帧推理时间还有几个指标模型加载时间、预热后与预热前的耗时差异、连续推理时的帧率稳定性。很多人只看平均耗时忽略了抖动问题。实测中有的模型平均耗时很低但持续推理时会有偶发的高延迟这在实时监控场景下非常致命。最后提醒一句内存占用。同一个模型在 PyTorch 里、ONNX Runtime 里、TensorRT 里内存占用差异巨大。嵌入式和移动端场景对内存有硬限制必须在开发前就确认好内存预算否则模型导出了也上不了线。5. 从导出到落地的完整流程经验谈5.1 从模型训练到人员入侵检测的完整链路聊完技术细节谈谈这些能力在实际项目里怎么组合。以热词里“YOLO26人员入侵检测”这类项目为例完整链路大概是这样的先用 YOLO26 在自己的数据集上训练数据集里得有正常人员和入侵人员的标注样本训练完成后导出成适合目标设备的格式然后在部署端写推理逻辑包括读视频流或摄像头、逐帧检测、画框、告警。这个过程中模型导出环节决定了整个系统能不能达到实时性要求。如果摄像头有 25 帧每秒单帧推理时间必须控制在 40ms 以内这基本就排除了用 PyTorch 直接推理的方案ONNXRuntime 或 TensorRT 是底线选择。我用 YOLO26n 导出成 TensorRT FP16 后在 Jetson Orin Nano 上能跑到 30ms 左右稳定支撑 25 帧的实时检测这个方案我复制到过好几个项目上。5.2 结合单相机测距的导出策略再聊聊“YOLO26 单相机测距输出距离”这个方向。单相机测距本质上是先检测出目标再根据目标的像素位置、尺寸和相机参数估算距离。YOLO26 的检测输出包含边界框的中心坐标和宽高这些信息正好是测距的输入。这类项目的模型导出重点不在格式选择而在于保持输出信息的完整性。有些会在导出时把后处理逻辑一并优化掉只输出最终的类别和置信度这会丢掉边界框的坐标信息导致测距算法没有输入可用。所以导出时建议保留完整的原始输出在部署代码里自己实现后处理和距离计算逻辑。另外测距场景对精度要求更高在导出时尽量保持 FP32 精度。FP16 虽然在大多数检测场景下没问题但在边界框回归上偶尔会有微小偏差这个偏差在距离换算后会被放大影响最终结果。5.3 如何在“计算机视觉大作业”中把导出做得出彩如果是学生项目或者课程作业把模型导出做好往往是加分项。很多人的大作业止步于训练出一个模型再用 PyTorch 跑个 demo这已经不算亮点了。如果你能在作业里完整展示“训练 PyTorch 模型 → 导出 ONNX → 部署到边缘设备 → 实时推理”的链路并且对比各阶段的性能和精度数据作业的综合完成度立刻就不一样了。这里分享一个小技巧导出过程中记录完整的性能对比数据包括各格式的模型大小、推理耗时、精度指标整理成表格放进实验报告里。数据永远比文字有说服力。5.4 后续还能怎么扩展模型优化思路导出完成之后优化工作其实才刚刚开始。一个很强的优化方向是知识蒸馏用训练好的大模型当教师训练一个小模型当学生然后把这个学生模型部署到边缘设备。YOLO26 的高精度模型作为教师能得到精度和速度双优的小模型这也是“YOLO26改进”类项目里性价比很高的思路。另一个方向是剪枝和量化。剪枝可以移除不重要的通道或层量化则可以把权重的精度从 FP32 降到 INT8 甚至 INT4这两个技术在导出环节都能做且效果显著。我的实际建议是先把手头的模型导出并部署跑通拿到真实场景下的性能数据再决定要不要做进一步优化。很多人在优化技术上花了一堆时间结果发现当前模型在目标设备上已经跑得很流畅过度优化反而浪费了时间。先完成再完美。6. 导出过程中的几个核心心得体会把 YOLO26 模型导出这件事做到现在我越来越觉得导出不是训练的收尾而是部署的发令枪。整个环节里最关键的从来不是某个参数怎么设置而是你是否理解了每个格式背后的适用场景。我个人的工作习惯是先导 ONNX 作为通用中间格式验证精度和速度都达标后再针对最终硬件做平台专属优化。直接盲选 TensorRT 或者 NCNN 容易陷入“倒腾半天发现硬件不支持”的尴尬局面。先把 ONNX 跑通相当于给整个部署链路做了一次端到端验证后面再换格式是风险最低的路径。另一个体会是文档要勤记。不同版本的 Ultralytics、TensorRT、ONNX Runtime 之间兼容性问题非常多今天跑通的代码放几天可能就动不了了。我会把每个项目用到的版本号、导出命令、遇到的坑和解决方案都记下来这个习惯在跨项目复用时帮我省了大量时间。如果你正在做 YOLO26 的部署工作建议按这个优先级推进先用 640 分辨率导出 ONNX 验证通路再尝试 FP16 的 TensorRT engine 看性能收益最后根据实际部署设备决定是否需要 NCNN 或 OpenVINO。别一上来就研究 INT8 量化先跑通流程比追求极致性能重要得多。