文章目录
- 一、量化基础--计算机中数的表示
- 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
优势:
- 计算效率:FP8减少了数据存储和传输需求,可以大幅加速深度学习模型的训练和推理过程。
- 内存带宽:由于数据量更小,FP8能够显著减少内存带宽压力。
- 硬件支持:一些现代神经网络加速器和硬件架构已经开始支持FP8计算,以便提高深度学习任务的性能。
应用场景: FP8主要应用于需要大量计算但对数值精度要求相对较低的场景,例如:
- 深度学习推理:在推理阶段,模型的权重和激活值可以量化为FP8,以加速计算。
- 训练过程中的权重量化:在某些情况下,模型训练中的权重可以被量化为FP8以减少计算复杂度。
二、量化经典方法
1.K-means聚类量化(K-means Clustering-based Quantization)
K-means聚类是一种常用的无监督学习算法,主要用于数据的聚类分析。它通过将数据分成K个簇(cluster),使得同一簇中的数据点尽可能接近,而不同簇之间的距离尽可能远。
K-means聚类的量化可以理解为将连续的特征空间转化为离散的簇标签。具体过程如下:
-
量化后的数据表示:
- 一旦数据被聚类,每个数据点就被分配一个簇标签(0到K-1),这意味着原来的数据被“量化”为K个类别。
-
质心作为代表:
- 每个簇的质心可以看作是该簇内数据点的一个“代表”。在某些应用中,可以用质心的值来替代该簇内的所有数据点,从而实现数据压缩。
-
量化误差:
-
量化过程中不可避免地会引入误差。量化误差可以通过计算每个数据点与其对应簇的质心之间的距离来衡量。总的误差可以表示为:
-
这也被称为簇内平方和(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(或 0 和 1)。例如,可以根据某个阈值将权重值转化为 +1 或 -1。
- 这种二值化不仅减少了存储需求(每个权重仅需一个比特位),同时降低了计算复杂度。
-
高效的乘法和累加:
- 在二值化网络中,传统的乘法运算可以通过XNOR操作来替代。XNOR门是一种逻辑电路,能够同时执行两个输入的比较,并输出相应的结果。
- 计算卷积操作时,使用二值权重和激活值,可以通过XNOR和pop count(计数操作)来替代复杂的浮点乘法运算,从而实现更高效的计算。
b.优势
-
极致的模型压缩:
- 二值化极大地减少了模型的存储需求,通常可以将模型的大小降低到原来的1/32或更小。这使得在存储和带宽有限的设备(如移动设备和嵌入式系统)上运行深度学习模型变得可行。
-
显著加速计算:
- 由于二值化网络使用XNOR和计数操作代替传统的乘法和加法,这种操作在硬件上通常可以实现极快的并行计算,从而大幅度提高推理速度。
-
低功耗:
- 二值化操作相比于全精度计算所需的能量和资源更少,适合在低功耗环境下执行,如物联网设备和边缘计算场景。
c.挑战
虽然BNN在近5年来已经取得了很大的进步啦,但是比较大的问题就是精度的损失仍然是个头痛的问题,尤其是对于大型网络和数据集而言。主要原因可能包括:
1)目前还没有SOTA的二值化网络模型,不确定什么样的网络结构才合适做二值化;
2)即使有用于二值化的梯度估计或近似函数,在离散空间中优化二值网络是一个难题。
3.混合精度量化(Mixed-Precision Quantization)
混合精度量化是一种量化策略,旨在根据不同层对量化的敏感性,灵活地选择合适的量化精度。这种方法能够在模型的存储和计算效率与精度之间取得更好的平衡。
a.基本原理
在深度学习模型中,并非所有层对量化的敏感程度相同。一些层(如卷积层)可能对量化的反应比较敏感,而其他层(如全连接层)可能对量化的影响较小。混合精度量化通过分析各层的特点,动态地选择合适的量化精度,以最大限度地减少精度损失,同时降低计算和存储需求。
b.具体实现
-
层级分析:
- 对于每一层,首先进行量化敏感性分析,评估其对量化的反应程度。可以通过训练和验证阶段的实验,观察不同层在不同量化精度下的表现。
-
量化策略:
- 根据分析结果,为每一层选择适当的精度。例如,某些敏感层可以使用较高的精度(如FP16),而其他层可以采用较低的精度(如INT8或更低)。
-
强化学习反馈:
- 混合精度量化也可以结合强化学习,动态收集反馈,通过试验与调整的方式不断优化各层的量化策略。借助强化学习算法,能够在延迟和精度之间自动获得最佳平衡。