唠一唠对AI炼丹师的模型部署的探索

2023-11-23 05:59

本文主要是介绍唠一唠对AI炼丹师的模型部署的探索,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、内容介绍

这期内容是@走走大佬关于目标检测模型End to End推理方案的探索和尝试。其实说到推理和部署,其实怎么也绕不开ONNX,ONNX在成立的初衷就是希望解决神经网络在不同的训练框架、推理框架上的转换问题。 所以本期的内容会从如何玩转ONNX出发,唠一唠,我们在目标检测部署遇到的那些事情。因为篇幅以及有部分内容我不太了解不敢乱说的关系,我会在这里对开放麦的内容做一点顺序和内容上进行一点的调整,我也会加入自己的一些经历和看法,让大家看得更加轻松有趣一点。

2、ONNX是什么,如何生成ONNX(ONNX简要的介绍)?

预告:下面用三种方法向大家介绍如何生成Relu的ONNX模型,那么哪种方法才是最强的ONNX的生成方法呢?大家可以思考一下,我们继续往下看~

2.1、ONNX的组成

ONNX的静态图主要由「Node」(节点),「Input」(输入)和「initializer」(初始化器)但部分所组成的。

  • 节点就代表了神经网络模型一层的layer

  • 输入代表了输入矩阵的维度信息

  • 初始化器通常是存储权重/权值的。

  • 每个组件元素都是hierarchical的结构,都是有着相互依赖关系的;

  • 这是一个双向的链表。(Node、Graph彼此关联有相互关系的);

大家觉得难改,其实很大一部分也是因为ONNX的结构,边与边是一个稳定的结构关系,彼此很大程度上是相互依赖的。所以我们具体要怎么转化模型,怎么修改模型呢?我们接着看下去~

2.2、Pytorch导出ONNX模型

Pytorch是可以直接导出ONNX的模型,然后我们可以把导出的模型使用Netron的工具进行可视化工具。

Pytorch -> ONNX

2.3、Numpy出发,揉一个数据结构是可行吗?

ONNX可以在Pytorch,通过转换得到。那么我们假如我们不用Pytorch上的转换,从零开始直接用Numpy人手揉一个ONNX模型是可行的吗?答案是可行的。

ONNX是用protobuf数据格式进行保存的。而protobuf本身也是跨语言的可以支持C, C++, C#, Java, Javascript, Objective-C, PHP, Python, Ruby,使用ONN下的helper fuction就可以帮助我们顺利的完成这些跨语言的转变,所以Numpy也自然可以使用helper函数揉出输入、节点以及初始化权值。

根据上图展示的情况,可想而知要想实现一个能用的模型整体的代码量是非常恐怖的。单一个Relu结构的代码量就要比Pytorch的转化(最上面的图)实现要多将近三倍左右。(其实最大的代码量还是出现在输入的数据类型转化上)如果要实现一个完整的深度模型转化,工作量可想而知,所以我们有没有其他的更科学高效一点的做法呢?

2.4、ONNX GraphSurgeon Basics

如果我们从ONNX出发要修改ONNX,其实是一个比较复杂的过程。那自然我们就会思考,那如果直接ONNX转ONNX困难的化,能不能借助点工具,也就是有没有更好的IR(中间表达)来帮助修改ONNX模型呢?

没错「TensorRT」就已经做出来一套有效帮助Python用户修改ONNX的工具GraphSurgeon(图手术刀)

这款IR主要有三部分组成

  • Tensor——分为两个子类:变量和常量。

  • 节点——在图中定义一个操作。可以放任何的Python 原始类型(list、dict),也可以放Graph或者Tensor。

  • 图表——包含零个或多个节点和输入/输出张量。

目的就是为了更好的编辑ONNX

ONNX GraphSurgeon转化Relu结构

有了输入,再使用图手术刀对模型的结构进行组合,最后完成了Relu在ONNX上的转化。

3、如何在 ONNX 上进行图手术

因为ONNX本身是一种hierarchical的设计,这种其实就是一种经典的计算机思路。当我们打算动其中一层的时候,因为上下游的关联,下游的框架也会跟着被修改。

3.1、ONNX的IR,我们需要一个友好的中间表达!

比如在目标检测的场景中,我们有两种数据标注表达「txt」「mscoco」。如果是一个区分train集和val集的工作的话,txt直接把标签随机分开两组就行。但是在coco数据集上,如果需要划分val集的时候,就要对json格式进行划分,还需要遵循一个图片和标注信息一一对应的关系,就会更加复杂。那ONNX的转化也是同理,所以理论上为了简便这个整个修改的工程,我们需要一个IR工具的一个中间表达来帮助我们进行修改。

3.2、GraphSurgeon IR

提供了丰富的API来帮我们进行表达。

没有边的信息,边的信息存在了输入输出中,所以ONNX需要对模型的信息进行拓扑排序。平时的手,我们在使用Pytorch导出ONNX模型的时候会发现有孤立的节点。如果对这个模型进行拓扑排序的话,会发现这个孤立算子是没有意义的,应该是需要处理掉这个冗余的算子。

3.3、TorchScript (具体的使用)

首先Pytorch是一个动态图,我们需要把Pytorch转变为ONNX的静态图!

Torchscript模式主要分为Tracing和Script,区分是用「Tracing」还是「Script」,主要是看是否是动态流。

Tracing会从头到脚执行一遍,记录下来所有的函数

如果遇到动态控制流「(if-else)Script」 会走其中的一条,执行哪条就会记录哪条,另一条就会忽略。并且Script对不同大小的输入有效。

「一般都建议Trace,因为除了ONNX_runtime,别的都不会人if这个动态算子。」

3.4、Symbolic

某些情况下,帮助模型在端侧落地,在转换后也能够达到很好的效果。Python语言和c++本质上不一致,找到所以还是希望找到一种方式可以直接转换,不用自己再手动写C++算子,这算是一件很棒的事情。

NMS_F是一个很平常的一个算子,在上图的实现。如果我们用Symbolic的函数会直接转出,整个后处理都可以用ONNX转出来,但是这种方法

3.5、ONNX GraphSurgeon

如何把上面的结构转换为下面的结构,大概需要做到是吧x0的输入分支给去掉,然后再加入LeakyReLU和Identity的节点,最后完成输出。

  1. 先找到add的算子,把add的名字改成LeakyReLU

  2. 补充attribute属性,加入alpha

  3. 指定一个输出属性identuty_out

  4. 然后再把identity节点加入到结构当中

  5. 先clean一些,再进行拓扑排序。

操作的代码展示

这个任务其实也可以用ONNX原生的IR来做,但是原生IR没有太多的帮助函数,很多工具链还是不太完善的,所以还是建议使用ONNX GraphSurgeon,因为用原生的IR的代码量一页肯定是写不完的了。

3.6、torch.fx

因为这块没有听太懂,所以就直接简单的吹一些没啥用的,大家可以放松一下看看!

从以前的量化进化到现在也能涉及一部分的图手术。其实为了能够在python上也能进行图手术上,在symbolic tracer的底层上也做了很多不一样的工作,但是在转化过程中也是有很多坑的,但是因为Python-to-Python会更加有利于模型训练师的开发,Pytorch的工程师也正在继续发展,「正在逐步舍弃TorchScript」

利用torch.fx+ONNX做量化可以极大的节省代码量,是一个很棒的工作。

4、Focus模块替换(部署的技巧)

Focus在yolov5提出来的!

Focus包括了两部分组成「Space2Depth + Conv3」。有一点值得注意的是,Focus在实现过程focus_transform中会用到Slice的动态的操作,而这种动态的操作在部署的时候往往是会出大问题的。但是有意思的一点是,Space2Depth和Pytorch中的nn.PixelUnShuffle物理意义是一致的,但是实现的过程却有点不太相同,这也是这一版本YoloV5比较坑的点。

但是实现上一般有 CRD/DCR mode 方式, 由排列顺序决定, focus的实现跟这两种常用的mode 均不一致

「nn.PixelUnShuffle」是我们分割任务的老朋友了,在这里的出现,其更多的是在说明,其实下游任务正常逐步的进行一个统一和兼容。FPN到现在也转变为PAN,这样的转变也说明了很多。

仔细看看右边的Focus2的内容,其实只是一个reshape+conv+reshape的操作,这在虽然物理含义上是Space2Depth,但是与ONNX和Pytorch对应的实现都是不一致的。

mmdepoly有提供一系列的转换,可以帮助我们更好的解释这一点,大家可以看看。

在yolov5-6.0的时候已经没有人再使用Focus,这个操作也被替换成了一个6x6的卷积操作了。

再到现在6x6的卷积会转换为3x3的卷积拼接出来,这样会让整体的推理速度会更快。

4.1、Torch.FX对Focus进行替换

主要是用自己的卷积的实现替换focus_transform和Focus的实现。把中间层展开来看的,就可以发现还需要自己手写去补充buffer的算子。

一个比较新的图手术的方法,大家可以看一看,代码量也不是很大。

5、给目标检测网络插入EfficientNMS结构(如何做后处理会更加的高效!)

其实EfficientNMS是trt8.0的一个插件,以前是BatchedNMS,这个操作还没有手写的插件快。

下面就展开的讲讲EfficientNMS。

EfficientNMS原本是来自谷歌的EfficientDet 来的,能提速,而且与BatchedNMS一致,这么好用,我们为啥不用呢?

Yolo系列中,卷积后会加一个Box的解码,最后再加上NMS的操作。Box解码需要我们去重点的优化,如果想要在C++实现,就要自己手写一个实现。但是在我们的实现中,我们会更多的加速方法,这里就不展开说了。但是总的来说现在的新版本的Yolo都基本都固定了前处理跟NMS部分,卷积部分和编解码一直在变,不过现在也基本被RepVGG统治了。

大家也可以看看上面实现的yolov7后处理的方法。这是一个日本的一个项目实现出的一个整体的结构,我们其实也还有另一种方式可以用pytorch+onnx直接拼出来这样一个graph出来的。主要还是为了解决这种动态性,转化为静态去部署。

6、小小的概括一下

「EfficientNMS」该插件主要用于在 「TensorRT」 上与 「EfficientDet」 一起使用,因为这个网络对引入的延迟特别敏感较慢的 NMS 实现。 但是,该插件对于其他检测架构也足够的适用,例如 SSD 或Faster RCNN。

  1. 标准 NMS 模式:仅给出两个输入张量,

(1)边界框坐标和

(2)和每个Box的对应的分数。

  1. 融合盒解码器模式:给出三个输入张量,

(1)原始每个盒子的定位预测直接来自网络的定位头,

(2)相应的分类来自网络分类头的分数

(3)认锚框坐标通常硬编码为网络中的常数张量

7、项目的实验结果

这里的实验结果大家可以看一看,这里值得注意的是居然时间要比以前没有加操作的结构要快。其实主要原因是没有把后处理的时间给加上,显然这样的快就没有啥意义。大家要记得对比后处理的时间,如果不对比这样的比较是不公平的,也不具有啥意义!

8、总结

感觉这个笔记还是没有记录得很到位,因为有些信息确实也是我的盲区,但是整个讲解过程,其实巨棒,我这里小小一篇杂谈,其实还不足以记录这么多内容,建议大家去看看开放麦的录播,以及去了解YOLORT和MMDeploy的代码哦~!

https://link.zhihu.com/?target=https%3A//github.com/zhiqwang/yolov5-rt-stack

https://link.zhihu.com/?target=https%3A//github.com/open-mmlab/mmdeploy

这篇关于唠一唠对AI炼丹师的模型部署的探索的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/415869

相关文章

C++对象布局及多态实现探索之内存布局(整理的很多链接)

本文通过观察对象的内存布局,跟踪函数调用的汇编代码。分析了C++对象内存的布局情况,虚函数的执行方式,以及虚继承,等等 文章链接:http://dev.yesky.com/254/2191254.shtml      论C/C++函数间动态内存的传递 (2005-07-30)   当你涉及到C/C++的核心编程的时候,你会无止境地与内存管理打交道。 文章链接:http://dev.yesky

揭秘未来艺术:AI绘画工具全面介绍

📑前言 随着科技的飞速发展,人工智能(AI)已经逐渐渗透到我们生活的方方面面。在艺术创作领域,AI技术同样展现出了其独特的魅力。今天,我们就来一起探索这个神秘而引人入胜的领域,深入了解AI绘画工具的奥秘及其为艺术创作带来的革命性变革。 一、AI绘画工具的崛起 1.1 颠覆传统绘画模式 在过去,绘画是艺术家们通过手中的画笔,蘸取颜料,在画布上自由挥洒的创造性过程。然而,随着AI绘画工

一份LLM资源清单围观技术大佬的日常;手把手教你在美国搭建「百万卡」AI数据中心;为啥大模型做不好简单的数学计算? | ShowMeAI日报

👀日报&周刊合集 | 🎡ShowMeAI官网 | 🧡 点赞关注评论拜托啦! 1. 为啥大模型做不好简单的数学计算?从大模型高考数学成绩不及格说起 司南评测体系 OpenCompass 选取 7 个大模型 (6 个开源模型+ GPT-4o),组织参与了 2024 年高考「新课标I卷」的语文、数学、英语考试,然后由经验丰富的判卷老师评判得分。 结果如上图所

UnrealScriptIDE调试环境部署

先安装vs2010   再安装VSIsoShell.exe, 下载地址 https://pan.baidu.com/s/10kPNUuDGTbWXbz7Nos-1WA       fd3t   最后安装unside,下载地址 https://archive.codeplex.com/?p=uside  安装中间有一步选择Binary文件夹要选对路径。   安装好以后,启动 UDKDe

AI儿童绘本创作

之前分享过AI儿童绘画的项目,但是主要问题是角色一致要花费很长的时间! 今天发现了这款,非常奈斯! 只需输入故事主题、风格、模板,软件就会自动创作故事内容,自动生成插画配图,自动根据模板生成成品,测试效果如下图。 变现方式:生成儿童绘本发布到各平台,吸引宝妈群体进私域。  百度网盘 请输入提取码百度网盘为您提供文件的网络备份、同步和分享服务。空间大、速度快、安全

大语言模型(LLMs)能够进行推理和规划吗?

大语言模型(LLMs),基本上是经过强化训练的 n-gram 模型,它们在网络规模的语言语料库(实际上,可以说是我们文明的知识库)上进行了训练,展现出了一种超乎预期的语言行为,引发了我们的广泛关注。从训练和操作的角度来看,LLMs 可以被认为是一种巨大的、非真实的记忆库,相当于为我们所有人提供了一个外部的系统 1(见图 1)。然而,它们表面上的多功能性让许多研究者好奇,这些模型是否也能在通常需要系

探索蓝牙协议的奥秘:用ESP32实现高质量蓝牙音频传输

蓝牙(Bluetooth)是一种短距离无线通信技术,广泛应用于各种电子设备之间的数据传输。自1994年由爱立信公司首次提出以来,蓝牙技术已经经历了多个版本的更新和改进。本文将详细介绍蓝牙协议,并通过一个具体的项目——使用ESP32实现蓝牙音频传输,来展示蓝牙协议的实际应用及其优点。 蓝牙协议概述 蓝牙协议栈 蓝牙协议栈是蓝牙技术的核心,定义了蓝牙设备之间如何进行通信。蓝牙协议

人工和AI大语言模型成本对比 ai语音模型

这里既有AI,又有生活大道理,无数渺小的思考填满了一生。 上一专题搭建了一套GMM-HMM系统,来识别连续0123456789的英文语音。 但若不是仅针对数字,而是所有普通词汇,可能达到十几万个词,解码过程将非常复杂,识别结果组合太多,识别结果不会理想。因此只有声学模型是完全不够的,需要引入语言模型来约束识别结果。让“今天天气很好”的概率高于“今天天汽很好”的概率,得到声学模型概率高,又符合表达

智能客服到个人助理,国内AI大模型如何改变我们的生活?

引言 随着人工智能(AI)技术的高速发展,AI大模型越来越多地出现在我们的日常生活和工作中。国内的AI大模型在过去几年里取得了显著的进展,不少独创的技术点和实际应用令人瞩目。 那么,国内的AI大模型有哪些独创的技术点?它们在实际应用中又有哪些出色表现呢?此外,普通人又该如何利用这些大模型提升工作和生活的质量和效率呢?本文将为你一一解析。 一、国内AI大模型的独创技术点 多模态学习 多

探索Elastic Search:强大的开源搜索引擎,详解及使用

🎬 鸽芷咕:个人主页  🔥 个人专栏: 《C++干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 引入 全文搜索属于最常见的需求,开源的 Elasticsearch (以下简称 Elastic)是目前全文搜索引擎的首选,相信大家多多少少的都听说过它。它可以快速地储存、搜索和分析海量数据。就连维基百科、Stack Overflow、