MobileViT v2导出onnx模型时遇Col2Im算子无法导出问题

news2024/11/16 12:38:08

相关error log索引

  • onnxruntime.capi.onnxruntime_pybind11_state.InvalidGraph: [ONNXRuntimeError] : 10 : INVALID_GRAPH : This is an invalid model. In Node, ("/classifier/classifier.0/ReduceMean", ReduceMean, "", -1) : ("/layer_5/layer_5.1/conv_proj/block/conv/Conv_output_0": tensor(float),) -> ("/classifier/classifier.0/ReduceMean_output_0",) , Error Unrecognized attribute: axes for operator ReduceMean
  • torch.onnx.errors.CheckerError: Unrecognized attribute: axes for operator ReduceMean
  • Context: Bad node spec for node. Name: /classifier/classifier.0/ReduceMean OpType: ReduceMean
  •     num_dimensional_axis = symbolic_helper._get_tensor_sizes(output_size)[0]
    TypeError: 'NoneType' object is not subscriptable 
    (Occurred when translating col2im)
  •     raise ValueError(f"Unsupported ONNX opset version: {value}")
    ValueError: Unsupported ONNX opset version: 18
  • torch.onnx.errors.UnsupportedOperatorError: Exporting the operator 'aten::col2im' to ONNX opset version 13 is not supported. Please feel free to request support or submit a pull request on PyTorch GitHub: https://github.com/pytorch/pytorch/issues
  • torch.onnx.errors.CheckerError: Unrecognized attribute: axes for operator ReduceMean

    ==> Context: Bad node spec for node. Name: /classifier/classifier.0/ReduceMean OpType: ReduceMean

1. 初始导出

原始模型直接导出(opset version配置版本为13),插入脚本如下:

    input = torch.randn((1, 3, 224, 224))
    torch.onnx.export(model, input, "weights/mobilevitv2-2.0_opset13.onnx", input_names=["input"], output_names=["output"], verbose=True, opset_version=13)

遇到error如下:

Log提示由于网络结构中存在col2im算子,而ONNX opset version 13不支持该算子,直到opset version 18才支持。故将torch.onnx.export()中opset_version设为18。

2. 配置opset 18选项

    input = torch.randn((1, 3, 224, 224))
    torch.onnx.export(model, input, "weights/mobilevitv2-2.0_opset18.onnx", input_names=["input"], output_names=["output"], verbose=True, opset_version=18)

执行后出现错误如下:

从log可以看出,该错误的原因为当前torch版本不支持导出opset version 18,故需升级torch。

3. 升级torch

我们将所有torch相关依赖包均升级为最高版本

再次执行推理导出,结果仍然报错,错误log如下:

4. 固定输出维度

经google搜索issue后确定,torch.onnx.export不支持动态输入目标shape的col2im算子导出,故我们找到对应Col2Im算子对应前向推理部分,如下:

其中F.fold()函数即为torch端的Col2Im算子,前面不支持导出的变长输入实为output_size,经debug得出output_size共存在三种输入分别为(28,28)、(14,14)以及(8,8),故我们只需要利用if else将其改为固定输入即可,修改如下:

修改脚本后再次执行即可正常导出opset version 18的onnx模型,对应的Col2Im算子如下图

虽然在导出时log中显示ReduceMean的错误(如下图),但onnx模型已经被保存出。

重点信息与ReduceMean的属性axes有关,详细解决请看第5点。

5. 推理错误

导出模型后,我们调用onnxruntime进行推理,出现如下报错:

简单看,就是网络中的ReduceMean算子有个属性axes是未识别的。查阅onnx官方资料可知,在opset=13时,用于决定ReduceMean计算轴的axes被安排在Attribute中,而opset=18则需放在节点node的input中。如下图:

所以,怀疑就是torch.onnx.export在导出onnx时,可能存在内置的bug,导致ReduceMean在转出时还是沿用了旧方案,将axes仍然放置在ATTRIBUTES(属性配置)中,经过检查刚导出的onnx模型,果然发现此问题,如下图:

所以,我们通过python脚本读入原始onnx模型,手动调整axes位置,调用onnx.helper.make_tensor新建axes tensor添置在ReduceMean算子的INPUTS中,即可正常运行。此处提供一份手动修改脚本,供参考,如下:

import onnx
from onnx import TensorProto

onnx_model = onnx.load_model("./weights/mobilevitv2-2.0_opset18.onnx")
for node in onnx_model.graph.node:
    if node.op_type == 'ReduceMean':
        for idx, cur_attr in enumerate(node.attribute):
            if cur_attr.name == 'axes':
                del node.attribute[idx]                                     
                ### 删除原始attribute中的axes
                break
        input_tensor = onnx.helper.make_tensor(name=node.name+'_axes',
                                               data_type=TensorProto.INT64,
                                               dims=[2],
                                               vals=[-2, -1])               
        ### 创建一个存放axes的tensor
        onnx_model.graph.initializer.append(input_tensor)                   
        ### 将新创建的axes tensor添加到onnx模型initializer proto结构中
        node.input.append(input_tensor.name)                                
        ### 将axes tensor的name加入到ReduceMean算子的input中
        break
onnx.save_model(onnx_model, "./weights/mobilevitv2-2.0_opset18_repair_reducemean.onnx")

另外,调用onnxruntime的通用推理脚本,请参考我的github工程(觉得好用,请帮忙点star),工程地址:https://github.com/xncaffe/caffe_convert_onnx ,按教程安装依赖包后即可使用onnx_inference.py进行推理。

6. 后续方案

        虽然通过前面的方法正常导出了opset version为18的onnx模型,但是由于市面上很多移动平台并不支持opset version为18的版本,而降级opset会带来很大的工作量且不会得到onnx官方的支持。那怎么样才能不改变模型结构,正常导出任何版本opset的onnx模型呢?

为此,我们分析了此模型中Col2Im的作用,其实就是做了维度转换,刚好是此网络前端的Gather部分的逆运算,每个Col2Im都与一组Gather+Transpose对应。如上图。所以,该过程其实可以完全使用Reshape和Transpose算子组合代替。故我们修改前向,使用reshape+permute组合替代前述的F.fold流程,修改后脚本如下:

修改后即可随意导处任何opset版本的onnx模型,而对应Col2Im在onnx模型被显示如下:

导出的opset=13的onnx和前述的使用Col2Im opset=18的onnx模型,调用onnx_inference.py推理后发现,结果完全一致,证明我们的推理完全正确,如下图:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1077330.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

hive3.1核心源码思路

系列文章目录 大数据主要组件核心源码解析 文章目录 系列文章目录大数据主要组件核心源码解析 前言一、HQL转化为MR 核心思路二、核心代码1. 入口类,生命线2. 编译代码3. 执行代码 总结 前言 提示:这里可以添加本文要记录的大概内容: 对大…

UUID和雪花(Snowflake)算法该如何选择?

博主简介:不写代码没饭吃,一名全栈领域的创作者,专注于研究互联网产品的解决方案和技术。熟悉云原生、微服务架构,分享一些项目实战经验以及前沿技术的见解。关注我们的主页,探索全栈开发,期待与您一起在移…

嵌入式养成计划-38----C++--匿名对象--友元--常成员函数和常对象--运算符重载

八十七、匿名对象 概念&#xff1a;没有名字对象格式 &#xff1a;类名&#xff08;&#xff09;;作用 用匿名对象给有名对象初始化的用匿名对象给对象数组初始化的匿名对象作为函数实参使用 示例 : #include <iostream> using namespace std; class Dog { private:s…

小程序如何设置各种时间参数

在小程序管理员后台->基本设置处&#xff0c;可以设置各种时间。例如待支付提醒时间、待支付取消时间、自动发货时间、自动收货时间、自动评价时间等等。下面具体解释一下各个时间的意思。 1. 待支付提醒时间&#xff1a;在用户下单后&#xff0c;如果一段时间内没有完成支付…

IDEA的使用(一)代码模块的导入、快捷使用、自定义 (IntelliJ IDEA 2022.1.3版本)

目录 1. IDEA项目结构 2. 模块的导入操作 2.1 正规操作 2.2 取巧操作 2.3 出现乱码 2.4 模块改名 3. 代码模板的使用 后缀补全&#xff08;Postfix Completion&#xff09;、实时模板&#xff08;Live Templates&#xff09;菜单里面什么介绍都有&#xff0c;可以自学&a…

C#(Csharp)我的基础教程(四)(我的菜鸟教程笔记)-Windows项目结构分析、UI设计和综合事件应用的探究与学习

目录 windows项目是我们.NET学习一开始必备的内容。 1、窗体类&#xff08;主代码文件窗体设计器后台代码文件&#xff09; 主窗体对象的创建&#xff1a;在Program类里面&#xff1a; Application.Run(new FrmMain());这句代码就决定了&#xff0c;当前窗体是项目的主窗体。…

Python Opencv实践 - 车辆识别(1)读取视频,移除背景,做预处理

示例中的图像的腐蚀、膨胀和闭运算等需要根据具体视频进行实验得到最佳效果。代码仅供参考。 import cv2 as cv import numpy as np#读取视频文件 video cv.VideoCapture("../../SampleVideos/Traffic.mp4") FPS 10 DELAY int(1000 / FPS) kernel cv.getStructu…

Python数据容器——字典的常用操作(增、删、改、查)

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 本文专栏&#xff1a;Python专栏 专栏介绍&#xff1a;本专栏为免费专栏&#xff0c;并且会持续更新python基础知识&#xff0c;欢迎各位订阅关注. 目录 一、理解字典 1. Python字典是什么&#xff1f; 2. 字…

隆重宣布:.NET 8 RC1 现已推出

作者&#xff1a;Leslie Richardson 排版&#xff1a;Alan Wang .NET 8 RC1 现已推出。这是我们两个候选版本中的第一个。此版本包括适用于 Android 和 WASM 的新 AOT 模式、System.Text.Json 改进以及对容器的 Azure Managed Identity 支持。如果您还没有开始学习和测试 .NET …

基于Java+SpringBoot+Vue民宿管理系统的设计与实现 前后端分离【Java毕业设计·文档报告·代码讲解·安装调试】

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

android Google官网 :支持不同的语言和文化 rtl / ltr : 本地化适配:RTL(right-to-left) 适配

参考 google官网&#xff1a; 支持不同的语言和文化 应用包含可能专门针对特定文化而设计的资源。例如&#xff0c;应用可以包含针对特定文化的字符串&#xff0c;这些字符串将转换为当前语言区域的语言。 将具有文化特异性的资源与应用的其他资源分开是一种很好的做法。And…

Apache Doris 数据建模之 Aggregate Key 模型

了解 Doris 数据模型对于我们使用 Doris 来解决我们业务问题非常重要&#xff0c;这个系列我们将详细介绍 Doris 的三种数据模型及 Doris 数据分区分桶的一些策略&#xff0c;帮助用户更好的使用 Doris 。 这个系列我会讲解 Doris 的三种数据模型及在这三种数据模型之上的 Rol…

算法练习11——买卖股票的最佳时机 II

122. 买卖股票的最佳时机 II 给你一个整数数组 prices &#xff0c;其中 prices[i] 表示某支股票第 i 天的价格。 在每一天&#xff0c;你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买&#xff0c;然后在 同一天 出售。 返回 你能获得…

【移植代码】matlab.engine报错、numpy+mkl安装、Qt platform plugin报错总结

文章目录 numpy报错numpy安装PyQt5报错matlab.engine无法加载确认配置版本进行配置 matlab文件路径缺失vscode无法debug3.7以下版本总结 今天的任务是复现师姐的代码&#xff0c;代码在服务器的环境下可以跑&#xff0c;而我要做的&#xff0c;就是将环境和源码配置好&#xff…

Python库学习(九):Numpy[续篇三]:数组运算

NumPy是用于数值计算的强大工具&#xff0c;提供了许多数组运算和数学函数&#xff0c;允许你执行各种操作&#xff0c;包括基本运算、统计计算、线性代数、元素级操作等 1.基本运算 1.1 四则运算 NumPy数组支持基本的四则运算&#xff08;加法、减法、乘法和除法&#xff09;…

mysql面试题31:一条SQL语句在MySQL中如何执行的

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:一条SQL语句在MySQL中如何执行的 以下是一条SQL语句在MySQL中的详细执行步骤: 语法分析:MySQL首先对SQL语句进行语法分析,检查SQL语句是否符合…

算法题:分发饼干(典型的贪心算法问题)

这个题目是一个典型的贪心算法问题&#xff0c;解决思路是排序双指针贪心法&#xff0c;先将两个数组分别排序&#xff0c;优先满足最小胃口的孩子。&#xff08;本题完整题目附在了最后面&#xff09; 代码如下&#xff1a; class Solution(object):def findContentChildren(…

如何使用 ONLYOFFICE API 转换办公文档格式

作者&#xff1a;天哥 上一期我们介绍了 ONLYOFFICE 的文档生成器API接口函数库。这一期我们继续介绍ONLYOFFICE 的文件转换API接口函数库。 为什么要使用 ONLYOFFICE 转换API ONLYOFFICE 转换 API 有助于转换大部分类型的Office文档&#xff1a;文本、表格、幻灯片、表单、P…

Visual Studio 2022新建项目时没有ASP.NET项目

一、Visual Studio 2022新建项目时没有ASP.NET项目 1、打开VS开发工具&#xff0c;选择工具菜单&#xff0c;点击“获取工具和功能” 2、选择“ASP.NET和Web开发”和把其他项目模板&#xff08;早期版本&#xff09;勾选上安装即可

C/C++实现简单高并发http服务器

基础知识 html&#xff0c;全称为html markup language&#xff0c;超文本标记语言。 http&#xff0c;全称hyper text transfer protocol&#xff0c;超文本传输协议。用于从万维网&#xff08;WWW&#xff1a;World Wide Web&#xff09;服务器传输超文本到本地浏览器的传送…