- 1. 参考
- 2. OBD
- 3. OBS
- 4. 从 OBS 到 OBQ
- 5. GPTQ Gradient PreTrained Quantity
1. 参考
GPTQ 量化技术演进:https://zhuanlan.zhihu.com/p/690834228?utm_id=0
OBS/OBD/GPTQ:https://www.cnblogs.com/wangbingbing/p/17547681.html
GPTQ使用的方法改进自OBC(Frantar, 2022),OBC来源于OBS(Hassibi, 1992),OBS来源于OBD(Lecun, 1990)
2. OBD
OBD 的基本思想是以模型训练损失
为目标函数,迭代地选择剪枝参数使目标函数Loss最小化。
设模型的权重为w,损失函数为f,则在当前权重下,模型的训练损失为 。
对损失函数进行泰勒展开可以估计权重调整造成的影响,对 进行泰勒展开:
其中:是 Hessian 矩阵
是剪枝后损失的变化量,显然越小越好
目标就是找到一个,使得最小。
一个训练好的神经网络模型,其损失一般都处于权重空间中的局部极小值,因此可以认为,因此式中的第一项可以忽略。另外再忽略高阶项,则上式可以简化为:
介绍 OBD 的一个重要假设
,为了进一步简化问题,OBD 认为 Hessian 矩阵是一个对角矩阵
--也就是只有对角线有元素,其他全为0,其含义是,同时剪枝多个权重参数对模型精度造成的影响,等于单独剪枝每个权重对模型造成影响之和
最终需要求解的问题就成了
3. OBS
OBS 受到 OBD 关于减小模型剪枝对损失函数影响
的启发,但是不同意 OBD 的假设。
认为权重剪枝之间是有关联的,所以不能简单地将 Hessian 矩阵假设为对角矩阵
再次分析:
假设对第q个参数进行剪枝,
也就是对应位置的权重置为0,
于是这里就变成了带约束的凸优化问题:
其中:约束条件可以写成更一般的形式:
第q个值为 1 的单位向量。
对于上述问题,可以使用拉格朗日乘子法来求解,定义拉格朗日函数:
对求导,并设置为 0
然后做如下变换:
- 对一个方程乘以
交换第二个方程的 ,:
-
第二个方程乘以
-
注意到并将第二个方程带入第一个方程
-
得到
-
第一个方程,解得
其中:
表示的第q列,
- 获得之后带入损失函数
得到:
可以找到当前最优的剪枝参数q,再使用公式计算所有权重的修正量,这就完成了一次迭代。不断找到需要剪枝的权重参数,直到达到剪枝的目标。
4. 从 OBS 到 OBQ
剪枝和量化都涉及到对权重值的修改,只不过剪枝是直接将权重设置为 0,而量化则是降低权重值的数值精度,比如将 fp32 数值变成 fp16,int8,int4 等
OBS 的思想可以很自然的应用到量化上来,这种方法也被称为OBQ (Optimal Brain Quantization),为了兼顾剪枝和量化,论文的标题就叫 OBC (Optimal Brain Compression)。
从这个公式出发:
在 OBS 中,对应的约束条件为,
索引为 q 的权重修改量为 ,
而在量化条件下,情况要复杂一点,
参考:https://arxiv.org/abs/2106.08295
量化实际上就是将浮点数权重转换为整数:
其中 表示缩放系数,
z表示零点偏移,
N表示最大整数值。
以为例,量化函数图像如下:
可以看到,该函数将浮点数权重分阶段地映射到了整数值上。
一个训练好的模型,对所有权重值应用量化变换,并保存好相应的参数,这就是经典的量化过程。
与量化过程对应的还有一个逆量化操作可以恢复原先的精度类型
量化后的权重实际上存在两种等价的表示形式,第一种是通过量化函数变换到的整数空间,第二种是通过逆量化函数变换到的浮点数空间。
对于 OBQ 来说,每量化一个权重值,需要调整剩余权重来最小化量化损失,但是我们不能直接在整数空间上调整(因为剩余权重都是浮点数),应该在浮点数空间上调整,
定义函数 quant先对权重进行量化,再逆量化,就得到浮点数空间上的量化值,
剪枝操作中的约束条件在这里就变成了
再次使用拉格朗日乘子法求解最小化问题,可以得到,
表示一行权重的修正量即
交替使用上面公式 就得到了量化版本的 OBC 算法 OBQ。
5. GPTQ Gradient PreTrained Quantity
OBQ 采用 row-wise 的权重量化方法,将 Hessian 矩阵求逆的复杂度降低到了
并且一个权重矩阵总的参数量为因此总体来说 OBQ 的时间复杂度为
虽然相对于 OBS 有了很大的改进,但对于大模型来说,OBQ 仍然是一个非常耗时的操作。
GPTQ 提出了两点改进来提高 OBQ 的量化效率,
首先是将每一行的量化权重选择方式从贪心策略改成按索引顺序选择,
其次是将权重更新方式修改为批量更新