深度学习-Python调用ONNX模型

目录


ONNX模型使用流程

ONNX(Open Neural Network Exchange)是一种开放的、跨平台的深度学习模型格式和编译器,可以帮助用户在不同的深度学习框架中转换和部署模型。下面介绍ONNX如何使用的流程:

  1. 导出模型:在训练好深度学习模型后,通过ONNX的支持的框架,比如PyTorch、TensorFlow等将模型导出为ONNX格式。

  2. 加载模型:使用ONNX的支持库,比如ONNX Runtime,加载ONNX文件格式的模型。

  3. 部署模型:通过ONNX Runtime在不同的硬件设备上运行模型,支持常见的CPU、GPU、FPGA等。

  4. 进行推理:将输入数据加载到模型中,进行推理或分类任务,输出结果。

ONNX还有其他的特点,比如具有可扩展性、良好的跨平台支持、对多种硬件设备的支持等。因此,ONNX是一种强大的深度学习模型转换和部署工具,可以大大加速深度学习模型的开发和部署过程。

获取ONNX模型方法

获取ONNX模型有以下几种方法:

        1. 使用ONNX标准工具导出已有的深度学习模型

许多深度学习框架都支持直接导出ONNX格式的模型,如PyTorch、TensorFlow、Keras等。可参考相应框架的文档,使用ONNX标准工具将模型导出为ONNX格式。

        2. 使用第三方工具转换

也可以使用一些第三方工具将已有的模型进行转换,例如mmcv中的convert_to_onnx.py工具。

        3. 手动编写ONNX模型

如果没有原始模型或无法导出,则需要手动编写ONNX模型。ONNX模型由计算图和模型参数组成。计算图用于定义模型结构和计算流程,可以使用ONNX工具或第三方工具进行编写,也可以手动编写。模型参数用于定义模型权重,可以使用Python脚本或其他工具进行生成或导入。

总之,获取ONNX模型的方法取决于具体情况,不同场景下合适的方法也会有所不同。

使用ONNX模型

手动编写ONNX模型

手动编写ONNX模型需要了解ONNX模型的结构和语法,以及具体深度学习框架的计算图结构和权重参数格式。

以下是一个手动编写的简单ONNX模型例子,用于对一维张量进行线性变换和ReLU激活:

import onnx
import numpy as np
from onnx import numpy_helper
from onnx import helper

# 定义输入张量
input_tensor = helper.make_tensor_value_info('input', onnx.TensorProto.FLOAT, [1, 10])

# 定义权重张量
weight = np.random.rand(10, 5).astype(np.float32)
weight_initializer = numpy_helper.from_array(weight, 'weight')

# 定义偏置张量
bias = np.random.rand(5).astype(np.float32)
bias_initializer = numpy_helper.from_array(bias, 'bias')

# 定义节点1:矩阵乘法
matmul_node = helper.make_node(
    'MatMul',
    inputs=['input', 'weight'],
    outputs=['matmul_output']
)

# 定义节点2:加法
add_node = helper.make_node(
    'Add',
    inputs=['matmul_output', 'bias'],
    outputs=['add_output']
)

# 定义节点3:ReLU激活
relu_node = helper.make_node(
    'Relu',
    inputs=['add_output'],
    outputs=['output']
)

# 定义计算图
graph_def = helper.make_graph(
    [matmul_node, add_node, relu_node],
    'test-model',
    [input_tensor],
    [helper.make_tensor_value_info('output', onnx.TensorProto.FLOAT, [1, 5])],
    initializer=[weight_initializer, bias_initializer]
)

# 定义模型
model_def = helper.make_model(
    graph_def,
    producer_name='my-model',
    opset_imports=[helper.make_opsetid('', 12)]
)

# 保存模型
onnx.save(model_def, 'test-model.onnx')

此例中,通过手动定义输入张量、权重张量、偏置张量和节点(矩阵乘法、加法、ReLU激活)构建了一个简单的计算图,并通过ONNX工具生成了ONNX格式的模型文件test-model.onnx。可以使用ONNX工具或特定框架工具加载此模型进行推理。

Python调用ONNX模型

下面以使用Python调用ONNX模型为例子,具体步骤如下:

  1. 安装ONNX Runtime库
  2. 加载ONNX模型
  3. 准备输入数据
  4. 进行推理


import onnxruntime
import numpy as np
import onnxruntime as ort


model_path = 'test-model.onnx'



providers = ['CPUExecutionProvider']
ort_session = ort.InferenceSession(model_path, providers=providers)

# ort_session = onnxruntime.InferenceSession('test-model.onnx', providers=['CPUExecutionProvider', 'CUDAExecutionProvider'])



batch_size = 1
input_size = 10  # set input size to 10

input_data = np.random.rand(batch_size, input_size).astype(np.float32)
input_data = input_data.reshape(batch_size, input_size)  # reshape input_data to (batch_size, 10)


# batch_size = 1
# input_size = 784  # assuming you have a model that takes 784 inputs
#
# input_data = np.random.rand(batch_size, input_size).astype(np.float32)

output = ort_session.run(None, {'input': input_data})[0]

print(output)

执行结果:

[[2.5079055 3.4431007 2.5739892 2.332235  1.9329181]]

在这个例子中,我们使用Python调用ONNX Runtime库来加载ONNX模型,并使用随机生成的输入数据进行推理。在ONNX模型的输入中,我们以字典的形式传递输入数据。推理的结果是一个输出数组,这是由ONNX模型定义的。

这就是Python调用深度学习模型ONNX的基本步骤,可以根据具体的模型和任务,在此基础上进行调整和扩展。

常见错误

错误raise ValueError…

  raise ValueError(
ValueError: This ORT build has ['AzureExecutionProvider', 'CPUExecutionProvider'] enabled. Since ORT 1.9, you are required to explicitly set the providers parameter when instantiating InferenceSession. For example, onnxruntime.InferenceSession(..., providers=['AzureExecutionProvider', 'CPUExecutionProvider'], ...)

解决方法

该错误是由于在ORT 1.9版本中,调用InferenceSession时必须显式地设置providers参数来指定要使用的执行提供程序,否则会引发此错误。

要解决此错误,您需要在调用InferenceSession时设置providers参数。例如,如果您要使用CPUExecutionProvider和CUDAExecutionProvider,请按以下方式调用InferenceSession:

import onnxruntime

session = onnxruntime.InferenceSession('model.onnx', providers=['CPUExecutionProvider', 'CUDAExecutionProvider'])

在这里,我们将providers参数设置为包含CPUExecutionProvider和CUDAExecutionProvider的列表。根据您的需求,您可以选择其他ExecutionProvider。

请注意,如果您在调用InferenceSession时不设置providers参数,将会发生上述错误,即使您在构建模型时已经定义了ExecutionProvider。

错误:Load model model.onnx failed

onnxruntime.capi.onnxruntime_pybind11_state.NoSuchFile: [ONNXRuntimeError] : 3 : NO_SUCHFILE : Load model from model.onnx failed:Load model model.onnx failed. File doesn't exist

该错误提示 ONNXRuntimeError:3:NO_SUCHFILE,是由于onnxruntime无法在指定路径中找到模型文件model.onnx,因此无法加载模型。

要解决此错误,您需要检查以下几点:

  1. 检查您提供的文件路径是否正确。

    请确保您提供的文件路径是正确的,并且包含文件名和后缀名,例如’model.onnx’。

  2. 检查文件名是否正确。

    请确保文件名拼写正确,并且大小写正确。

  3. 检查文件是否存在。

    请确保指定路径中包含该文件。您可以通过在Python中运行以下代码进行检查:

    import os.path
    
    model_path = 'model.onnx'
    exists = os.path.isfile(model_path)
    if not exists:
        print('Model file not found:', model_path)
    
  4. 检查文件路径是否有权限访问。

    如果您使用的是Windows,则可能需要以管理员身份运行命令提示符或PyCharm。如果您使用的是Linux或macOS,则需要检查文件路径是否有正确的权限。

通过以上步骤排查未能加载模型的原因,并进行相应的修正即可解决此错误。

错误:’CUDAExecutionProvider’ is not in available provider

UserWarning: Specified provider 'CUDAExecutionProvider' is not in available provider names.Available providers: 'AzureExecutionProvider, CPUExecutionProvider'
  warnings.warn(
Traceback (most recent call last):
  File "D:\code\AutoTest\common\onnx\testOnnx.py", line 13, in <module>
    input_data = np.random.rand(batch_size, input_size).astype(np.float32)
                                ^^^^^^^^^^
NameError: name 'batch_size' is not defined 
解决方法

此错误具有两个独立的部分:

  1. UserWarning:Specified provider ‘CUDAExecutionProvider’ is not in available provider names。

    这意味着您正在尝试使用CUDAExecutionProvider,但是您的环境中可能没有安装或可用CUDAExecutionProvider。您可以尝试更改提供程序使用CPUExecutionProvider或AzureExecutionProvider。

    在您的代码中,您可以这样设置提供程序:

    import onnxruntime as rt
    
    providers = ['CPUExecutionProvider']  # or ['AzureExecutionProvider']
    session = rt.InferenceSession('model.onnx', providers)
    
  2. NameError:name ‘batch_size’ is not defined。

    这意味着您在代码中使用了“batch_size”变量,但是在代码的上下文中未定义该变量。请确保您已经定义了batch_size变量并赋予其正确的值。

    例如,您可以在代码中设置batch_size变量,如下所示:

    import numpy as np
    
    batch_size = 1
    input_size = 784  # assuming you have a model that takes 784 inputs
    
    input_data = np.random.rand(batch_size, input_size).astype(np.float32)
    

通过以上步骤排查未定义变量和可用提供程序的问题,并进行相应的修正即可解决此错误。

错误:ONNXRuntimeError

 in run
    return self._sess.run(output_names, input_feed, run_options)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
onnxruntime.capi.onnxruntime_pybind11_state.InvalidArgument: [ONNXRuntimeError] : 2 : INVALID_ARGUMENT : Got invalid dimensions for input: input for the following indices
 index: 1 Got: 784 Expected: 10
 Please fix either the inputs or the model. 
解决方法

此错误涉及到两个问题:

  1. UserWarning: Specified provider ‘CUDAExecutionProvider’ is not in available provider names。 Available providers: ‘AzureExecutionProvider, CPUExecutionProvider’。

这个问题在前一个错误中已经解释过了。请参考之前的解决方法。

  1. InvalidArgument: [ONNXRuntimeError] : 2 : INVALID_ARGUMENT : Got invalid dimensions for input: input for the following indices index: 1 Got: 784 Expected: 10 Please fix either the inputs or the model。

这个错误意味着您提供的输入张量形状不正确,或者模型中期望的输入形状与提供的输入形状不匹配。

在您给出的代码中,您正在尝试将一个形状为(batch_size, 784)的输入张量提供给模型,但是模型期望输入张量的形状为(batch_size, 10)。 您需要更改输入张量的形状,以便它符合模型的输入形状。

例如,如果您的模型期望的输入形状是(batch_size, 10),您可以将示例代码中的input_size变量设置为10。 然后您可以在生成随机输入数据时,将生成的随机数重塑为(batch_size, 10)形状的张量。

具体而言,您可以在代码中添加以下行,将input_size变量设置为10,并将input_data变量重塑为(batch_size, 10)张量:

import numpy as np

batch_size = 1
input_size = 10  # set input size to 10

input_data = np.random.rand(batch_size, input_size).astype(np.float32)
input_data = input_data.reshape(batch_size, input_size)  # reshape input_data to (batch_size, 10)

这样,您就可以使用正确形状的输入张量来运行模型,避免了此错误。

错误:’CUDAExecutionProvider’ is not in available provider

UserWarning: Specified provider 'CUDAExecutionProvider' is not in available provider names.Available providers: 'AzureExecutionProvider, CPUExecutionProvider'
  warnings.warn( 
解决方法

这个警告通常意味着您指定了一个不存在的执行提供程序。在使用onnxruntime.InferenceSession()创建会话对象时,您可以指定要使用的执行提供程序列表。如果指定的执行提供程序不在可用提供程序列表中,则会出现上述警告。

如何解决这个问题取决于您的目标。如果您确信指定的执行提供程序可用,则可以无视警告。否则,可以从可用的提供程序列表中选择一个或多个提供程序,并在创建会话时将其作为提供程序参数传递。例如:

import onnxruntime as ort

providers = ['CPUExecutionProvider']
ort_session = ort.InferenceSession(model_path, providers=providers)

在这个示例中,我们将CPUExecutionProvider作为提供程序传递给onnxruntime.InferenceSession()。如果这个提供程序在可用的提供程序列表中,则不会出现警告。

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
xiaoxingxing的头像xiaoxingxing管理团队
上一篇 2023年11月6日
下一篇 2023年11月6日

相关推荐