pytorch 模型转 onnx 遇到的问题记录.

博客讲述了在尝试将PyTorch模型导出为ONNX格式时遇到的Resize运算符版本不匹配问题。作者发现警告提示建议使用opset11及以上版本以避免结果不一致。通过将导出时的opset_version从9改为12,最终成功解决了问题。转换代码中包含了关键参数设置和调整。
部署运行你感兴趣的模型镜像

1.第一个内存溢出.

解决方法,增加系统虚拟内存.

2.导出时报错

D:\Anaconda3\lib\site-packages\torch\onnx\symbolic_helper.py:266: UserWarning: You are trying to export the model with onnx:Resize for ONNX opset version 10. This operator might cause results to not match the expected results by PyTorch.
ONNX’s Upsample/Resize operator did not match Pytorch’s Interpolation until opset 11. Attributes to determine how to transform the input were added in onnx:Resize in opset 11 to support Pytorch’s behavior (like coordinate_transformation_mode and nearest_mode).
We recommend using opset 11 and above for models using this operator.
warnings.warn("You are trying to export the model with " + onnx_op + " for ONNX opset version "

翻译一下

您正在尝试用导出模型onnx:Resize for ONNX opset版本10。此运算符可能导致结果与PyTorch的预期结果不匹配。
直到opset 11,ONNX的Upsample/Resize操作符才与Pytorch的插值匹配onnx:Resize in opset 11支持Pytorch的行为(比如坐标转换模式和最近的模式)。
对于使用此运算符的模型,我们建议使用opset 11及更高版本。

大概意思就是要升级一下版本. 至于是哪个版本,百度一下
You are trying to export the model with onnx:Resize for ONNX opset version 10
结果在 https://blog.youkuaiyun.com/flyfish1986/article/details/115031540 找到了答案, 感谢博主.

解决方案
默认opset version 是9,更改为11,

import torch
torch.onnx.export(model,, opset_version=11)

后来还是提示有版本问题, 于是抱着试试看的态度我有改成了12. 结果就通了…

附加一下我的转换代码. 也是抄自别人博客的. 做了点小修改, 注意使用的时候cpu和cuda的问题. 我的cuda 内存太小于是用的cpu转的. 就是比较吃内存, 反正就运行一次. 能用就好.


    
    
    #
# demo.py
# 识别单张图片
#
import argparse
import os
import numpy as np
import time

from modeling.deeplab import *
from dataloaders import custom_transforms as tr
from PIL import Image
import torch
from torchvision import transforms
from dataloaders.utils import  *

from utils.ColorMap import colors   
 
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt

# from torchvision.utils import make_grid, save_image,to_image
palette = np.array(colors).reshape(-1).tolist()

def main():  
    global palette

    print("start to onnx ...") 
    parser = argparse.ArgumentParser(description="PyTorch DeeplabV3Plus Training")
    parser.add_argument('--checkpoint_file', type=str, required=True, help='image to test')
    parser.add_argument('--export_onnx_file', type=str, required=True, help='image out path')
    parser.add_argument('--backbone', type=str, default='resnet', choices=['resnet', 'xception', 'drn', 'mobilenet'],  help='backbone name (default: resnet)')
    parser.add_argument('--out_stride', type=int, default=16,  help='network output stride (default: 8)')
    parser.add_argument('--num_classes', type=int, default=2, help='crop image size')
    parser.add_argument('--sync_bn', type=bool, default=None, help='whether to use sync bn (default: auto)')
    parser.add_argument('--batch_size', type=int, default=4, help=' batch size ') 

    # parser.add_argument('--out-path', type=str, required=True, help='mask image to save')
    # parser.add_argument('--ckpt', type=str, default='deeplab-resnet.pth', help='saved model')
    # parser.add_argument('--no-cuda', action='store_true', default=False,  help='disables CUDA training')
    # parser.add_argument('--gpu-ids', type=str, default='0', help='use which gpu to train, must be a \ comma-separated list of integers only (default=0)')
    # parser.add_argument('--dataset', type=str, default='pascal', choices=['pascal', 'coco', 'cityscapes','invoice'],  help='dataset name (default: pascal)')
    # parser.add_argument('--crop-size', type=int, default=513,  help='crop image size')
    parser.add_argument('--freeze_bn', type=bool, default=True,  help='whether to freeze bn parameters (default: False)')

    args = parser.parse_args()
    # args.cuda = not args.no_cuda and torch.cuda.is_available() 

    model = DeepLab(num_classes=args.num_classes,
                    backbone=args.backbone,
                    output_stride=args.out_stride,
                    sync_bn=args.sync_bn,
                    freeze_bn=args.freeze_bn)

    ckpt = torch.load(args.checkpoint_file, map_location=lambda storage, loc: storage.cuda(0))
    # ckpt = torch.load(args.checkpoint_file, map_location='cpu')
    model.load_state_dict(ckpt['state_dict'])

    # if torch.cuda.is_available():
    #   # model = model.cuda()
    #   device = torch.device("cuda:0")
    #   model.to(device)

    model.eval()
    
    batch_size = args.batch_size #批处理大小
    input_shape = (3, 1080, 1920)   #输入数据,改成自己的输入shape
    inputx = torch.randn(args.batch_size, *input_shape)   # 生成张量
    # inputx = inputx.to('cpu')
    # inputx = inputx.cuda()
    # export_onnx_file = os.path.join(Seting.AIModelsDir_Production, "deeplabv3model.onnx")	# 目的ONNX文件名 
    torch.onnx.export(model,
                      inputx,
                      args.export_onnx_file,
                      opset_version=12,
                      do_constant_folding=True,	# 是否执行常量折叠优化
                      input_names=["input"],	# 输入名
                      output_names=["output"],	# 输出名
                      dynamic_axes={"input":{0:"batch_size"},  # 批处理变量
                                    "output":{0:"batch_size"}}
                    )

    # print("image save in image_path.")
    print("end to onnx ...")

if __name__ == "__main__":
    main()
 

您可能感兴趣的与本文相关的镜像

PyTorch 2.5

PyTorch 2.5

PyTorch
Cuda

PyTorch 是一个开源的 Python 机器学习库,基于 Torch 库,底层由 C++ 实现,应用于人工智能领域,如计算机视觉和自然语言处理

<think>好的,我现在需要回答用户关于如何在C++中加载PyTorch换的ONNX模型文件的问题。首先,我需要确认用户的具体需求。用户提到参考了三个引用,其中引用[3]提到使用TensorRT进行部署的步骤,包括将PyTorch模型ONNX,再成TensorRT,或者使用ONNX Runtime。因此,用户可能希望在C++环境中加载ONNX模型,可能使用ONNX Runtime或TensorRT。 接下来,我应该分步骤说明。首先,用户需要将PyTorch模型导出为ONNX,这部分引用[1]中的torch.onnx.dynamo_export()可能相关,但用户已经完成了导出,所以重点在C++加载部分。 然后,我需要考虑两种常见情况:使用ONNX Runtime或TensorRT来加载ONNX模型。引用[3]提到两者都有C++接口,所以需要分别说明。对于ONNX Runtime,步骤可能包括安装库、编写C++代码加载模型、创建会话、准备输入输出张量等。对于TensorRT,可能需要先ONNX到TensorRT引擎,再加载引擎进行推理。 另外,引用[2]中提到的问题可能与模型导出时的兼容性有关,比如某些操作在ONNX tracing时可能不被支持。需要提醒用户在导出ONNX时确保模型兼容性,避免在C++加载时出现问题。 需要检查ONNX Runtime和TensorRT的安装方法,确保用户能正确配置环境。例如,在Ubuntu下使用apt安装ONNX Runtime的C++包,或者从源码编译。对于TensorRT,可能需要下载官方库并配置路径。 在编写示例代码时,要确保语法正确,比如使用ONNX Runtime的C++ API创建环境、会话,处理输入输出。对于TensorRT,可能需要使用解析器加载ONNX模型,构建引擎,并执行推理。 最后,需要提醒用户注意模型导出时的动态轴设置、算子兼容性以及输入输出的正确性,这些都可能影响C++端的加载和推理结果。同时,引用相关的引用来源,如引用[3]提到的流程,确保回答有据可依。</think>在C++中加载PyTorch换的ONNX模型文件,主要可以通过**ONNX Runtime**或**TensorRT**两种方式实现。以下是具体步骤和代码示例: --- ### 一、使用ONNX Runtime加载(CPU/GPU通用) #### 1. 安装ONNX Runtime C++库 ```bash # Ubuntu/Debian安装预编译库 sudo apt-get install libonnxruntime-dev ``` 或从[ONNX Runtime GitHub Release](https://github.com/microsoft/onnxruntime/releases)下载对应平台的二进制包。 #### 2. C++代码示例 ```cpp #include <onnxruntime/core/session/onnxruntime_cxx_api.h> int main() { // 1. 初始化环境 Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "test"); Ort::SessionOptions session_options; // 2. 加载ONNX模型 Ort::Session session(env, "model.onnx", session_options); // 3. 准备输入数据 std::vector<int64_t> input_shape = {1, 3, 224, 224}; // 输入张量形状 std::vector<float> input_data(1*3*224*224, 1.0f); // 示例输入数据 Ort::MemoryInfo memory_info = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault); // 4. 创建输入Tensor Ort::Value input_tensor = Ort::Value::CreateTensor<float>( memory_info, input_data.data(), input_data.size(), input_shape.data(), input_shape.size() ); // 5. 执行推理 const char* input_name = session.GetInputName(0, Ort::AllocatorWithDefaultOptions()); const char* output_name = session.GetOutputName(0, Ort::AllocatorWithDefaultOptions()); std::vector<const char*> input_names = {input_name}; std::vector<const char*> output_names = {output_name}; auto outputs = session.Run(Ort::RunOptions{nullptr}, input_names.data(), &input_tensor, 1, output_names.data(), 1); // 6. 处理输出 float* output_data = outputs[0].GetTensorMutableData<float>(); // ...对输出数据进行操作 return 0; } ``` --- ### 二、使用TensorRT加载(GPU加速) #### 1. 安装TensorRT库 从[NVIDIA官网](https://developer.nvidia.com/tensorrt)下载TensorRT的C++库,并配置环境变量: ```bash export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/TensorRT/lib ``` #### 2. C++代码示例 ```cpp #include <NvInfer.h> #include <NvOnnxParser.h> // 1. 创建TensorRT日志记录器 class Logger : public nvinfer1::ILogger { void log(Severity severity, const char* msg) override { if (severity <= Severity::kWARNING) std::cout << msg << std::endl; } } logger; int main() { // 2. 创建构建器和网络 nvinfer1::IBuilder* builder = nvinfer1::createInferBuilder(logger); nvinfer1::INetworkDefinition* network = builder->createNetworkV2(1U << static_cast<uint32_t>(nvinfer1::NetworkDefinitionCreationFlag::kEXPLICIT_BATCH)); // 3. 解析ONNX模型 nvonnxparser::IParser* parser = nvonnxparser::createParser(*network, logger); parser->parseFromFile("model.onnx", 2); // 第二个参数为日志级别 // 4. 构建优化引擎 nvinfer1::IBuilderConfig* config = builder->createBuilderConfig(); config->setMaxWorkspaceSize(1 << 30); // 1GB内存空间 nvinfer1::ICudaEngine* engine = builder->buildEngineWithConfig(*network, *config); // 5. 序列化引擎并保存(可选) nvinfer1::IHostMemory* serialized_engine = engine->serialize(); std::ofstream engine_file("model.engine", std::ios::binary); engine_file.write(static_cast<const char*>(serialized_engine->data()), serialized_engine->size()); // 6. 执行推理(需反序列化引擎并创建执行上下文) // ...后续代码略,需包含CUDA上下文管理和数据拷贝 return 0; } ``` --- ### 三、关键注意事项 1. **模型导出兼容性** - 确保PyTorch导出ONNX时使用`torch.onnx.export`或`torch.onnx.dynamo_export`,并验证模型是否包含动态轴(如`dynamic_axes`参数)[^1][^3]。 - 若遇到类型问题(如`torch.Size`在ONNX导出时失效),需显式换为`tuple`或使用静态形状[^2]。 2. **性能优化** - ONNX Runtime支持多线程推理,可通过`session_options.SetIntraOpNumThreads(4)`配置。 - TensorRT可通过FP16/INT8量化进一步加速。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值