ONNX模型的量化

news2024/11/27 4:26:43

我们都希望从代码中榨取更多的性能,对吧?

在现代,充斥着需要大量计算资源的复杂机器学习算法,因此,榨取每一点性能至关重要。

传统上,机器学习算法是在具有支持大量并行计算能力的 GPU 上进行训练的。但是,当部署我们训练过的模型进行推理时,将所有东西都部署在能够访问这种高端 GPU 的机器上是不切实际的

NSDT工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎 - Three.js虚拟轴心开发包 - 3D模型在线减面 - STL模型在线切割 

1、实际示例

让我们举一个例子来更好地理解我们正在解决的问题。

假设我们正在为神经机器翻译做一个机器学习组件。虽然你可以用任何机器学习模型来做到这一点,但我们以谷歌的 T5模型为例。

这是一个文本到文本的转换模型,在大型语料库上进行训练以完成多项任务。

Google T5 多任务图

执行此任务的示例代码如下所示:

from transformers import T5Tokenizer, T5ForConditionalGeneration, pipeline

tokenizer = T5Tokenizer.from_pretrained("t5-small")
model = T5ForConditionalGeneration.from_pretrained("t5-small")
pipe = pipeline(
	task='text2text-generation', 
    model=model, 
    tokenizer = tokenizer)
print(pipe('Translate English to French: Hi, How are you ?')) 

# Output: [{'generated_text': 'Bonjour, Comment êtes-vous ?'}]
  • 首先,我们从 transformers 包中导入所有必要的类和函数
  • 然后我们实例化 tokenizer 和模型
  • 我们将 tokenizer 和模型传递给管道辅助函数,
  • 从高层次上讲,transformer 架构可以分为两半:编码器和解码器。
  • 我们将文本输入句子转换为各自的 token 表示,并将这些 token 提供给 T5 模型的编码器部分,然后这些输出被提供给解码器部分,最后我们使用相同的 tokenizer 将输出 token 转换回其文本表示。
  • 所有上述复杂性都很好地包装在我们上面使用的管道函数中

现在,让我们来测量此代码的性能:

from transformers import T5Tokenizer, T5ForConditionalGeneration, pipeline
from timeit import timeit

tokenizer = T5Tokenizer.from_pretrained("t5-small")
model = T5ForConditionalGeneration.from_pretrained("t5-small")
pipe = pipeline(task='text2text-generation', model=model, tokenizer = tokenizer)

globals = dict(map(
    lambda x: (x, eval(x)),
    dir()
))

time_taken = timeit(
    globals = globals,
    number = 5,
    stmt="pipe('Translate English to French: Hi, How are you ?')",
)

print(f"It took about {time_taken} seconds")

我们使用 Python 内置的 time-it 模块来测量代码翻译所需的时间,并重复 5 次以获得平均估计值。

因为我们没有使用任何 GPU 进行推理,所以这些数字肯定取决于机器的原始 CPU 能力。但是我们仍然可以提取相对测量值。

(venv-meta) tarun@Taruns-MacBook-Pro ML % /Users/tarun/ML/venv-meta/bin/python /Users/tarun/ML/
t5_torch.py
It took about 0.4970941249999996 seconds

大约需要 0.5 秒

现在让我们检查一下内存使用情况

from memory_profiler import profile

from transformers import T5Tokenizer, T5ForConditionalGeneration, pipeline
from timeit import timeit

tokenizer = T5Tokenizer.from_pretrained("t5-small")
model = T5ForConditionalGeneration.from_pretrained("t5-small")
pipe = pipeline(task='text2text-generation', model=model, tokenizer = tokenizer)

@profile
def perform_inference():
    return pipe('Translate English to French: Hi, How are you ?')

if __name__ == '__main__':
    perform_inference()

运行脚本我们会发现以下结果:

(venv-meta) tarun@Taruns-MacBook-Pro ML % python -m memory_profiler t5_torch_memory_profile.py
Filename: t5_torch_memory_profile.py
Line #    Mem usage    Increment  Occurrences   Line Contents
=============================================================
    10    847.9 MiB    847.9 MiB           1   @profile
    11                                         def perform_inference():
    12    859.2 MiB     11.3 MiB           1       return pipe('Translate English to French: Hi, How are you ?')

我们可以看到,推理任务需要大约 11MB 的内存

虽然这些数字在功能强大的计算机上还不错,但在低功耗移动设备上可能会更加昂贵,如果有一种方法可以让这些模型的部署成本降低很多计算要求,并且执行速度更快,同时基本保持其准确性,那会怎样呢?

2、了解 ONNX

ONNX 代表开放神经网络交换,它是一种由微软研究院开发的开源技术,用于帮助加速跨框架和语言的机器学习推理。

ONNX 的好处在于它是跨平台和跨语言的。

这意味着你可以将机器学习导出为 ONNX 格式,并且可以用你喜欢的任何语言使用它们。

除此之外,ONNX 还具有许多内置优化功能,可以利用现代硬件级功能来加速推理。

让我们从将模型导出到 ONNX 表示开始。

将 transformer 模型导出为 ONNX 运行时等效项的官方方法是使用optimum。

运行以下命令执行导出:

(venv-meta) tarun@Taruns-MacBook-Pro ML % optimum-cli export onnx \
--model t5-small \
--optimize O3 \
t5_small_onnx

在上面的命令中,我们使用 optimum-cli ,它是 optimal 库的命令行包装器。

我们首先指定要导出的模型,然后指定 ONNX 应该进行的优化级别。

但我们还没有完成,我们可以做得更好!

3、量化ONNX模型

如果我说我对某个结果的确定性为 85.90123456789%,而对同一结果的确定性为 85.88%,这里的小数精度会有所不同吗?

可能不会,这就是量化对机器学习模型的作用。

当我们训练这些模型时,我们通常使用更高的精度来训练它们,例如使用高达 64 位的浮点精度。

但在实践中,我们可以根据我们的偏好将这个精度降低到 32 位、16 位甚至 8 位。

量化是降低权重、偏差和激活的精度的过程,这样它们消耗的内存更少,运行速度更快!

为了量化我们新导出的模型,让我们再次运行 optimal-cli:

(venv-meta) tarun@Taruns-MacBook-Pro ML % optimum-cli onnxruntime \
quantize \
--onnx_model t5_onnx_small \
--arm64 \
--output t5_onnx_small_quantized

...

Saving quantized model at: t5_onnx_small_quantized (external data format: False)
Configuration saved in t5_onnx_small_quantized/ort_config.json
Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.
Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.

现在我们已经准备好了量化模型。让我们再次检查一下时间消耗:

from optimum.pipelines import pipeline
from transformers import T5Tokenizer
from optimum.onnxruntime import ORTModelForSeq2SeqLM
from timeit import timeit

model = ORTModelForSeq2SeqLM.from_pretrained('t5_onnx_small_quantized')
tokenizer = T5Tokenizer.from_pretrained('t5-small')
pipe = pipeline(task='text2text-generation',model=model, tokenizer=tokenizer)

globals = dict(map(
    lambda x: (x, eval(x)),
    dir()
))

time_taken = timeit(
    globals = globals,
    number = 5,
    stmt="pipe('Translate English to French: Hi, How are you ?')",
)

print(f"It took about {time_taken} seconds")

我们可以看到,我们的逻辑大部分保持不变,唯一的变化是,我们不再加载由 PyTorch 支持的 hugging face transformers T5 模型,而是加载来自 optimal.onnxruntime 的 ONNX 等效模型。

(venv-meta) tarun@Taruns-MacBook-Pro ML % /Users/tarun/ML/venv-meta/bin/python /Users/tarun/ML/
t5_onnx.py
It took about 0.09925400000000018 seconds

只需很少的代码改动,性能就能提升 5 倍。

同样,让我们​​看看内存方面的表现如何:

from memory_profiler import profile
from optimum.pipelines import pipeline
from transformers import T5Tokenizer
from optimum.onnxruntime import ORTModelForSeq2SeqLM

model = ORTModelForSeq2SeqLM.from_pretrained('t5_onnx_small_quantized')
tokenizer = T5Tokenizer.from_pretrained('t5-small')
pipe = pipeline(task='text2text-generation',model=model, tokenizer=tokenizer)

@profile
def perform_inference():
    return pipe('Translate English to French: Hi, How are you ?')

if __name__ == '__main__':
    perform_inference()

除模型初始化部分外,代码再次看起来大致相似:

(venv-meta) tarun@Taruns-MacBook-Pro ML % python -m memory_profiler t5_onnx_quantized_memory_profile.py
Line #    Mem usage    Increment  Occurrences   Line Contents
=============================================================
    10    933.9 MiB    933.9 MiB           1   @profile
    11                                         def perform_inference():
    12    938.7 MiB      4.9 MiB           1       return pipe('Translate English to French: Hi, How are you ?')

我们可以清楚地看到,我们最终消耗的内存少了很多。事实上,它的内存消耗比以前少了近 2.2 倍。正如一位聪明的程序员曾经说过的:

“当谈到扩展时,优化就是游戏的名称”😎

这个故事的所有代码示例都可以在我的 github 页面上找到。


原文链接:ONNX 模型的量化 - BimAnt

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

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

相关文章

WordPress建站:如何使用ChemiCloud搭建外贸独立站

以前自行搭建一个网站,不懂一点技术那是很难完成的,现如今WordPress的出现极大地降低了搭建网站的技术门槛,不需要懂任何代码,只需按步骤操作就行。WordPress 是一个非常流行的开源内容管理系统(CMS)&#…

职业教育计算机网络综合实验实训室建设应用案例

近年来,职业教育在培养技能型人才方面发挥着越来越重要的作用。然而,传统的计算机网络技术教学模式往往重理论、轻实践,导致学生缺乏实际操作能力和职业竞争力。为了改变这一现状,唯众结合职业教育特点,提出了“教、学…

Kubeflow v1.7.0 创建新用户

文章目录 为新用户创建配置文件配置用户密码重启auth生效 为新用户创建配置文件 apiVersion: kubeflow.org/v1beta1 kind: Profile metadata:name: kubeflow-cyw-example-com # replace with the name of profile you want, this will be users namespace name spec:owner:k…

STC单片机UART映射printf

文章目录 使用STC-ISP生成UART初始化函数 增加如下函数&#xff0c;注意使用printf函数需要添加 #include <stdio.h> 头文件 #include <stdio.h>void Uart1_Init(void) //9600bps12.000MHz {SCON 0x50; //8位数据,可变波特率AUXR | 0x01; //串口1选择定时器2为…

【Spring】——Spring概述、IOC、IOC创建对象的方式、Spring配置、依赖注入(DI)以及自动装配知识

&#x1f3bc;个人主页&#xff1a;【Y小夜】 &#x1f60e;作者简介&#xff1a;一位双非学校的大二学生&#xff0c;编程爱好者&#xff0c; 专注于基础和实战分享&#xff0c;欢迎私信咨询&#xff01; &#x1f386;入门专栏&#xff1a;&#x1f387;【MySQL&#xff0…

LeetCode 101.对称二叉树 C写法

LeetCode 101.对称二叉树 C写法 思路&#xff1a; 将该树一分为二&#xff0c;左子树的左边与右子树的右边比&#xff0c;左子树的右边与右子树的左边比&#xff0c;不相等或者一边为空则不是对称。 代码&#x1f50e;&#xff1a; bool _isSymmetric(struct TreeNode* Leftroo…

程序员开发指南

在这个快节奏的时代&#xff0c;作为一名程序员&#xff0c;大家都希望能更快地开发出高质量的应用&#xff0c;而不是花费大量时间在基础设施和后台服务的搭建上。今天&#xff0c;我要向大家介绍一款专为懒人开发者准备的一站式开发应用的神器——MemFire Cloud。 一站式开发…

使用代理访问内网:实验二

目录 环境搭建 内网搭建&#xff08;win2019&#xff09; 跳板机搭建&#xff08;win10&#xff09; 实验步骤 1. win10上线kali 2. 借助msf做代理 3. 在攻击机上做个代理&#xff0c;访问目标网站 4. 使用SocksCap64工具&#xff0c;进行sock4a隧道的连接 5. 启用soc…

TypeScript 的主要特点和重要作用

还是大剑师兰特&#xff1a;曾是美国某知名大学计算机专业研究生&#xff0c;现为航空航海领域高级前端工程师&#xff1b;CSDN知名博主&#xff0c;GIS领域优质创作者&#xff0c;深耕openlayers、leaflet、mapbox、cesium&#xff0c;canvas&#xff0c;webgl&#xff0c;ech…

最短路(dijkstra迪杰斯特拉)

最短路径问题在图论中是一个经典的问题&#xff0c;目的是找到从一个起始顶点到其他所有顶点的最短路径。Dijkstra算法是解决非负权图最短路径问题的常用算法。下面是一个使用Dijkstra算法解决最短路径问题的Java程序例子。 动画描述(从0节点开始更新) 问题描述 假设有一个图…

【机器学习西瓜书学习笔记——模型评估与选择】

机器学习西瓜书学习笔记【第二章】 第二章 模型评估与选择2.1训练误差和测试误差错误率误差 欠拟合和过拟合2.2评估方法留出法交叉验证法自助法 2.3性能度量查准率、查全率与F1查准率查全率F1 P-R曲线ROC与AUCROCAUC 代价敏感错误率与代价曲线代价曲线 2.4比较检验假设检验&…

VSCode+Vue3无法找到模块“../components/xxxxx.vue”的声明文件的错误

莫名奇妙的错误 今天用Vue3写个demo&#xff0c;在components下面新建了一个DeviceList.Vue的文件&#xff0c;在HomeView引用它后居然报错&#xff0c;提示&#xff1a;无法找到模块“…/components/DeviceList.vue”的声明文件&#xff0c;真是离了个大谱&#xff0c;文件明…

【Redis】 拓展:Redis - BigKey方案探讨

BigKey: 用户越多&#xff0c;redis数据越多&#xff0c;bigkey会使得缓存数据更大&#xff0c;网络带宽会被占用&#xff0c;执行效率就低下&#xff0c;高并发的时候吞吐量QPS也会下降。 产生原因&#xff1a; 看如下list&#xff1a; 一个key的内容太大&#xff0c;比如1M&…

VR舒适度术语表与检查表:为MR和空间计算应用创业者准备

随着混合现实&#xff08;MR&#xff09;和空间计算应用的发展&#xff0c;确保用户在虚拟环境中的舒适度变得尤为重要。本文将介绍一套专门针对VR舒适度的术语表&#xff0c;并提供两个知名VR游戏作为示例&#xff0c;来展示如何应用这些术语。这些术语和示例可以帮助开发者更…

基于Hadoop的服装电商数据分析系统【Hdfs、flume、HIve、sqoop、MySQL、echarts】

文章目录 有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博主项目介绍总体研究方向数据集介绍配置flume文件HIve建表HIveSQL大数据分析MySQL建表Sqoop命令导出数据到MySQL数据可视化店铺销售情况.......等 总结每文一语 有需要本项目的代码或文档以及全…

【面向就业的Linux基础】从入门到熟练,探索Linux的秘密(十四)-租云服务器及配环境、docker基本命令

主要介绍了租云服务器和docker配置、基本命令&#xff01;&#xff01;&#xff01; 文章目录 前言 一、云平台 二、租云服务器及安装docker 1.阿里云 2.安装docker 三、docker命令 将当前用户添加到docker用户组 镜像&#xff08;images&#xff09; 容器(container) 四、实战…

Vue3-18 组件基础

组件的定义 我们在项目的src/components种定义组件&#xff0c;vue提供了几种简单的组件的定义方式 在单文件种定义组件 <script setup> import { ref } from vue const count ref(0) </script> <template><div>第一种<button click"count…

系统测试:验证系统整体行为的关键环节

目录 前言1. 系统测试的概念2. 系统测试的主要作用2.1 验证需求实现2.2 发现集成问题2.3 提高系统质量2.4 评估系统性能 3. 系统测试在整个测试过程中的地位3.1 单元测试3.2 集成测试3.3 系统测试3.4 验收测试 4. 常用的系统测试工具4.1 Selenium4.2 JMeter4.3 LoadRunner4.4 T…

高等数学 第七讲 一元函数积分学的概念和性质_不定积分_定积分_变限积分_反常积分

1.不定积分 文章目录 1.不定积分1.1 原函数1.1.1 原函数与不定积分的定义1.1.2 原函数存在定理 2.定积分2.1 定积分的定义2.2 定积分的精确定义2.3 定积分的几何意义2.4 定积分的存在定理2.5 定积分的性质 3.变限积分3.1 变限积分的定理3.2 变限积分的性质 4.反常积分(待更新) …

springboot集团门户网站--论文源码调试讲解

第2章 开发环境与技术 开发集团门户网站需要搭建编程的环境&#xff0c;也需要通过调查&#xff0c;对各个相关技术进行分析&#xff0c;选取适合本系统开发的技术与工具。 2.1 MySQL数据库 MySQL是一种具有安全系数、安全系数、混合开发性、高效化等特征的轻量关联数据库智…