TensorRT转换onnx的Transpose算子遇到的奇怪问题

近来把一个模型导出为onnx并用onnx simplifier化简后转换为TensorRT engine遇到非常奇怪的问题,在我们的网络中有多个检测头时,转换出来的engine的推理效果是正常的,当网络中只有一个检测头时,转换出来的engine的推理效果奇差,类别得分经sigmoid()计算出来的很多很大的值,导致输出上百万个3D box,这明显不正常。

开始以为3D box的C++后处理解码部分有问题,调查折腾了不少时间发现根本没什么大问题,然后想起模型只有一个检测头输出不正常,有多个头时检测头时反而正常,于是去仔细翻看模型网络的实现代码,也没发现什么不对的,很郁闷,想到把用于TensorRT生成engine的onnx可视化出来看有何差异,刚开始看也没发现什么特别的,感觉展示出来的结构都很正确没毛病啊:

那为何多个检测头就正常一个检测头就不行呢?再仔细看代码,发现heatmap这个分支的输出tensor在作permute(onnx里对应的是Transpose)后有这么一句有关:

      result['hm_preds'] =  torch.cat(hm_preds_list, dim=-1)

hm_preds_list是个list,当有多个head时,会有多个hm_preds加入到这个[ ]里,只有一个检测头时就只有一个hm_preds加入这个[ ]里,很显然,当hm_preds_list里只有一个hm_preds时,torch.cat()不会作实质操作,只是依据hm_preds_list里的数据直接输出tensor而已,那我强制只有一个检测头时也作和有多个检测头时一样的算子运算会如何?于是修改代码当网络只配置有一个检测头时,将这个hm_preds tensor自己和自己强制来个Concat,也就是相当于torch.cat([hm_preds, hm_preds], dim=-1),然后为保持输出tensort的维度不变进行了切片,得到的网络结果是这样:

然后导出onnx并用onnx simplifier化简,生成TensorRT engine后推理结果就正常了!

那为何强制加了Concat后输出结果就正常了呢?再回头看从pytorch导出onnx和onnx化简全过程中网络结构上的变化,发现上面有一个检测头和有多个检测头时的网络的onnx图,发现,只有一个检测头时,像上面提到,因为torch.cat()没有实质操作,pytorch导出onnx时虽然在onnx生成了Concat算子节点,但是后面用onnx simplifier化简时,它会把这个Concat算子节点删掉,Transpose算子的输出就直接作为网络的hm_preds输出了,而有多个检测头时,torch.cat()会有实质拼接操作,Concat算子自然被onnx simplifier保留了,所以生成的TensorRT engine的推理结果正常!

于是我修改脚本,当网络只有一个检测头时,在调用onnx simplifier化简网络后,在Transpose算子节点后和网络的输出节点hm_preds之间强制增加Concat算子节点(注意指定attrs={"axis":-1})

然后再生成TensorRT engine,然后用这个engine推理就一切正常了!

再回头仔细想想这个问题的最终原因,当只有一个检测头时,TensorRT在对hm_preds tensor 作Transpose后因为后续没有其他算子了,没有触发输出Transpose后的tensor值而是把原始tensor值输出了?或者因为Transpose输出的hm_preds tensor在加入hm_preds_list后,因为hm_preds_list不是tensor,TensorRT把它丢弃了,直接用的Transpose处理前的tensor值?只能等后面哪天有时间再实验找找根本原因。

附上增加Concat节点的相关代码(:

  hm_node = graph.outputs[1]check_node = hm_node.inputs[0]if check_node.op == 'Transpose':  # only one head, no concat, need to add it forciblytranspose_out = [gs.Variable("transpose_out", shape=hm_node.shape, dtype=hm_node.dtype)]check_node.outputs = transpose_outgraph.layer(name="Concat_199", op= 'Concat', inputs=transpose_out, outputs=[hm_node], attrs={"axis":-1})graph.cleanup().toposort()

我们修改onnx使用的NVIDIA的ONNX GraphSurgeon,它封装后用起来比较简单,感觉比直接使用onnx的API修改网络容易得多,具体文档和examples可参见:

ONNX GraphSurgeonicon-default.png?t=N7T8https://docs.nvidia.com/deeplearning/tensorrt/onnx-graphsurgeon/docs/index.html

 Examplesicon-default.png?t=N7T8https://github.com/NVIDIA/TensorRT/tree/main/tools/onnx-graphsurgeon/examples

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

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

相关文章

动态代理IP如何选择?

IP地址是由IP协议所提供的一种统一的地址格式,通过为每一个网络和每一台主机分配逻辑地址的方式来屏蔽物理地址的差异。根据IP地址的分配方式,IP可以分为动态IP与静态IP两种。对于大部分用户而言,日常使用的IP地址均为动态IP地址。从代理IP的…

LeetCode 0429.N 叉树的层序遍历:广度优先搜索(BFS)

【LetMeFly】429.N 叉树的层序遍历:广度优先搜索(BFS) 力扣题目链接:https://leetcode.cn/problems/n-ary-tree-level-order-traversal/ 给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)…

aiofiles:解锁异步文件操作的神器

aiofiles:解锁异步文件操作的神器 在Python的异步编程领域,文件操作一直是一个具有挑战性的任务。传统的文件操作函数在异步环境下无法发挥其最大的潜力,而aiofiles库应运而生。aiofiles是一个针对异步I/O操作的Python库,它简化了…

C#使用迭代器实现文字的动态效果

目录 一、涉及到的知识点 1.GDI 2.Thread类 3.使用IEnumerable()迭代器 二、实例 1.源码 2.生成效果: 一、涉及到的知识点 1.GDI GDI主要用于在窗体上绘制各种图形图像。 GDI的核心是Graphics类,该类表示GDI绘图表面,它提供将对象绘制…

不等式的证明之二

不等式的证明之二 证明下述不等式证法一证法二证法二的补充 证明下述不等式 设 a , b , c a,b,c a,b,c 是正实数,请证明下述不等式: 11 a 5 a 6 b 11 b 5 b 6 c 11 c 5 c 6 a ≤ 3 \begin{align} \sqrt{\frac{11a}{5a6b}}\sqrt{\frac{11b}{5b6c}…

leetcode hot100不同路径

本题可以采用动态规划来解决。还是按照五部曲来做 确定dp数组:dp[i][j]表示走到(i,j)有多少种路径 确定递推公式:我们这里,只有两个移动方向,比如说我移动到(i,j&#x…

STM32 寄存器操作 systick 滴答定时器 与中断

一、什么是 SysTick SysTick—系统定时器是属于CM3内核中的一个外设,内嵌在NVIC中。系统定时器是一个24bit的向下递减的计数器, 计数器每计数一次的时间为1/SYSCLK,一般我们设置系统时钟SYSCLK等于72M。当重装载数值寄存器的值递减到0的时候…

python学习(三):pip安装及如何加速安装第三方组件

pip全称Package Installer for Python,即用来安装第三方组件的工具 一.安装pip Python3中setuptools、Pip安装详解 1、安装setuptools 命令如下: wget --no-check-certificate https://pypi.python.org/packages/source/s/setuptools/setuptools-19.…

C语言—指针

碎碎念:做指针题的时候我仿佛回到了原点&#xff0c;总觉得目的是为了把框架搭建起来&#xff0c;我胡说的哈31 1.利用指针变量将一个数组中的数据反向输出。 /*1.利用指针变量将一个数组中的数据反向输出。*/#include <stdio.h> #include <time.h> #include <…

phpstrom创建thinkphp项目

安装php和composer 参考 安装phpstrom 创建项目 查看thinkphp版本 https://packagist.org/packages/topthink/think 打开所在项目编辑配置 即可调试运行

二维码的颜色怎么改变?轻松3步修改二维码样式

怎么修改二维码的颜色呢&#xff1f;一般我们制作的二维码或者经过系统生成的二维码大多都是黑白颜色的&#xff0c;有些小伙伴会觉得不太美观无法满足自己的使用需求。那么对于想要修改二维码样式的小伙伴&#xff0c;可以使用二维码生成器的二维码美化功能来处理&#xff0c;…

07 按键控制 LED

按键简介 按键开关是一种电子开关&#xff0c;属于电子元器件类。常见的按键开关有两种&#xff0c;第一种是轻触式按键开关&#xff08;简称轻触开关&#xff09;&#xff0c;使用时以向开关的操作方向施加压力使内部电路闭合接通&#xff0c;当撤销压力时开关断开&#xff0…

git分布式版本控制工具基本操作

Windows操作 1.1 git基本操作 1.设置用户签名 git config user.name xx git config user.email xxb163.com2.初始化本地库 git init3.查看本地库状态 git status4.添加暂存区 git add 文件名称 git add *5.提交本地库 git commit -m "描述信息" 文件6.查看版本…

《富爸爸:巴比伦最富有的人》读书笔记

目录 作者简介 感悟 经典摘录 观点&#xff1a; 支付给自己(理解是投资自己) 观点&#xff1a;源源不断地放入金币 观点&#xff1a; 把收入的一部分留给我自己 观点&#xff1a; 从专业的人士得到建议 观点&#xff1a;一旦为自己规定了任务&#xff0c;就一定要完成 …

微波炉维修笔记

微波主要是靠2.45GHz 左右的微波(12.2cm 波长)加热水分子实现食物加热 所有不要使用金属器皿进行加热&#xff0c;要么因为电磁屏蔽&#xff0c;起不到加热效果&#xff0c;要么火光四射 微波炉基本组成 借鉴姜师傅的视频 碰到不加热其它都正常的问题 1.检查高压电容 使用万…

自动驾驶中的 DCU、MCU、MPU、SOC 和汽车电子架构

自动驾驶中的 DCU、MCU、MPU 1. 分布式电子电气架构2. 域集中电子电气架构架构2.1 通用硬件定义 3. 车辆集中电子电气架构4. ADAS/AD系统方案演变进程梳理4.1 L0-L2级别的ADAS方案4.2 L2以上级别的ADAS方案 5. MCU和MPU区别5.1 MCU和MPU的区别5.2 CPU与SoC的区别5.3 举个例子 R…

【STM32】软件SPI读写W25Q64芯片

目录 W25Q64模块 W25Q64芯片简介 硬件电路 W25Q64框图 Flash操作注意事项 状态寄存器 ​编辑 指令集 INSTRUCTIONS​编辑 ​编辑 SPI读写W25Q64代码 硬件接线图 MySPI.c MySPI.h W25Q64 W25Q64.c W25Q64.h main.c 测试 SPI通信&#xff08;W25Q64芯片简介&am…

说说对BOM的理解(常见的BOM对象了解哪些)

文章目录 一、是什么二、window三、location四、navigator五、screen六、history 一、是什么 BOM (Browser Object Model)&#xff0c;浏览器对象模型&#xff0c;提供了独立于内容与浏览器窗口进行交互的对象 其作用就是跟浏览器做一些交互效果,比如如何进行页面的后退&…

四川盐亭清代古寨重现,文物建筑保护引关注

近日&#xff0c;在四川盐亭的五台山深处&#xff0c;一处历经160余年风霜的古山寨遗迹重现天日。寨门巍峨&#xff0c;文字斑驳&#xff0c;诉说着清代同治年间的历史沧桑。然而&#xff0c;岁月侵蚀下&#xff0c;文物保护刻不容缓。温湿度波动等自然因素&#xff0c;对这些珍…

森林气象火险监测站

TH-SL10在广袤无垠的森林中&#xff0c;每一片树叶、每一缕风都蕴含着大自然的秘密。而在这片生机勃勃的绿色世界里&#xff0c;森林气象火险监测站就像是守护宝藏的“千里眼”和“顺风耳”&#xff0c;时刻警惕着潜在的危险。 一、森林气象火险监测站&#xff1a;实时监测的“…