onnx优化系列 - 获取中间Node的inference shape的方法

本文介绍如何使用ONNX的shape_inference模块获取模型中间节点的形状信息,这对于理解模型内部工作原理及优化至关重要。文章详细展示了通过修改输入张量、添加权重信息并运行形状推断的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ONNX获取中间Node的inference shape的方法

需求描述

很多时候发现通过tensorflow或者pytorch转过来的模型是没有中间的node的shape的,比如下面这样:
原始模型
但是碰到一些很奇怪的算子的时候,我们又想知道他对上一层feature map的形状影响是怎样的,于是下面的模型看起来会更友好一些
带中间shape的模型
这里之所以看上去和原来的node的分布都不一样,是因为我在这里将pad和biasadd加到conv中了已经。

原理

ONNX本身提供了进行inference的api:

shape_inference.infer_shapes()

但是呢,这里进行inference并不是根据graph中的tensor,而是根据graph的input中各个tensor的tensor_value_info。所以我们需要做的就是根据各个tensor的信息创建出对应的tensor_value_info之后将其append进graph.inputs即可。

最开始我进行infer_shapes之后发现没用就是因为graph.inputs中的tensor_value_info只有input node的。

代码

import onnx
from onnx.tools import update_model_dims
import numpy as np
import onnx.helper as helper
from onnx import shape_inference, TensorProto
import sys

ONNX_DTYPE = {
    0: TensorProto.FLOAT,
    1: TensorProto.FLOAT,
    2: TensorProto.UINT8,
    3: TensorProto.INT8,
    4: TensorProto.UINT16,
    5: TensorProto.INT16,
    6: TensorProto.INT32,
    7: TensorProto.INT64,
    8: TensorProto.STRING,
    9: TensorProto.BOOL
}

# load model
onnx_model = onnx.load("tf_resnet_v2_50_onnx.onnx")
graph = onnx_model.graph

# rewrite the input tensor of graph
input_tensor = graph.input[0]
input_shape = input_tensor.type.tensor_type.shape.dim
input_tensor_new = onnx.helper.make_tensor_value_info(name = input_tensor.name, elem_type = 1, 
                                                      shape = [1, input_shape[1].dim_value, input_shape[2].dim_value, input_shape[3].dim_value])
graph.input.remove(input_tensor)
graph.input.insert(0, input_tensor_new)

# append all tensor infos to graph input
weight_infos = []
tensors = graph.initializer
for i, tensor in enumerate(tensors):
    value_info = helper.make_tensor_value_info(tensor.name, ONNX_DTYPE[tensor.data_type], tensor.dims)
    weight_infos.append(value_info)
    graph.input.insert(i+1, value_info) # because 0 is for placeholder, so start index is 1

# run node shape inference
node = graph.node
value_info = graph.value_info
print("Before shape inference: \n")
print(value_info)
print("------------------------------------------------------------")
print("After shape inference: \n")
inferred_onnx_model = shape_inference.infer_shapes(onnx_model)
onnx.checker.check_model(onnx_model)
inferred_graph = inferred_onnx_model.graph
inferred_value_info = inferred_graph.value_info
print(inferred_value_info)
onnx.save(inferred_onnx_model,"./new.onnx")
### 将PaddleOCR模型转换为ONNX格式 为了将PaddleOCR中的推理模型转换成ONNX格式,需遵循特定的过程并准备必要的资源。此过程适用于希望利用ONNX优化部署流程或跨平台支持的应用场景。 #### 准备工作 确保拥有待转换的PaddleOCR推理模型URL或是本地tar包路径作为输入源。对于文字识别类模型而言,还需额外准备好对应的字符映射表(txt文件),以便将其集成至最终导出的ONNX模型内[^1]。 #### 转换命令示例 针对文字识别模型的具体转换操作可以通过`paddle2onnx`工具完成: ```bash paddle2onnx --model_dir ./inference_large/rec/ \ --model_filename inference.pdmodel \ --params_filename inference.pdiparams \ --save_file ./onnx_model/rec_large.onnx \ --opset_version 11 \ --enable_onnx_checker True ``` 这条指令会读取位于指定目录下的`.pdmodel`与`.pdiparams`两个文件,并按照设定参数保存为新的ONNX格式模型文件于目标位置。其中`--opset_version`指定了所使用的ONNX版本号;而`--enable_onnx_checker`选项则用于启用对生成模型的有效性验证功能[^2]。 #### 修改模型配置 默认情况下,转换后的ONNX模型具有固定的输入维度(-1, 3, 32, 100)。如果应用需求涉及到不同大小的数据集,则可能需要调整这些预设值来匹配实际应用场景的要求。这一步骤通常借助第三方库如`onnx`来进行编程式的修改。 ```python import onnx from onnx import helper as hlp # 加载现有模型定义 model = onnx.load('rec_large.onnx') # 获取第一个节点的信息 input_node = model.graph.input[0] # 更新输入张量形状属性 new_shape = ['?', '3', '?', '?'] # '?' 表示动态轴 dim_value_proto_list = [] for dim in new_shape: if isinstance(dim, str): dvp = hlp.make_tensor_value_info(name='dynamic_dim', elem_type=7, shape=[], vals=None) dim_value_proto_list.append(dvp) else: dim_value_proto_list.append(hlp.make_tensor_value_info( name='', elem_type=7, shape=[], vals=np.array([int(dim)]).astype(np.int64))) hlp.set_shape(input_node.type.tensor_type.shape.dim, dim_value_proto_list) # 保存更新过的模型结构 onnx.save(model, "modified_rec_large.onnx") ``` 这段Python脚本展示了如何更改已有的ONNX模型输入层的尺寸信息,使之能够适应更广泛范围内的图像分辨率变化情况。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值