模型压缩 --学习记录1
- 一、模型压缩的定义
- 二 、模型量化技术
- 2.1、线性量化 - 对称线性量化
- 对称线性量化的过程
- Step 1:确定量化范围(range)
- Step 2:计算缩放因子(scale)
- Step 3:执行量化
- 对称线性量化存在的问题
- 2.2、线性量化 - 非对称线性量化
- 非对称线性量化的过程
- Step 1:统计数据范围
- Step 2:计算缩放因子和零点
- Step 3:浮点数量化为整数
- 总结
- 2.3、非线性量化
- 2.4、动态量化(大语言模型经常使用)
- 动态量化 vs 静态量化
- 2.5、量化粒度
- 量化粒度的选择
一、模型压缩的定义
定义:让模型变得更小、更快、但是精度尽可能不下降。
模型压缩的常用方法:
- 量化
- 稀疏
- 蒸馏
- NAS
- 低秩分解
二 、模型量化技术
在神经网络中,量化是一种将模型参数(权重/激活)从高精度浮点数转换为低精度整数表示的技术。
2.1、线性量化 - 对称线性量化
- 线性量化:通过一个线性公式,将高精度的浮点数值映射到低精度的整数值中。其转换公式为:
q = round ( x s ) q = \text{round} \left( \frac{x}{s} \right) q=round(sx)
-
( q ):量化后的整数值。
-
( x ):原始的浮点数值。
-
( s ):缩放因子(scale),用来将浮点数缩小到目标整数的范围。
-
round:表示四舍五入到最近的整数。
-
对称量化:量化后的数值范围是对称的,例如,对于8位整数,量化值通常会位于 ([-127, 127]) 或 ([-128, 127]) 范围内。对称量化假设零点(zero point)为零,这使得正数和负数的量化是对称的。
对称线性量化的过程
Step 1:确定量化范围(range)
在量化之前,需要统计待量化数据(如权重或激活值)的范围,以确定数据的最小值和最大值。
遍历模型的每一层权重张量,找到权重的最小值 x_min
和最大值 x_max
。
示例:
假设某一层的权重值为 [-0.8, 0.4, 1.2, -1.0, 0.6]。
则 x_min = -1.0,x_max = 1.2。
Step 2:计算缩放因子(scale)
量化的关键在于将浮点范围映射到整数范围,而缩放因子(Scale)就是完成这种映射的比例因子。
公式如下:
s = x_max / Q_max
其中:
x_max 是数据的最大绝对值,即 max(|x_min|, |x_max|)
。
Q_max 是整数范围的最大值,比如对于 int8,Q_max = 127。
示例:
如果 x_min = -1.0,x_max = 1.2,则绝对范围为 x_max = 1.2。
对于 int8 格式,Q_max = 127,那么 s = 1.2 / 127 ≈ 0.00945。
注意:
对称量化中,缩放因子 s 是唯一的,不存在零点(zero-point),这与非对称量化不同
Step 3:执行量化
将浮点数值 x 映射到整数值 q 的过程称为量化,公式如下:
q = clip(round(x / s), -Q_max, Q_max)
步骤:
- 浮点值缩放:首先将 x 除以缩放因子 s,将浮点值调整到整数范围。
- 四舍五入:对于非整数结果,进行四舍五入操作。
- 将结果限制在整数范围内,即 [-Q_max, Q_max]。如果值超出了范围,则用边界值代替。
示例:
假设 x = 0.6,s = 0.00945,则 x / s = 0.6 / 0.00945 ≈ 63.49。
63.49 四舍五入为 63。
截断(Clipping):如果结果是 130,而 int8 的范围是 [-127, 127],则最终取值为 127。
对称线性量化存在的问题
- 会有无效映射区,没有完全的利用整数的表示范围
- 正负的半轴(range),谁大谁小没关系
- scale大于1还是小于1,取决于数值的范围,实际往往范围比较小,会小于1
2.2、线性量化 - 非对称线性量化
非对称线性量化不用再做范围扩充,最大值最小值分别表示整数表示的最大值和最小值。
非对称量化依赖两个核心参数:
- 缩放因子 (scale):将浮点范围映射到整数范围的比例。
- 零点 (zero-point):整数范围中对应浮点值零点的位置。
参数定义
缩放因子 (scale):s = (x_max - x_min) / (Q_max - Q_min)
其中:
x_max 是数据的最大值。
x_min 是数据的最小值。
Q_max 是量化范围的最大值,例如对 int8,Q_max = 127。
Q_min 是量化范围的最小值,例如对 int8,Q_min = -128。
零点 (zero-point):z = Q_min - round(x_min / s)
其中:
z 是整数范围内的零点位置。
s 是缩放因子。
非对称线性量化的过程
Step 1:统计数据范围
首先,统计权重或激活值的浮点数据范围:
- 输入数据:
x_min
:数据的最小值。x_max
:数据的最大值。
假设某层权重的范围为
[-1.2, 1.8]
,则:
x_min = -1.2
x_max = 1.8
Step 2:计算缩放因子和零点
缩放因子:s = (x_max - x_min) / (Q_max - Q_min)
零点 (zero-point):z = Q_min - round(x_min / s)
假设:
x_min = -1.2
x_max = 1.8
- 对 int8 类型,整数范围为
[-128, 127]
,即Q_min = -128
,Q_max = 127
。计算缩放因子: s = (1.8 - (-1.2)) / (127 - (-128)) s = 3.0 / 255 s ≈ 0.01176
计算零点: z = Q_min - round(x_min / s) z = -128 - round(-1.2 / 0.01176) z
= -128 - round(-102.04) z = -128 + 102 z ≈ -26最终结果:
- 缩放因子
s ≈ 0.01176
- 零点
z ≈ -26
Step 3:浮点数量化为整数
浮点数 x
映射到量化后的整数值 q
的公式:q = clip(round(x / s) + z, Q_min, Q_max)
clip()
:截断函数,用于确保结果在[Q_min, Q_max]
范围内。
假设:
- 浮点值
x = 0.5
- 缩放因子
s ≈ 0.01176
- 零点
z ≈ -26
- 对 int8 类型,整数范围为
[-128, 127]
。计算:
q = clip(round(0.5 / 0.01176) + (-26), -128, 127)
q =clip(round(42.5) - 26, -128, 127)
q = clip(43 - 26, -128, 127)
q = clip(17, -128, 127) q = 17
总结
非对称量化的完整步骤包括:
- 统计数据范围:确定输入数据的
x_min
和x_max
。 - 计算缩放因子和零点:
- 缩放因子:
s = (x_max - x_min) / (Q_max - Q_min)
- 零点:
z = Q_min - round(x_min / s)
- 缩放因子:
- 执行量化:通过公式
q = clip(round(x / s) + z, Q_min, Q_max)
。
2.3、非线性量化
因为量化是一种数据压缩的方式,压缩必然会带来信息损失;
对称量化的无效映射区会带来信息损失(非对称量化)
线性量化没有考虑数据不同部分的稠密和稀疏(非线性量化)
为了更好的解决数据分布的问题:分布稠密的部分,给予更多的量化bit位数
非线性量化是一种灵活且强大的量化方法,特别适合复杂分布的数据。常用的方法包括:
- 对数量化:处理动态范围大的数据。
- 分段量化:针对复杂分布的灵活量化。
- 非均匀量化:基于优化算法的聚类量化。
- μ-law 和 A-law:动态范围压缩,用于音频信号。
2.4、动态量化(大语言模型经常使用)
动态量化是一种在推理过程中动态决定或调整量化参数的策略。与静态量化不同,动态量化通常只对 权重 进行离线量化,而激活值的量化范围和参数是在推理过程中动态计算的。
核心思想:
- 权重量化:事先将权重从浮点格式(如 FP32)量化为低精度的整数(如 INT8)。
- 激活值量化:在推理时,根据每个输入的分布动态计算激活值的量化范围和参数。
动态量化 vs 静态量化
特性 | 动态量化 | 静态量化 |
---|---|---|
权重量化 | 离线量化(在训练后完成) | 离线量化 |
激活值量化 | 推理时动态计算量化范围 | 离线计算并固定的量化参数 |
量化精度 | 更灵活,适应输入数据的动态分布 | 固定,可能会受数据分布的变化影响 |
硬件支持 | 较少依赖于硬件特性(无需校准数据) | 需要硬件支持静态量化(校准过程复杂) |
2.5、量化粒度
量化粒度的选择
对于一堆数据,我们可以统一设置同样的一套量化参数(scale,zp),pre-Tensor量化
。
我们也可以将这堆数据先分成若干组,每个组内设置一套量化参数:
(1)按照channel维度去分组 pre-channel 量化
(2)更细粒度的去分组,以一个较小的group为一组 pre-Group量化
- 越细粒度的分组,带来的量化精度就越高,但是相对应的量化计算复杂度就会越高
- 权重 weight 是固定的,一般采用
pre-channel 量化
- 激活输入是在线变化的,一般采用
pre-Tensor量化
pre-Group量化
往往在大模型中的4bit 权重量化中应用