模型转换案例学习:等效替换不支持算子

news2024/12/30 2:49:19

文章介绍

       Qualcomm Neural Processing SDK (以下简称SNPE)支持Caffe、ONNX、PyTorch和TensorFlow等不同ML框架的算子。对于某些特定的不支持的算子,我们介绍一种算子等效替换的方法来完成模型转换。本案例来源于https://github.com/quic/qidk/tree/master/Model-Enablement/Model-Conversion-Layer-Replacement

以PyTorch  MobilenetV3模型转换SNPE DLC的过程为例子,介绍如何使用等效算子替换的方法达成不支持算子的转换

前置条件

  • SNPE-2.7.x-PC上下载并设置好SNPE

相关步骤参考Snapdragon Neural Processing Engine SDK: SNPE Setup

  • python version 3.6.x and 3.8.x
  • Torch version 1.10
  • 安装pip install jupyter
  • 一台Linux机器
  • 高通Snapdragon 安卓手机,推荐Snapdragon® 8 Gen 2系列手机

特别注意:Qualcomm Neural Processing SDK需要python 3.6版本,型号repo需要python 3.8版本。因此,建议使用两个不同的虚拟环境。

操作步骤:

一、获取模型

1. 运行以下命令获取模型:

cd generatedModels

 wget https://download.pytorch.org/models/mobilenet_v3_large-8738ca79.pth

2. 现在,我们将使用MobileNetV3的Pytorch模型来获得ONNX模型。我们通常建议使用这种方法从pytorch模型生成dlc,方法是先转换为onnx,然后再转换为dlc。

运行getModel.py生成ONNX文件:
python getModel.py

cd ..

3. 这将生成ONNX模型可以在generatedModels/ONNX/文件夹中找到。

4. 现在,我们可以将ONNX模型转换为DLC

 

二、模型转换错误信息

1. 注意:在继续操作之前,请确保generatedModels/ONNX/mobilenet_v3.ONNX文件存在。

2. 使用Qualcomm Neural Processing SDK检查模型到dlc的转换

snpe-onnx-to-dlc -i generatedModels/ONNX/mobilenet_v3.onnx -o generatedModels/ONNX/mobilenet_v3.dlc

3. 以上,我们可以看到“onnx_hardsigmoid”转换没有注册,这里将用我们自己的自定义harsigmoid实现来更改。

三、替换架构-Harsigmoid

1. 找到模型源文件。

<python3.8-packages>/torchvision/models/mobilenetv3.py。

2. 搜索Hardsigmoid的调用/实现。

3. 对该行进行注释,并使用新的CustomHardsigmoid调用添加新的代码行。

4. 正如我们所看到的,Hardsigmoid是从nn模块调用为nn.Hardsigmoid。因此,我们找到<python3.8_path>/site packages/torch/nn/dir来编写我们自己的CustomHardsigmoid实现。

5. Hardsigmoid是一个激活函数。因此,它位于nn/modules/activation.py文件中。

6. 在__all__变量中添加``CustomHardsigmoid```,即要定义的自定义函数的名称。

7. 在nn/modules/activation.py中实现您自己的CustomHardsigmoid。注意:SDK没有nn.Hardsigmoid的转换。因此,我们将以与SDK兼容的方式定义Hardsigmoid。

Hardsigmoid可以表示为- torch.clamp((input*0.167+0.5),0,1)

8. 参考如下CustomHardsigmoid的实现代码

https://github.com/quic/qidk/blob/master/Model-Enablement/Model-Conversion-Layer-Replacement/class/CustomHardsigmoid.py

class CustomHardsigmoid(Module):

    __constants__ = ['inplace']

    inplace: bool

    def __init__(self, inplace : bool = False)->None:   

        super().__init__()

        self.inplace = inplace

    def forward(self, input: Tensor, inplace: bool = False) -> Tensor:

        return torch.clamp((input*0.167+0.5), 0, 1)

9. 我们已经定义了自己的实现,现在我们将查找nn.Hardsigmoid的所有依赖项

10. 在同一torc/nn/modules/目录中,在__init__.py文件中添加CustomHarsigmoid调用。然后保存后继续操作

11. 到MobileNetV3目录,并使用新实现的Customhardsigmoid层转储模型。

python generatedModels/getModel.py

 

四、再次转换,分析错误

1. 将具有新实现的CustomHardsigmoid层的ONNX模型转换为dlc

  snpe-onnx-to-dlc -i generatedModels/ONNX/mobilenet_v3.onnx -o generatedModels/ONNX/mobilenet_v3.dlc

Error :

2. 我们得到了一个新的框架错误,说“onnx_hadswish”转换没有注册,我们现在将来更改hardswish的实现。

五、替换架构-Hardswish

1. 找到模型源文件。

<python3.8-packages>/torchvision/models/mobilenetv3.py

2. 搜索Hardswish的调用/实现

Occurrence-1

Occurrence-2

Occurrence-3

Occurrence-4

3. 注释所有这些行,并使用新的CustomHardswish调用添加新的代码行。

4. 正如我们所看到的,Hardswish是从nn模块调用为nn.Hardswish的,因此,我们将到<python3.8_path>/site packages/torch/nn/目录来编写我们自己的CustomHardswish实现。

5. Hardswish是一个激活函数。因此,它位于nn/modules/activation.py文件中。

6. 在__all__变量中添加``CustomHardswish```,即要定义的自定义函数的名称。

7. 在nn/modules/activation.py中实现您自己的CustomHardswish。注意:SDK没有nn.Hardswish的转换。因此,我们将以与SDK兼容的方式定义Hardsigmoid。

Hardswish可以定义为一个简化的表达式- input*torch.clamp(input+3, min=0, max=6)/6

8. 参考CustomHardswish的实现代码

https://github.com/quic/qidk/blob/master/Model-Enablement/Model-Conversion-Layer-Replacement/class/CustomHardswish.py

class CustomHardswish(Module):

    __constants__ = ['inplace']

    inplace: bool

    def __init__(self, inplace : bool = False) -> None:

        super().__init__()

        self.inplace = inplace

    def forward(self, input: Tensor) -> Tensor:

        return input*torch.clamp(input+3, min=0,max=6)/6

9. 我们已经定义了自己的实现,现在我们将查找nn.Hardswish的所有依赖项。

10. 在同一torch/nn/modules/目录中,在__init.py文件中添加CustomHarswish调用,保存修改,继续下一步操作

11. 到MobileNetV3目录,并使用新实现的Customhardswish层转储模型。

   python generatedModels/getModel.py

 六、再次转换DLC

1. 将具有新实现的CustomHardswish以及CustomHardsigmoid层的ONNX模型转换为dlc

snpe-onnx-to-dlc -i generatedModels/ONNX/mobilenet_v3.onnx -o generatedModels/ONNX/mobilenet_v3.dlc

2. 现在,我们可以使用snpe-onx-to-dlc将ONNX模型转换为dlc。

最后我们完成了DLC模型的转换

作者:高通工程师,戴忠忠(Zhongzhong Dai)

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

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

相关文章

js谐音梗创意小游戏《望子成龙》

&#x1f33b; 前言 龙年到来&#xff0c;祥瑞满天。愿您如龙般矫健&#xff0c;事业腾飞&#xff1b;如龙鳞闪耀&#xff0c;生活美满。祝您龙年大吉&#xff0c;万事如意&#xff01; 龙年伊始&#xff0c;我给各位设计了一款原创的小游戏&#xff0c;话不多说&#xff0c;直…

D5020——外围元件少,内含压缩器和扩展器静噪电路,可应用在1.5V立体声耳机上,响应时间可调

D5020是一块增益可调 的压缩、扩展电路。它有两个通道组成&#xff0c;一个通道作扩展用&#xff0c;另一个通道能作压缩或扩展用。电路内部含有小信号全波整流、检测信号的大小&#xff0c;用于调节输入或反馈通道的增益大小。含有温度特性较好的带隙精密基准源&#xff0c;静…

Leetcode 11.盛水最多的容器

题目 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 说明&#xff1a;你不能倾斜容器。…

浏览器---浏览器/http相关面试题

1.localStorage和sessionStorage 共同点&#xff1a;二者都是以key-value的键值对方式存储在浏览器端&#xff0c;大小大概在5M。 区别&#xff1a; &#xff08;1&#xff09;数据有效期不同&#xff1a;sessionStorage仅在当前浏览器窗口关闭之前有效&#xff1b;localStorag…

C语言第二十八弹---整数在内存中的存储

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 目录 1、整数在内存中的存储 2、大小端字节序和字节序 2.1、什么是大小端&#xff1f; 2.2、为什么有大小端? 2.3、练习 2.3.1、练习1 2.3.2、练习2 2.…

安装SSH连接工具

连接Linux 1). 打开finalShell 2). 建立连接 Linux目录结构 在Linux系统中&#xff0c;也是存在目录的概念的&#xff0c;但是Linux的目录结构和Windows的目录结构是存在比较多的差异的 在Windows目录下&#xff0c;是一个一个的盘符(C盘、D盘、E盘)&#xff0c;目…

使用python构建Android,探索跨平台应用开发Kivy框架

使用python构建Android&#xff0c;探索跨平台应用开发Kivy框架 1. 介绍Kivy框架 Kivy是什么&#xff1f; Kivy是一个开源的Python跨平台应用程序开发框架&#xff0c;旨在帮助开发者快速构建创新的、可扩展的移动应用和多点触控应用。Kivy采用MIT许可证&#xff0c;允许开发…

java数据结构与算法刷题-----LeetCode102. 二叉树的层序遍历

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 1. 法一&#xff1a;广度优先遍历&#xff08;队列&#xff09; 解题思路…

嵌入式Qt 计算器核心算法_2

一.中缀表达式转后缀表达式 中缀表达式是最常用的算术表达式形式——运算符在运算数中间。但运算时需要考虑运算符优先级。 ​后缀表达式是计算机容易运算的表达式&#xff0c;运算符在运算数后面&#xff0c;从左到右进行运算,无需考虑优先级,运算呈线性结构。 1 2 * 3// …

django自定义后端过滤

​ DRF自带的过滤 第一个 DjangoFilterBackend 是需要安装三方库见[搜索&#xff1a;多字段筛选]两外两个是安装注册了rest_framework就有。 如上图&#xff0c;只要配置了三个箭头所指的方向&#xff0c;就能使用。 第一个单字段过滤 用户视图集中加上filterset_fields …

HarmonyOS—添加/删除Module

Module是应用/服务的基本功能单元&#xff0c;包含了源代码、资源文件、第三方库及应用/服务配置文件&#xff0c;每一个Module都可以独立进行编译和运行。一个HarmonyOS应用/服务通常会包含一个或多个Module&#xff0c;因此&#xff0c;可以在工程中创建多个Module&#xff0…

C++模板从入门到入土

1. 泛型编程 如果我们需要实现一个不同类型的交换函数&#xff0c;如果是学的C语言&#xff0c;你要交换哪些类型&#xff0c;不同的类型就需要重新写一个来实现&#xff0c;所以这是很麻烦的&#xff0c;虽然可以cv一下&#xff0c;有了模板就可以减轻负担。 下面写一个适…

Windows下搭建EFK实例

资源下载 elasticSearch &#xff1a;下载最新版本的就行 kibana filebeat&#xff1a;注意选择压缩包下载 更新elasticsearch.yml&#xff0c;默认端口9200&#xff1a; # Elasticsearch Configuration # # NOTE: Elasticsearch comes with reasonable defaults for most …

CSB ---> (XXE)XML基础

本来今天想更一下CSbeacon上线多层的内网机器的&#xff0c;但是刚好今天是年后的第一节课&#xff0c;讲的是XXE的基础&#xff0c;那就来先盘一下基础&#xff01;&#xff01; 1.XXE XXE全称是XML External Entity即xml外部实体注入攻击&#xff01;其后果会导致用户…

UE C++ 设置碰撞前 后事件 碰撞中事件

一.在Actor中声明碰撞BOX组件 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category "MySceneComponent")class UBoxComponent* MyBox; 在Actor以这样的形式实现代理绑定&#xff0c;在BeginPlay()里。 MyBox->OnComponentBeginOverlap.AddDynamic(); 转到…

《游戏引擎架构》--学习3

内存管理 优化动态内存分配 维持最低限度的堆分配&#xff0c;并且永不在紧凑循环中使用堆分配 容器 迭代器 Unicode

(C++) 详解内存地址空间

详解内存空间 0. 概述 一个C/C 程序&#xff0c;编译之后&#xff0c;形成的程序&#xff0c;在执行期间&#xff0c;内存中不仅存在一块区域用于存放代码&#xff0c;还有一些其他的区域用于使用&#xff0c;本节会详解C/C内部所使用的内存地址空间&#xff0c;关于各内存的…

Java下访问SQLServer 2008(低于2016)数据连接问题

环境&#xff1a;ubuntu20.04&#xff0c;tomcat&#xff0c;java 通过jdbc:sqlserver连接远程的SQLServer 2008R2数据库&#xff0c;2016版本之前仅支持TLS10&#xff0c;因此在连接时会出现如下错误&#xff0c; The driver could not establish a secure connection to SQ…

(二十二)Flask之上下文管理第三篇【收尾—讲一讲g】

目录&#xff1a; 每篇前言&#xff1a;g到底是什么&#xff1f;生命周期在请求周期内保持数据需要注意的是&#xff1a; 拓展—面向对象的私有字段深入讲解一下那句&#xff1a; 每篇前言&#xff1a; &#x1f3c6;&#x1f3c6;作者介绍&#xff1a;【孤寒者】—CSDN全栈领域…

Java项目:21 基于SSM实现的图书借阅管理系统

作者主页&#xff1a;舒克日记 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 基于SSM实现的图书借阅管理系统设计了两个角色&#xff0c;分别是管理员、用户&#xff0c;在数据表user中以ident字段区分&#xff0c;为1表示管理员…