当前位置: 首页 > news >正文

神经网络量化基础

  • 1,模型量化概述
    • 1.1,模型量化优点
    • 1.2,模型量化的方案
      • 1.2.1,PTQ 理解
    • 1.3,量化的分类
      • 1.3.1,线性量化概述
  • 2,量化算术
    • 2.1,定点和浮点
    • 2.2,量化浮点
    • 2.2,量化算术
  • 3,量化方法的改进
    • 3.1,浮点数动态范围选择
    • 3.2,最大最小值(MinMax)
    • 3.3,滑动平均最大最小值(MovingAverageMinMax)
    • 3.4,KL 距离采样方法(Kullback–Leibler divergence)
    • 3.5,总结
  • 4,量化实战经验
  • 参考资料

本文为对目前线性量化优点、原理、方法和实战内容的总结,主要参考 神经网络量化简介 并加以自己的理解和总结,适合初学者阅读和自身复习用。

1,模型量化概述

1.1,模型量化优点

模型量化是指将神经网络的浮点算法转换为定点。量化有一些相似的术语,低精度(Low precision)可能是常见的。

  • 低精度模型表示模型权重数值格式为 FP16(半精度浮点)或者 INT8(8位的定点整数),但是目前低精度往往就指代 INT8
  • 常规精度模型则一般表示模型权重数值格式为 FP32(32位浮点,单精度)。
  • 混合精度(Mixed precision)则在模型中同时使用 FP32FP16 的权重数值格式。 FP16 减少了一半的内存大小,但有些参数或操作符必须采用 FP32 格式才能保持准确度。

模型量化有以下好处:

参考 TensorFlow 模型优化:模型量化-张益新

  • 减小模型大小:如 int8 量化可减少 75% 的模型大小,int8 量化模型大小一般为 32 位浮点模型大小的 1/4
    • 减少存储空间:在端侧存储空间不足时更具备意义。
    • 减少内存占用:更小的模型当然就意味着不需要更多的内存空间。
    • 减少设备功耗:内存耗用少了推理速度快了自然减少了设备功耗;
  • 加快推理速度,访问一次 32 位浮点型可以访问四次 int8 整型,整型运算比浮点型运算更快;CPUint8 计算的速度更快
  • 某些硬件加速器如 DSP/NPU 只支持 int8。比如有些微处理器属于 8 位的,低功耗运行浮点运算速度慢,需要进行 8bit 量化。

总结:模型量化主要意义就是加快模型端侧的推理速度,并降低设备功耗和减少存储空间,

工业界一般只使用 INT8 量化模型,如 NCNNTNN 等移动端模型推理框架都支持模型的 INT8 量化和量化模型的推理功能。

通常,可以根据 FP32INT8 的转换机制对量化模型推理方案进行分类。一些框架简单地引入了 QuantizeDequantize 层,当从卷积或全链接层送入或取出时,它将 FP32 转换为 INT8 或相反。在这种情况下,如下图的上半部分所示,模型本身和输入/输出采用 FP32 格式。深度学习推理框架加载模型时,重写网络以插入 QuantizeDequantize 层,并将权重转换为 INT8 格式。

注意,之所以要插入反量化层(Dequantize),是因为量化技术的早期,只有卷积算子支持量化,但实际网络中还包含其他算子,而其他算子又只支持 FP32 计算,因此需要把 INT8 转换成 FP32。但随着技术的迭代,后期估计会逐步改善乃至消除 Dequantize 操作,达成全网络的量化运行,而不是部分算子量化运行。

量化模型的推理

图四:混合 FP32/INT8 和纯 INT8 推理。红色为 FP32,绿色为 INT8 或量化。

其他一些框架将网络整体转换为 INT8 格式,因此在推理期间没有格式转换,如上图的下半部分。该方法要求算子(Operator)都支持量化,因为运算符之间的数据流是 INT8。对于尚未支持的那些,它可能会回落到 Quantize/Dequantize 方案。

1.2,模型量化的方案

在实践中将浮点模型转为量化模型的方法有以下三种方法:

  1. data free:不使用校准集,传统的方法直接将浮点参数转化成量化数,使用上非常简单,但是一般会带来很大的精度损失,但是高通最新的论文 DFQ 不使用校准集也得到了很高的精度。
  2. calibration:基于校准集方案,通过输入少量真实数据进行统计分析。很多芯片厂商都提供这样的功能,如 tensorRT、高通、海思、地平线、寒武纪
  3. finetune:基于训练 finetune 的方案,将量化误差在训练时仿真建模,调整权重使其更适合量化。好处是能带来更大的精度提升,缺点是要修改模型训练代码,开发周期较长。

TensorFlow 框架按照量化阶段的不同,其模型量化功能分为以下两种:

  • Post-training quantization PTQ(训练后量化、离线量化);
  • Quantization-aware training QAT(训练时量化,伪量化,在线量化)。
1.2.1,PTQ 理解

PTQ Post Training Quantization 是训练后量化,也叫做离线量化,根据量化零点 xzero_point 是否为 0,训练后量化分为对称量化和非对称量化;根据数据通道顺序 NHWC(TensorFlow) 这一维度区分,训练后量化又分为逐层量化和逐通道量化。目前 nvidiaTensorRT 框架中使用了逐层量化的方法,每一层采用同一个阈值来进行量化。逐通道量化就是对每一层每个通道都有各自的阈值,对精度可以有一个很好的提升。

1.3,量化的分类

目前已知的加快推理速度概率较大的量化方法主要有:

  1. 二值化,其可以用简单的位运算来同时计算大量的数。对比从 nvdia gpu 到 x86 平台,1bit 计算分别有 5 到128倍的理论性能提升。且其只会引入一个额外的量化操作,该操作可以享受到 SIMD(单指令多数据流)的加速收益。
  2. 线性量化(最常见),又可细分为非对称,对称和 ristretto 几种。在 nvdia gpux86arm 和 部分 AI 芯片平台上,均支持 8bit 的计算,效率提升从 1 倍到 16 倍不等,其中 tensor core 甚至支持 4bit计算,这也是非常有潜力的方向。线性量化引入的额外量化/反量化计算都是标准的向量操作,因此也可以使用 SIMD 进行加速,带来的额外计算耗时不大。
  3. 对数量化,一种比较特殊的量化方法。两个同底的幂指数进行相乘,那么等价于其指数相加,降低了计算强度。同时加法也被转变为索引计算。目前 nvdia gpux86arm 三大平台上没有实现对数量化的加速库,但是目前已知海思 351X 系列芯片上使用了对数量化。
1.3.1,线性量化概述

与非线性量化不同,线性量化采用均匀分布的聚类中心,原始浮点数据和量化后的定点数据存在一个简单的线性变换关系,因为卷积、全连接等网络层本身只是简单的线性计算,因此线性量化中可以直接用量化后的数据进行直接计算。

2,量化算术

模型量化过程可以分为两部分:将模型从 FP32 转换为 INT8,以及使用 INT8 进行推理。本节说明这两部分背后的算术原理。如果不了解基础算术原理,在考虑量化细节时通常会感到困惑。

2.1,定点和浮点

定点和浮点都是数值的表示(representation),它们区别在于,将整数(integer)部分和小数(fractional)部分分开的点,点在哪里。定点保留特定位数整数和小数,而浮点保留特定位数的有效数字(significand)和指数(exponent)

绝大多数现代的计算机系统采纳了浮点数表示方式,这种表达方式利用科学计数法来表达实数。即用一个尾数(Mantissa,尾数有时也称为有效数字,它实际上是有效数字的非正式说法),一个基数(Base),一个指数(Exponent)以及一个表示正负的符号来表达实数。具体组成如下:

  • 第一部分为 sign 符号位 s,占 1 bit,用来表示正负号;
  • 第二部分为 exponent 指数偏移值 k,占 8 bits,用来表示其是 2 的多少次幂;
  • 第三部分是 fraction 分数值(有效数字) M,占 23 bits,用来表示该浮点数的数值大小。

基于上述表示,浮点数的值可以用以下公式计算:

(−1)s×M×2k

值得注意是,上述公式隐藏了一些细节,如指数偏移值 k 使用的时候需要加上一个固定的偏移值。

比如 123.45 用十进制科学计数法可以表示为 1.2345×102,其中 1.2345 为尾数,10 为基数,2 为指数。

单精度浮点类型 float 占用 32bit,所以也称作 FP32;双精度浮点类型 double 占用 64bit

定点和浮点的格式和示例

图五:定点和浮点的格式和示例。

2.2,量化浮点

32-bit 浮点数和 8-bit 定点数的表示范围如下表所示:

数据类型最小值最大值
FP32-3.4e383.4e38
int8-128128
uint80255

神经网络的推理由浮点运算构成。FP32INT8 的值域是 [(2−223)×2127,(223−2)×2127][−128,127],而取值数量大约分别为 23228FP32 取值范围非常广,因此,将网络从 FP32 转换为 INT8 并不像数据类型转换截断那样简单。但是,一般神经网络权重的值分布范围很窄,非常接近零。图八给出了 MobileNetV1 中十层(拥有最多值的层)的权重分布。
十层 MobileNetV1 的权重分布

图八:十层 MobileNetV1 的权重分布。

根据偏移量 Z 是否为 0,可以将浮点数的线性量化分为两类-对称量化和非对称量化。

当浮点值域落在 (−1,1) 之间,权重浮点数据的量化运算可使用下式的方法将 FP32 映射到 INT8,这是对称量化。其中 xfloat 表示 FP32 权重, xquantized 表示量化的 INT8 权重,xscale 是缩放因子(映射因子、量化尺度(范围)/ float32 的缩放因子)。

xfloat=xscale×xquantized

对称量化的浮点值和 8 位定点值的映射关系如下图,从图中可以看出,对称量化就是将一个 tensor 中的 [−max(|x|),max(|x|)] 内的 FP32 值分别映射到 8 bit 数据的 [-128, 127] 的范围内,中间值按照线性关系进行映射,称这种映射关系是对称量化。可以看出,对称量化的浮点值和量化值范围都是相对于零对称的。

对称量化

因为对称量化的缩放方法可能会将 FP32 零映射到 INT8 零,但我们不希望这种情况出现,于是出现了数字信号处理中的均一量化,即非对称量化。数学表达式如下所示,其中 xzero_point 表示量化零点(量化偏移)。

xfloat=xscale×(xquantized−xzero_point)

大多数情况下量化是选用无符号整数,即 INT8 的值域就为 [0,255] ,这种情况,显然要用非对称量化。非对称量化的浮点值和 8 位定点值的映射关系如下图:

非对称量化

总的来说,权重量化浮点值可以分为两个步骤

  1. 通过在权重张量(Tensor)中找到 minmax 值从而确定 xscalexzero_point
  2. 将权重张量的每个值从 FP32 转换为 INT8 。

(1)xfloat∈[xfloatmin,xfloatmax](2)xscale=xfloatmax−xfloatminxquantizedmax−xquantizedmin(3)xzero_point=xquantizedmax−xfloatmax÷xscale(4)xquantized=xfloat÷xscale+xzero_point

注意,当浮点运算结果不等于整数时,需要额外的舍入步骤。例如将 FP32 值域 [−1,1] 映射到 INT8 值域 [0,255],有 xscale=2255,而xzero_point=255−2552≈127

注意,量化过程中存在误差是不可避免的,就像数字信号处理中量化一样。非对称算法一般能够较好地处理数据分布不均匀的情况

2.2,量化算术

量化的一个重要议题是用量化算术表示非量化算术,即量化神经网络中的 INT8 计算是描述常规神经网络的 FP32 计算,对应的就是反量化过程,也就是如何将 INT8 的定点数据反量化成 FP32 的浮点数据。

下面的等式 5-10 是反量化乘法 xfloat⋅yfloat 的过程。对于给定神经网络,输入 x、权重 y 和输出 z 的缩放因子肯定是已知的,因此等式 14 的 Multiplierx,y,z=xscaleyscalezscale 也是已知的,在反量化过程之前可预先计算。因此,除了 Multiplierx,y,z(xquantized−xzero_point)⋅(yquantized−yzero_point) 之间的乘法外,等式 16 中的运算都是整数运算。

(5)zfloat=xfloat⋅yfloat(6)zscale⋅(zquantized−zzero_point)=(xscale⋅(xquantized−xzero_point))⋅(yscale⋅(yquantized−yzero_point))(7)zquantized−zzero_point=xscale⋅yscalezscale⋅(xquantized−xzero_point)⋅(yquantized−yzero_point)(8)zquantized=xscale⋅yscalezscale⋅(xquantized−xzero_point)⋅(yquantized−yzero_point)+zzero_point(9)Multiplierx,y,z=xscale⋅yscalezscale(10)zquantized=Multiplierx,y,z⋅(xquantized−xzero_point)⋅(yquantized−yzero_point)+zzero_point

等式:反量化算术过程。

对于等式 10 可以应用的大多数情况,quantizedzero_point 变量 (x,y) 都是 INT8 类型,scaleFP32。实际上两个 INT8 之间的算术运算会累加到 INT16INT32,这时 INT8 的值域可能无法保存运算结果。例如,对于 xquantized=20xzero_point=50 的情况,有

相关文章:

神经网络量化基础

1,模型量化概述 1.1,模型量化优点1.2,模型量化的方案 1.2.1,PTQ 理解 1.3,量化的分类 1.3.1,线性量化概述 2,量化算术 2.1,定点和浮点2.2,量化浮点2.2,量化算…...

飞机大战告尾

参考 PPO算法逐行代码详解 链接 通过网盘分享的文件:PlaneWar 链接: https://pan.baidu.com/s/1cbLKTcBxL6Aem3WkyDtPzg?pwd1234 提取码: 1234 10.17关于博客发了又改这件事 悲催的事 今天训练了一早上ppo模型,满怀期待的检测成果时发现一点长进都…...

支持向量机SVM原理详解

SVM原理详解 1、超平面2、SVM原理1. 问题定义2. 分类决策得到约束条件 3. 最大化间隔4. 优化目标 3、凸优化问题1. 原始优化问题优化目标约束条件 2. 拉格朗日乘子法3. 拉格朗日函数分析4. 求解对 w w w 和 b b b 的极值5. 构造对偶问题对偶问题的约束条件: 6、通…...

使用JMeter进行Spring Boot接口的压力测试

使用 Apache JMeter 对接口进行压力测试是一个相对简单的过程。以下是详细的步骤,包括安装、配置和执行测试计划。 1. 下载和安装 JMeter 下载 JMeter 从 JMeter 官方网站https://jmeter.apache.org/download_jmeter.cgi 下载最新版本的 JMeter。 解压缩 将下载的 …...

C++学习笔记----9、发现继承的技巧(三)---- 尊重父类(1)

当写继承类的时候,需要清楚父类与子类之间的交互。像生成顺序,构造函数链,以及转化都可以是问题的根源。 1、父类构造函数 对象不会马上就能干活;它们必须由父类以及所包含的任意对象进行构建。c定义了如下的生成顺序&#xff1a…...

启动service报错ORA-44317: database open read-only

ADG&#xff08;RAC&#xff09;备库环境&#xff0c;srvctl添加service服务成功&#xff0c;启动service时报错ORA-44317: database open read-only。 这是预期行为&#xff0c; 使用“srvctl add service -d <db_name> -s <service_name>”创建服务时&#xff0c…...

GNU/Linux - Savannah项目

* 我们托管在自由操作系统上运行的自由项目&#xff0c;不依赖任何专有软件。 * 我们的服务使用 100% 的自由软件运行&#xff0c;包括服务本身。 * We host free projects that run on free operating systems and without any proprietary software dependencies. * Our se…...

Debug-028-el-carousel走马灯-当展示图片为2的问题处理

前言&#xff1a; el-carousel走马灯又是给elementui填坑的一天。el-carousel走马灯其实类似小程序中的轮播图。这里担心涉及版权问题就不贴项目中的图了。简单阐述一下问题&#xff1a;正常使用el-carousel时&#xff0c;如果图片数量大于等于3时&#xff0c;可以定时自动顺序…...

TapData 知识库 | 一文吃透数据整合(Data Consolidation)

顾名思义&#xff0c;数据整合指的是将不同来源的数据汇集在一起&#xff0c;并将其集中存储于一个统一的数据平台。数据整合使用户能够通过单一访问入口获取数据&#xff0c;进而推动数据洞察的生成与分析。 数据通常被简单地看作信息的集合&#xff0c;仿佛默认每个数据单元在…...

MySQL数据的导出

【图书推荐】《MySQL 9从入门到性能优化&#xff08;视频教学版&#xff09;》-CSDN博客 《MySQL 9从入门到性能优化&#xff08;视频教学版&#xff09;&#xff08;数据库技术丛书&#xff09;》(王英英)【摘要 书评 试读】- 京东图书 (jd.com) MySQL9数据库技术_夏天又到了…...

微服务--OpenFeign【重点】

如果哪天 我们硬编码写的接口变了&#xff0c;只要写过该接口的 都要改&#xff0c;太麻烦了&#xff0c; 所以 就用 OpenFeign 来解决这个麻烦 了解&#xff1a; SimpleClientHttpRequestFactory和 HttpComponentsClientHttpRequestFactory 都是Spring框架中用于创建ClientH…...

【力扣打卡系列】滑动窗口与双指针(两数之和)

坚持按题型打卡&刷&梳理力扣算法题系列&#xff0c;语言为go&#xff0c;Day1 两数之和 题目描述 解题思路 采用哈希表 将nums[i] nums[j] target 转化成 nums[i] target - nums[j]去思考新建一个map来存储&#xff0c;键为值&#xff08;左边的&#xff09;&#…...

蚂蚁华东师范大学:从零开始学习定义和解决一般优化问题LLMOPT

&#x1f3af; 推荐指数&#xff1a;&#x1f31f;&#x1f31f;&#x1f31f; &#x1f4d6; title&#xff1a;LLMOPT: Learning to Define and Solve General Optimization Problems from Scratch &#x1f525; code&#xff1a;https://github.com/caigaojiang/LLMOPT &am…...

价格游戏的终章:品牌如何在通货膨胀时代智取市场

来源&#xff1a;The era of price-led profit growth is coming to an end (marketingweek.com) 近年来&#xff0c;通货膨胀促使许多品牌通过提价来提升利润&#xff0c;而销量几乎没有受到太大影响。然而&#xff0c;随着通货膨胀放缓&#xff0c;继续提价的策略可能会吸引…...

CVTE Android面试题及参考答案

Activity 的生命周期 Activity 的生命周期分为以下几个主要状态: onCreate ():在 Activity 第一次被创建的时候调用。通常在这个方法中进行一些初始化操作,如设置布局、初始化成员变量等。这是 Activity 进入可见状态的第一步。onStart ():当 Activity 即将对用户可见的时候…...

Docker实战:从入门到进阶

Docker实战&#xff1a;从入门到进阶 引言 Docker是一个开源的应用容器引擎&#xff0c;它允许开发者打包他们的应用以及应用的依赖包到一个可移植的容器中&#xff0c;然后发布到任何支持Docker的平台上。本文将通过实战和应用举例&#xff0c;带领大家深入了解Docker的强大…...

Jupyter Notebook汉化(中文版)

原版jupyter notebook是英文的&#xff0c;想要将其改为中文 在jupyter notebook所在环境输入以下命令 pip install jupyterlab-language-pack-zh-CN打开jupyter notebook&#xff0c;在设置语言中将其设置为中文...

C#的小数位保留以及四舍五入

C#使用Math.Round("数值","保留位","保留方式")进行小数位保留以及四舍五入 //1.MidpointRounding.ToEven(四舍六入五成双) //当保留小数位后一位为0~4时&#xff0c;舍去末位 var x1 Math.Round(1.124, 2, MidpointRo…...

KNNImputer

KNNImputer实例是指在使用Python的scikit-learn库时&#xff0c;通过sklearn.impute.KNNImputer类创建的一个对象&#xff0c;该对象专门用于处理数据集中的缺失值。KNNImputer采用K-近邻&#xff08;K-Nearest Neighbors&#xff0c;KNN&#xff09;算法来估算并填充这些缺失值…...

RHCE例行性工作笔记

1、单一执行的例行性工作 单一执行的例行性工作&#xff1a; 仅处理执行一次就结束了 at命令的工作过程 /etc/at.allow &#xff0c;写在该文件的人可以使用 at 命令 /etc/at.deny &#xff0c;黑名单 两个文件如果都不存在&#xff0c;只有 root 能使用 #at 工作调度对应的…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统&#xff0c;可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析&#xff1a;自动解析Markdown文档结构PPT模板分析&#xff1a;分析PPT模板的布局和风格智能布局决策&#xff1a;匹配内容与合适的PPT布局自动…...

JDK 17 新特性

#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持&#xff0c;不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的&#xff…...

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...

LeetCode - 199. 二叉树的右视图

题目 199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 思路 右视图是指从树的右侧看&#xff0c;对于每一层&#xff0c;只能看到该层最右边的节点。实现思路是&#xff1a; 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...