全网最最实用--模型高效推理:量化基础

文章目录

  • 一、量化基础--计算机中数的表示
    • 1. 原码(Sign-Magnitude)
    • 2. 反码(Ones' Complement)
    • 3. 补码(Two's Complement)
    • 4. 浮点数(Floating Point)
      • a.常用的浮点数标准--IEEE 754(FP32)。
      • b.FP16(半精度浮点数)
      • c.FP8
        • E4M3结构
        • E5M2结构
  • 二、量化经典方法
    • 1.K-means聚类量化(K-means Clustering-based Quantization)
    • 2.线性量化(Uniform Quantization)
  • 三、工业实践的两种量化技术
    • 1.PTQ训练后量化(Post-Training Quantization)
      • a.量化粒度( 粗 ➡️ 细 )
      • b.动态范围裁剪(Dynamic Range Clipping)
      • c.取整(Rounding)
    • 2.QAT量化感知训练(Quantization-Aware Training)--微调
  • 四、进一步优化与压缩技术
    • 1.二值化量化(Binary Quantization)和三值化量化(Ternary Quantization)
      • a.二值化的基本原理
      • b.优势
      • c.挑战
    • 3.混合精度量化(Mixed-Precision Quantization)
      • a.基本原理
      • b.具体实现

一、量化基础–计算机中数的表示

当然可以。以下是对补码、反码、原码和浮点数的详细介绍。

1. 原码(Sign-Magnitude)

最高位用来表示符号(0表示正数,1表示负数),其余位表示数值的大小。

示例:
- 8位原码表示:- `+5` 的原码表示为:`00000101`- `-5` 的原码表示为:`10000101`
优点:
- 简单直观
缺点:
- 存在两个零,正零(`00000000`)和负零(`10000000`),这会导致某些计算上的复杂性
- 不便于直接进行加减运算

2. 反码(Ones’ Complement)

正数的反码与原码相同,负数的反码通过将原码的每一位取反(0变1,1变0)得到。

示例:
- 8位反码表示:- `+5` 的反码表示为:`00000101`- `-5` 的反码表示为:`11111010`
优点:
- 虽然反码表示法在加法运算中仍然需要处理进位,但是比起原码表示法,少了符号位的特殊处理,使得硬件实现上更为简单。
缺点:
- 仍然存在两个零,正零(`11111111`)和负零(`10000000`),但实际运算仍然复杂
- 不便于直接进行加减运算

3. 补码(Two’s Complement)

补码是计算机中普遍使用的带符号整数表示法。正数的补码与原码相同,负数的补码通过将其反码(逐位取反)加1得到。

示例:
- 8位补码表示:- `+5` 的补码表示为:`00000101`- `-5` 的补码表示为:`11111011`计算方法:
1. 求原码:`10000101`(-5的原码)
2. 取反:`01111010`(-5的反码)
3. 加1:`01111010 + 1 = 01111011`(-5的补码)优点:
- 消除零的双重表示(正零与负零相同)
- 统一的加减法运算,不需要额外处理符号位
缺点:
- 直接阅读和理解时不如原码和反码直观

4. 浮点数(Floating Point)

浮点数是一种用于表示实数(包括小数和非常大或非常小的数)的表示法。它分为三个部分:符号位、指数位和尾数(有效数字)位。

a.常用的浮点数标准–IEEE 754(FP32)。

IEEE 754 单精度浮点数:FP32(单精度浮点数)

  • 32位表示
    • 1位符号位(S)
    • 8位指数位(E)
    • 23位尾数位(M)
    • 表示范围大约为:±1.4 × 10^-45±3.4 × 10^38

IEEE 754 双精度浮点数

  • 64位表示
    • 1位符号位(S)
    • 11位指数位(E)
    • 52位尾数位(M)
示例:
- 单精度浮点数 `-5.75` 的IEEE 754表示可以分解为:- 符号位:`1`- 指数位:`10000001`(表示指数为`2^1`)- 尾数位:`01110000000000000000000`(表示`1.011`)计算方法:
1. 将数转换为二进制科学计数法。- `-5.75 = -1.011 * 2^2`
2. 符号位 `S`:负数为`1`,正数为`0`。这里是`1`3. 指数位 `E`:实际指数加上偏移量(127)。这里指数是`2`,所以`2 + 127 = 129`,对应二进制`10000001`4. 尾数位 `M`:去掉`1.`后的部分。这里是`01100000000000000000000`。优点:
- 能表示很大的范围:从非常小到非常大的数
- 能够精确表示整数、分数、小数和实数缺点:
- 存在精度问题,尤其是在表示很大的数或者进行大量浮点运算时
- 复杂性较高,比整数运算慢
FP32(单精度浮点数)和FP16(半精度浮点数)是指不同精度的浮点数表示法,常用于计算机科学和工程中的数值计算。以下是它们的详细表示方法。

b.FP16(半精度浮点数)

FP16,是指IEEE 754标准中的16位浮点数表示法。表示范围和精度适中,常用于深度学习中的权重和激活值表示。

结构:- 总共16位:- 1位符号位(S)- 5位指数位(E)- 10位尾数位(M)- 表示范围大约为:`±6.1 × 10^-5``±6.5 × 10^4`示例:假设我们要表示浮点数 `-5.75`:**
1. 转换为二进制科学计数法:- `-5.75` 转换为二进制为 `-101.11`- 转换为科学计数法:`-1.0111 * 2^2`2. 符号位(S):- 负数符号位为 `1`3. 指数位(E):- 指数是 `2`- 加上偏移量 `15``2 + 15 = 17`- 转换为二进制:`10001`4. 尾数位(M):- 去掉 `1.` 后的部分:`0111000000`最终表示:
- `1 10001 0111000000`

c.FP8

FP8是一种8位浮点数格式,正如其名称所示,它使用8个位来表示一个浮点数。虽然FP8并不是IEEE 754标准中的一种正式标准,但它在特定的应用场景(例如深度学习和神经网络计算)中逐渐受到关注。FP8的主要特点是它能以更低的精度和更小的存储需求来执行浮点数运算,从而加速计算和减少内存带宽需求。

FP8通常有两种主要的表示方式:E4M3 和 E5M2,这两种方式的主要区别在于指数和尾数的位数分配。

E4M3结构
E4M3表示法分配4位给指数,3位给尾数。- 符号位(S):1位
- 指数位(E):4位
- 尾数位(M):3位
- 范围大约为:`± 2^-6``± 240`
- E4M3:指数为4位,偏移量为7
E5M2结构
E5M2表示法分配5位给指数,2位给尾数。- 符号位(S):1位
- 指数位(E):5位
- 尾数位(M):2位
- 范围大约为: `± 2^-14``±57344`
- E5M2:指数为5位,偏移量为15

优势:

  1. 计算效率:FP8减少了数据存储和传输需求,可以大幅加速深度学习模型的训练和推理过程。
  2. 内存带宽:由于数据量更小,FP8能够显著减少内存带宽压力。
  3. 硬件支持:一些现代神经网络加速器和硬件架构已经开始支持FP8计算,以便提高深度学习任务的性能。

应用场景: FP8主要应用于需要大量计算但对数值精度要求相对较低的场景,例如:

  • 深度学习推理:在推理阶段,模型的权重和激活值可以量化为FP8,以加速计算。
  • 训练过程中的权重量化:在某些情况下,模型训练中的权重可以被量化为FP8以减少计算复杂度。

二、量化经典方法

1.K-means聚类量化(K-means Clustering-based Quantization)

K-means聚类是一种常用的无监督学习算法,主要用于数据的聚类分析。它通过将数据分成K个簇(cluster),使得同一簇中的数据点尽可能接近,而不同簇之间的距离尽可能远。
K-means聚类的量化可以理解为将连续的特征空间转化为离散的簇标签。具体过程如下:

  1. 量化后的数据表示

    • 一旦数据被聚类,每个数据点就被分配一个簇标签(0到K-1),这意味着原来的数据被“量化”为K个类别。
  2. 质心作为代表

    • 每个簇的质心可以看作是该簇内数据点的一个“代表”。在某些应用中,可以用质心的值来替代该簇内的所有数据点,从而实现数据压缩。
  3. 量化误差

    • 量化过程中不可避免地会引入误差。量化误差可以通过计算每个数据点与其对应簇的质心之间的距离来衡量。总的误差可以表示为:

    • 在这里插入图片描述

    • 这也被称为簇内平方和(Within-cluster Sum of Squares,WCSS)。

2.线性量化(Uniform Quantization)

线性量化是将连续的浮点数值映射为离散的整数值的一种方法,旨在减少存储需求和计算复杂度。

线性量化的核心是将浮点数值范围均匀分割为若干个离散值。每个离散值对应一个整数,通常用于表示模型的权重或激活值。量化过程中的关键参数是缩放因子(scale)偏置(zero-point)。它的计算过程如下:

1. 确定量化范围

首先,需要确定浮点数值的最小值((\text{min}))和最大值((\text{max}))。这可以通过分析数据集中的值来获得。

2. 计算缩放因子(Scale)

缩放因子用于定义浮点值与量化值之间的线性映射关系。其计算公式为:

在这里插入图片描述

在这里,Q_max 和 Q_min分别是量化后可能的最大和最小整数值。例如,对于8位量化,Q_max = 255 和 Q_min = 0。

3. 计算偏置(Zero-Point)

偏置用于调整量化值的范围,使其适应原始数据的分布。偏置的计算公式为:

在这里插入图片描述

这确保了量化后整数值能够尽可能准确地表示原始浮点值。

4. 量化转换

一旦计算出缩放因子和偏置,就可以将浮点数值转换为量化后的整数值。量化的转换公式为:

在这里插入图片描述
这里,x_float是原始浮点数值,而 x_int是得到的整数值。

示例

在这里插入图片描述

三、工业实践的两种量化技术

1.PTQ训练后量化(Post-Training Quantization)

PTQ使用一批校准数据对训练好的模型进行校准,将训练过的FP32模型直接转换为定点计算的模型,过程中无需对原始模型进行任何训练。只对几个超参数调整就可完成量化过程, 且过程简单快速,无需训练

a.量化粒度( 粗 ➡️ 细 )

  • 逐张量量化:每个张量(例如,权重或激活)都拥有自己的缩放因子和偏置。这种方法灵活性高,但对于参数的存储需求较大,因为每个张量都需要独立的量化参数。由于通道范围可能有差异,此方法在不同层表现效果不同。
  • 逐通道量化:每个通道(例如,在卷积层中,每个过滤器的输出)都有各自的缩放因子和偏置。这种方法能够更好地捕捉通道间的特征,使得视觉模型在量化后仍能保持较高的性能。虽然存储需求增加,但在许多视觉任务中,逐通道量化通常能带来更好的性能表现。
  • 一组数据量化:在某些情况下,可以对一组数据(如子向量)进行共享量化参数(例如,共享指数),以减少存储和计算开销。这种方法通常适用于特定的模型架构和任务。)

b.动态范围裁剪(Dynamic Range Clipping)

动态范围裁剪是一种有效的量化前处理技术。它在训练过程中使用指数移动平均(EMA)来动态调整每个张量的量化范围。具体流程如下:

  • 校准数据注入:在量化之前,向模型注入一小批校准数据。这些数据用于统计每个张量的特征值范围。
  • 动态范围计算:通过EMA对每个张量在校准批次中的最大值和最小值进行动态计算,从而得到每个张量的量化范围。这种方法可以有效捕获在实际推理中数据的动态变化,确保量化后的模型性能尽可能接近原始模型。

c.取整(Rounding)

取整是量化过程中一个重要的步骤,决定了浮点数值如何被转换为整数值。在量化时,浮点值会被映射到离散的整数值,这一过程通常涉及以下几种取整方式:

  • 四舍五入(Round Half to
    Even):这种方法在数字的尾数为0.5时,会向最近的偶数取整。这种方式在统计上是比较公平的,能减少量化误差的累积。

  • 向上取整(Ceiling):将所有浮点值向上取到下一个整数。这种方式可能导致量化后值偏高。

  • 向下取整(Floor):将所有浮点值向下取整到最近的整数。这一方法可能导致量化后值偏低

2.QAT量化感知训练(Quantization-Aware Training)–微调

QAT 是将训练过的模型量化后又再进行重训练。由于定点数值无法用于反向梯度计算,实际操作过程是在某些op前插入伪量化节点(fake quantization nodes), 用于在训练时获取流经该op的数据的截断值,便于在部署量化模型时对节点进行量化时使用。我们需要在训练中通过不断优化精度来获取最佳的量化参数。由于它需要对模型进行训练,对操作人员技术要求较高。

伪量化是在训练过程中保持一个全精度权重副本的过程。具体步骤如下:

  • 插入伪量化节点 :在模型的前向传播过程中,在适当的位置插入伪量化节点。每当数据流经这些节点时,输入数据首先通过量化操作(如缩放、取整等),然后再将量化值映射回全精度范围。
  • 保持全精度副本:尽管在前向传播中使用量化值进行计算,但模型仍然使用全精度权重进行反向传播的梯度计算。这意味着网络的更新将基于全精度的权重,从而避免了量化误差在训练过程中的累积。
  • 优化量化参数:通过不断迭代训练过程,模型会优化量化参数(如缩放因子和偏置),以便在最终量化时尽可能减少精度损失。

四、进一步优化与压缩技术

1.二值化量化(Binary Quantization)和三值化量化(Ternary Quantization)

二值化量化是一种极端的模型压缩技术,其主要目标是通过将神经网络的权重和激活值限制为仅包含两个离散值(通常是 +1 和 -1 或 0 和 1)来显著减少模型的存储需求和计算复杂度。这种方法特别适合在资源受限的设备上进行深度学习模型部署。

在三值化量化中,权重和激活值会被转换为三种可能的值。常见的转换方式是使用某个阈值,来将权重分为负值、零值和正值。例如,可以根据权重的大小来判断它应该被量化为 -1、0 或 +1。这种方法比二值化提供了更大的表达能力,允许网络在保留某些特征的同时,对不重要的权重进行稀疏化处理(即设置为0)。

a.二值化的基本原理

在传统的全精度(FP32)神经网络中,权重和激活值以浮点数形式表示,这使得模型的存储和计算需求相对较高。而二值化网络通过以下方式简化了这一过程:

  1. 权重和激活的二值化

    • 权重和激活值通过特殊的二值化函数转换为 +1 和 -1(或 0 和 1)。例如,可以根据某个阈值将权重值转化为 +1 或 -1。
    • 这种二值化不仅减少了存储需求(每个权重仅需一个比特位),同时降低了计算复杂度。
  2. 高效的乘法和累加

    • 在二值化网络中,传统的乘法运算可以通过XNOR操作来替代。XNOR门是一种逻辑电路,能够同时执行两个输入的比较,并输出相应的结果。
    • 计算卷积操作时,使用二值权重和激活值,可以通过XNOR和pop count(计数操作)来替代复杂的浮点乘法运算,从而实现更高效的计算。

b.优势

  • 极致的模型压缩

    • 二值化极大地减少了模型的存储需求,通常可以将模型的大小降低到原来的1/32或更小。这使得在存储和带宽有限的设备(如移动设备和嵌入式系统)上运行深度学习模型变得可行。
  • 显著加速计算

    • 由于二值化网络使用XNOR和计数操作代替传统的乘法和加法,这种操作在硬件上通常可以实现极快的并行计算,从而大幅度提高推理速度。
  • 低功耗

    • 二值化操作相比于全精度计算所需的能量和资源更少,适合在低功耗环境下执行,如物联网设备和边缘计算场景。

c.挑战

虽然BNN在近5年来已经取得了很大的进步啦,但是比较大的问题就是精度的损失仍然是个头痛的问题,尤其是对于大型网络和数据集而言。主要原因可能包括:
1)目前还没有SOTA的二值化网络模型,不确定什么样的网络结构才合适做二值化;
2)即使有用于二值化的梯度估计或近似函数,在离散空间中优化二值网络是一个难题。

3.混合精度量化(Mixed-Precision Quantization)

混合精度量化是一种量化策略,旨在根据不同层对量化的敏感性,灵活地选择合适的量化精度。这种方法能够在模型的存储和计算效率与精度之间取得更好的平衡。

a.基本原理

在深度学习模型中,并非所有层对量化的敏感程度相同。一些层(如卷积层)可能对量化的反应比较敏感,而其他层(如全连接层)可能对量化的影响较小。混合精度量化通过分析各层的特点,动态地选择合适的量化精度,以最大限度地减少精度损失,同时降低计算和存储需求。

b.具体实现

  1. 层级分析

    • 对于每一层,首先进行量化敏感性分析,评估其对量化的反应程度。可以通过训练和验证阶段的实验,观察不同层在不同量化精度下的表现。
  2. 量化策略

    • 根据分析结果,为每一层选择适当的精度。例如,某些敏感层可以使用较高的精度(如FP16),而其他层可以采用较低的精度(如INT8或更低)。
  3. 强化学习反馈

    • 混合精度量化也可以结合强化学习,动态收集反馈,通过试验与调整的方式不断优化各层的量化策略。借助强化学习算法,能够在延迟和精度之间自动获得最佳平衡。

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

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

相关文章

ElasticSearch核心之DSL查询语句实战

什么是DSL? Elasticsearch提供丰富且灵活的查询语言叫做DSL查询(Query DSL),它允许你构建更加复杂、强大的查询。 DSL(Domain Specific Language特定领域语言)以JSON请求体的形式出现。目前常用的框架查询方法什么的底层都是构建DSL语句实现的,所以你必…

跨境电商独立站:Shopify/Wordpress/店匠选哪个?

在面对不断增加的平台运营压力时,不少跨境电商的商家逐渐将注意力转向建立自己的独立站。据《中国跨境出口电商发展报告(2022)》所示,中国拥有的独立站数量在2022年已接近20万个,这表明独立站已成为卖家拓展海外市场的…

IndentationError:unindent does not match any outer indentation level

IndentationError:unindent does not match any outer indentation level 目录 IndentationError:unindent does not match any outer indentation level 【常见模块错误】 【解决方案】 原因分析: 解决方法: 示例: 欢迎来到我的主页&am…

正则采集器——前端搭建

前端使用有名的饿了么管理后台,vue3版本vue3-element-admin,首先从gitee中克隆一个vue3-element-admin模板代码vue3-element-admin: Vue3 Element Admin开箱即用的中后台管理系统前端解决方案,然后在此基础上进行开发。 1、修改vite.config.…

matlab仿真 数字信号载波传输(下)

(内容源自详解MATLAB/SIMULINK 通信系统建模与仿真 刘学勇编著第七 章内容,有兴趣的读者请阅读原书) clear all M8; msg[1 4 3 0 7 5 2 6]; ts0.01; T1; %t0:ts:T; t0:ts:T-ts; %x0:ts:length(msg); x0:ts:length(msg)-ts; f…

使用Dumpbin工具查看C++二进制文件的位数、时间戳及dll库的依赖关系

目录 1、Dumpbin简介 2、使用Dumpbin查看二进制文件的位数与时间戳 3、使用Dumpbin查看二进制文件依赖的dll库 4、最后 C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/125529931C/C++基础入…

几种数据库中保存树的常见存储结构

在数据库中存储树时,常见的存储结构有以下几种: 常见存储结构 邻接列表 每个节点都有一个指向其父节点(pid)的引用。这种方法简单直观,也是最容易理解和常用的,但在获取整棵树或子树时可能需要多次查询。 存储结构 一般表结构…

自动驾驶-机器人-slam-定位面经和面试知识系列05之常考公式推导(02)

这个博客系列会分为C STL-面经、常考公式推导和SLAM面经面试题等三个系列进行更新,基本涵盖了自己秋招历程被问过的面试内容(除了实习和学校项目相关的具体细节)。在知乎和牛客(牛客上某些文章上会附上内推码)也会同步…

Android APP 音视频(03)CameraX预览与MediaCodec编码

说明: 此CameraX预览和编码实操主要针对Android12.0系统。通过CameraX预览获取yuv格式数据,将yuv格式数据通过mediacodec编码输出H264码流(使用ffmpeg播放),存储到sd卡上。 1 CameraX 和 MediaCodec简介 1.1 CameraX…

【CN】Argo 持续集成和交付(一)

1.简介 Argo 英 [ˈɑ:ɡəu] 美 [ˈɑrˌɡo] Kubernetes 原生工具,用于运行工作流程、管理集群以及正确执行 GitOps。 Argo 于 2020 年 3 月 26 日被 CNCF 接受为孵化成熟度级别,然后于 2022 年 12 月 6 日转移到毕业成熟度级别。 argoproj.github.i…

基于Xejen框架实现的C# winform鼠标点击器、电脑按键自动点击器的软件开发及介绍

功能演示 文章开始之前,仍然是先来个视频,以便用户知道鼠标连点器的基本功能 软件主界面 多功能鼠标连点器 快速点击: 痕即鼠标点击器可以设定每秒点击次数,让您轻松应对高频点击需求。 切换时长,即每次动作之间的间…

0719_驱动3 printk使用方法

一、printk使用方法 1.应用层打印使用printf,内核层使用printk 2.如何查看内核层中printk如何使用 3.在内核空间执行grep "printk" * -nR 4.在内核空间执行vi -t KERN_INFO 5.printk有8中打印级别(0-7),打印级别用来过滤…

数据结构(Java):反射枚举Lambda表达式

目录 1、反射 1.1 反射的定义 1.2 反射机制的原理 1.3 反射相关类 1.4 Class类 1.4.1 相关方法 1.4.1.1 常用获得类相关的方法 ​编辑 1.4.1.2 常用获得类中属性相关的方法 1.4.1.3 获得类中构造器相关的方法 1.4.1.4 获得类中方法相关的方法 1.4.2 获取Class对象 1.…

linux进程——虚拟地址空间——重新认识进程!!!

前言: 本节内容就将进入linux进程里面的又一个大板块, 博主认为这个板块和PCB的板块是平级——两者独立;之前友友们可能认为进程分为PCB和代码与数据。 但是本节过后, 我们可以对进程重新定义——进程 (PCB&#xff0…

深入理解计算机系统 CSAPP 家庭作业11.8

回收子进程是书本537页的内容 在tiny.c文件加以下代码,记得重新编译哦 书中提到CGI是在动态内容中的,所以题目的意思应该是在动态内容里面回收 void handler1(int sig) {int olderrno errno;while (waitpid(-1,NULL,0)>0){Sio_puts("Handler reaped child\n");…

【秋招突围】2024届秋招笔试-OPPO笔试题-第一套-三语言题解(Java/Cpp/Python)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新 OPPO 春秋招笔试题**汇总~ 👏 感谢大家的订阅➕ 和 喜欢💗 ✨ 笔试合集传送们 -> 🧷春秋招笔试合集 🎀 01.K小姐的快…

DVWA中命令执行漏洞细说

在攻击中,命令注入是比较常见的方式,今天我们细说在软件开发中如何避免命令执行漏洞 我们通过DVWA中不同的安全等级来细说命令执行漏洞 1、先调整DVWA的安全等级为Lower,调整等级在DVWA Security页面调整 2、在Command Injection页面输入127.0.0.1&…

【计算机网络】物理层(第2章)大纲(共70+页)

最后只复习了1.5天,应用层简单过了一遍。 本来是mindmap的,但是太大了只能导出成提纲了,凑合看吧orz。 如果你找我要源文件,最好是在2024年,不然我可能就找不到了()。

C# Task.WaitAll 的用法

目录 简介 1.WaitAll(Task[], Int32, CancellationToken) 2.WaitAll(Task[]) 3.WaitAll(Task[], Int32) 4.WaitAll(Task[], CancellationToken) 5.WaitAll(Task[], TimeSpan) 结束 简介 Task.WaitAll 是 C# 中用于并行编程的一个的方法,它属于 System.Threa…

蓝牙耳机百元之内怎么选?四款百元精品爆款蓝牙耳机盘点

在蓝牙耳机的海洋中,百元价位仿佛是一片神秘的绿洲,既诱人又充满未知,如何在众多选项中挑选出真正的精品呢?蓝牙耳机百元之内怎么选?这是许多消费者的共同疑问,带着这个疑问,作为蓝牙耳机发烧党…