AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


LLM PTQ 量化经典研究解析
发布日期:2024-06-19 08:15:45 浏览次数: 3149 来源:吃果冻不吐果冻皮





本文主要对近年流行和经典的LLM PTQ量化算法论文进行一些汇总和分析。由于每篇详解的文章很多,本文不会逐篇做非常细致的讲解,主要对LLM量化算法的发展演进和核心思想方法做一些归纳,希望能触发一些思考和讨论。

GPTQ

GPTQ: ACCURATE POST-TRAINING QUANTIZATION FOR GENERATIVE PRE-TRAINED TRANSFORMERS (https://arxiv.org/abs/2210.17323)

Code: https://github.com/IST-DASLab/gptq

Type:W4A16

首先介绍GPTQ,它在LLM PTQ方向的历史地位已经毋庸置疑了,因其出色的效果得到广泛应用。它的背景非常悠久(OBD->OBS->OBQ->GPTQ),从最早的 Yann LeCun 在 1990 年提出的 OBD 算法,到 OBS、OBQ算法,再到GPTQ ,也算是站在巨人的肩膀上。GPTQ的出发点很朴素,就是试图最小化weight量化后和量化前的层函数误差,经过一系列复杂的数学求解后结果如下所示,代表最优先进行量化的weight,代表对剩下权重的更新,H是二阶的Hessian matrix(海森矩阵),这样量化误差会最小。

论文里关于数学公式推导描述地比较简单,详细数学推理公式可以参考文章杨远航:QLoRA、GPTQ:模型量化概述 (https://zhuanlan.zhihu.com/p/646210009) 。求解出来后,GPTQ的做法就是对每个weight进行逐步量化,每组参数量化后需要适当调整其他未量化的参数,以弥补量化造成的error,而弥补的数值需要参考最优化求解的结果。为了加速量化过程,GPTQ还做了一些优化,主要有:

  1. 舍弃了筛选参数进行量化的贪心策略,直接顺序方式对所有参数进行量化。

  2. 在量化-更新-量化-更新的迭代中使用批处理更新从而延迟一部分参数的更新,缓解 I/O 压力。

  3. 用 Cholesky 分解求海森矩阵的逆,在增强数值稳定性的同时,不再需要对海森矩阵做更新计算,进一步减少了计算量。

最终算法描述如下,详细的代码解析可以参考进击的Killua:GPTQ & SmoothQuant & AWQ 代码解析 (https://zhuanlan.zhihu.com/p/697860995)。GPTQ很好地解决了weight优化的问题,所以在开源社区多数大模型都有其对应的GPTQ 量化实现,但是它没有涉及解决异常值问题和 Activation 量化(给后人留了空间),而且利用calibration set进行量化的过程中存在一定过拟合风险。

LLM.int8()

LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale (https://arxiv.org/abs/2208.07339)
Code: https://github.com/TimDettmers/bitsandbytes
Type:W8A8
然后出自NeurIPS 2022的LLM.int8(),也是里程碑式的一篇文章,它没有复杂的计算公式,但提出的关于离群点的发现和度量具有深远的意义,影响了后续一系列的优化,基于此它以近乎无损的精度而闻名于业界。值得一提的是这篇文章的作者Tim Dettmers是模型量化压缩方向的大牛,出品了多篇高质量论文,有时间可以仔细阅读。

LLM.int8()发现LLM规模变大后会出现少量非常重要的离群点(即异常值),这些点对attention效果有较大影响,同时对量化带来挑战

论文的核心思想非常简单直接,就是分而治之。通过离群(Outlier)检测,把输入X和权重W中包含异常值的行、列挑选出来直接做fp16的浮点矩阵乘法,然后剩下的正常点用矢量化方法(X每一行用absmax进行量化、W每一列用absmax进行量化)量化后进行int8乘法再反量化回fp16,最后把它们累加起来作为最终结果输出,如下图所示。

这种简单的处理方式当然也会带来一些问题,比如离群点的检测、拆分以及合并会带来一些额外的计算开销,同时随着离群点增多混合精度的计算复杂度会显著提升,对性能提升的幅度会明显下降。当然这只是个开端,后面有很多研究是围绕这些优化展开的。

SmoothQuant

SmoothQuant: Accurate and Efficient Post-Training Quantization for Large Language Models (https://arxiv.org/abs/2211.10438)

Code:https://github.com/mit-han-lab/smoothquant  、https://github.com/Guangxuan-Xiao/torch-int

Type:W8A8

SmoothQuant是MIT 韩松老师实验发表的,已经集成到Pytorch、TensorRT-LLM等框架中成为W8A8的业界主流。它发现权重比较容易量化,激活值不易量化,因为有前文提到的离群值,激活值中某些channel异常地高。那么对激活值用per-channel的方式进行量化精度下降可能会比较小,但是这样就无法很好地使用TensorCore进行硬件加速了。于是作者就提出先用smooth的方式对weight和channel维度activation进行调整,平滑后就比较容易量化了,如下图所示。

猜测作者可能是借鉴了Cross Layer Equalization (https://arxiv.org/abs/1906.04721)论文的思想在LLM上也撸了一遍,这种平滑的处理方式其实在做常规PTQ量化的同学已经想到过了,只不过面向的场景不太一样,CLE是在不同layer之间做smooth,而这里是在权重和激活值上做smooth。平滑的具体做法如下所示,在激活值上进行缩放,同时在权重上进行扩增,这样总的结果是保持不变的,但是计算时候激活值的波动就变小了,这里还有个超参用来调整缩放的大小。详细的代码解析可以参考进击的Killua:GPTQ & SmoothQuant & AWQ 代码解析(https://zhuanlan.zhihu.com/p/697860995)

AWQ

AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration (https://arxiv.org/abs/2306.00978)

Code:https://github.com/mit-han-lab/llm-awq

Type:W4A16

AWQ是一种LLM低比特权重量化方法,MLSys 2024的best paper,也是韩松老师实验室发表的,可以认为是当前W4A16的SOTA,已经被应用到很多低比特量化框架中,如TensorRT-LLM、FastChat、vLLM、TGI、LMDeploy。它和SmoothQuant有些像,只是SmoothQuant侧重于对matrix multiplication场景的weight和activations进行INT8量化(W8A8),而AWQ关注在low bit(INT4) weight量化(W4A16),主要被应用在linear layer(包含最多的参数),详细的代码解析可以参考进击的Killua:GPTQ & SmoothQuant & AWQ 代码解析 (https://zhuanlan.zhihu.com/p/697860995)

它核心的贡献:

  1. 发现weight对模型的重要程度存在极强的不均衡性,1%的参数可能主导的量化过程中损失的性能,假如我们在量化中保护这1%的参数,就能极大程度保护模型性能不受影响,但是混合精度(FP16+低比特)对硬件不友好。

  2. 那么如何发现重要weight?不用权重!用激活值来发现重要的weight

  3. 不用混合精度的话如何保护重要weight?对weight进行per-channel的scale同时对激活值除以scale

  4. 如何确定最合适的scale?量化误差函数不可微,没法用梯度下降求解,所以退而减少搜索空间取和激活值相关的值进行grid search,找到那个让量化误差最小的scale

最优化的目标

简化的scale搜索空间

ZeroQuant系列

ZeroQuant: Efficient and Affordable Post-Training Quantization for Large-Scale Transformers(https://arxiv.org/abs/2206.01861)

ZeroQuant-V2: Exploring Post-training Quantization in LLMs from Comprehensive Study to Low Rank Compensation(https://arxiv.org/abs/2303.08302)

ZeroQuant-FP: A Leap Forward in LLMs Post-Training W4A8 Quantization Using Floating-Point Formats(https://arxiv.org/abs/2307.09782)

ZeroQuant-HERO: Hardware-Enhanced Robust Optimized Post-Training Quantization Framework for W8A8 Transformers(https://arxiv.org/abs/2310.17723)

Code:https://github.com/microsoft/DeepSpeed

ZeroQuant系列其由微软DeepSpeed团队于2022年推出,是一个端到端的量化推理流水线,具有很强的工程实践特性,至今已经发展成了一个系列量化算法,应用还是比较广泛的。

第一版的ZeroQuant主要包含以下三个方法:

  1. 对weight进行per-group量化,对activiation应用per-token的动态量化,兼顾了性能和精度。

  2. 使用了逐层知识蒸馏来提取量化网络,降低了显存开销。

  3. 使用cutlass prelogue进行量化算子fuse,使用epilogue进行反量化算子fuse,降低量化带来的性能损失。

第二版ZeroQuant-V2更多的是一些分析和总结,它分析了权重量化和激活值量化对精度的敏感性,比较了常用PTQ算法的模型效果,最后引入了一种称为低秩补偿(LoRC)的优化技术,它可以与 PTQ 的协同工作,以最小的模型参数大小的增加来改善整个模型质量的恢复,但这种方法的扩展性似乎不是很好。

第三版ZeroQuant-FP主要探索了浮点(FP)量化的可行性,特别关注FP8和FP4格式。对于LLM,FP8激活在性能上优于INT8,而在权重量化方面,FP4在性能上与INT4相比具有可比性,甚至更优越;LoRC有助于提升W4A8的整体表现。同时为了解决由权重和激活之间的差异(从FP4到FP8)引起的挑战,ZeroQuant-FP要求所有缩放因子为2的幂,并将缩放因子限制在单个计算组内。

第四版ZeroQuant-HERO是一种新的硬件增强型训练后 W8A8 量化框架,它考虑了内存带宽限制和计算密集型运算,总体偏工程方向,将transformer中更多子模块进行了量化改造,分别是:Embedding层量化、Attention模块量化、MLP 模块量化,同时采用不同量化精度对各个模块进行量化组合,按需选取量化等级。

SpQR

SpQR: A Sparse-Quantized Representation for Near-Lossless LLM Weight Compression(https://arxiv.org/abs/2306.03078)

Code: https://github.com/Vahe1994/SpQR

Type: W4A16

SpQR和LLM.int8()是同一作者,也是Tim Dettmers提出的,它有点像AWQ+GPTQ+LLM.int8()的混合体,整体上还是比AWQ复杂很多。它也像AWQ一样发现了weight对模型的重要程度存在极强的不均衡性,1%的参数可能主导的量化过程中损失的性能这一事实。但是它对识别敏感weight和保护敏感weight的做法和AWQ不一样,更像是GPTQ和LLM.int8()的做法。

首先它用类似OBC(Optimal Brain Compression)的方式来计算参数的敏感度,求解结果如下所示。

通过统计发现了敏感weight位置分布的一些特性,大多具有特定的结构(行、列、注意力头、非结构化等),为此SpQR对两类weight进行特殊处理:敏感值group和单个异常值,然后将它们存储在更高的精度中;将所有其他权重压缩为3-4比特。利用这些发现提出一个压缩表示,可以支持所有这些不同的离群值类型。

该压缩表示的内容为:

  1. dense的普通权重(低比特量化)

  2. group的量化敏感权重值(高精度)

  3. sparse的离群单点(高精度)

下图是单个weight张量的 SpQR 表示的高级概述,右侧描述了所有存储的数据类型及其维度。作者还为 SpQR 格式设计了一个基于 GPU 的高效解码实现。SpQR效果还是挺好的,在某些大模型上的效果比AWQ还要好一些,但它比AWQ复杂性高出很多,所以应用广泛度不及AWQ。

OWQ

OWQ: Outlier-Aware Weight Quantization for Efficient Fine-Tuning and Inference of Large Language Models (https://arxiv.org/abs/2306.02272)

Code: https://github.com/xvyaward/owq

Type: W4A16

OWQ也是延续了LLM.int8()和GPTQ的思想,weight的某些channel特别敏感最好使用fp16来存储,但是OWQ的筛选的方法是使用类似GPTQ的海森矩阵,而不是LLM.int8的outlier feature统计。OWQ对交叉维的每个channel计算敏感度指标如下:

其中是海森矩阵的第j个对角线元素。选择敏感度最大的top-k看成weak columns转化为fp16存储,其余部分用GPTQ的低比特方案存储(例如4比特),本质上也是混合精度的方式。具体操作如下:

  • 把原始 转换成全量的低比特矩阵,weak column(敏感列)用0填充。

  • 单独额外存储fp16的weak columns列,并且把列号附在最后一个元素后面。

论文同时提出对特定任务的finetune采取对低比特矩阵冻结,仅对weak column微调的方式来进行,能够做到在保持精度的同时节省内存开销的目的。

SqueezeLLM

SqueezeLLM: Dense-and-Sparse Quantization(https://arxiv.org/abs/2306.07629)

Code:https://github.com/SqueezeAILab/SqueezeLLM

Type: W4A16

SqueezeLLM也是一个权重量化算法,它基于的事实也已成为标准,即

  1. LLM模型推理的主要瓶颈是带宽,存在内存墙。

  2. 权重存在不同敏感度,少量权重非常敏感需要针对性进行量化。

和之前的AWQ、SpQR等的区别体现在:

1. 它采用近似的Fisher information来度量敏感度,这是一种新的度量方式。然后基于敏感度进行低比特非均匀量化,使用kmeans聚类来生成靠近敏感值的量化定点,其它点以MSE最小来安置,从而最小化量化误差。

2. 稠密和稀疏分解,高效的稀疏格式来存储outlier和敏感权重(FP16),稠密格式来存储大量的低比特常规权重值。分别开发了kernel来处理稠密和稀疏的矩阵向量乘kernel。

在困惑度方面,战胜了RTN,GPTQ,AWQ这些权重量化的方法,但是在加速与内存节省方面稍逊于GPTQ。

RPTQ

RPTQ: Reorder-based Post-training Quantization for Large Language Models(https://arxiv.org/abs/2304.01089)

Code: https://github.com/hahnyuan/RPTQ4LLM

Type: W4A4/W4A8/W4A4KV

RPTQ主要研究的是激活值的量化,它发现即使除去outlier,不同channel的range变化还是很大,如果用per-tensor的方式去量化误差较大,而per-channel的方式执行效率低,所以采取折中的方式per-group量化。

RPTQ的主要思想是对激活值的channel进行kmeans聚类重排,把(min,max)近似的channel聚成一个group,在这个基础上进行量化

内存重排的开销还是比较大的,为了减少这部分开销提出了一些工程优化:

  1. 把重排操作融入到了layernorm层中,这个想法比较简单,直接在layernorm刷回内存时按新排序的index进行写入。

  2. 调整了weight顺序,允许线性层直接接受重排的激活值,同时自身也输出重排的激活值。

  3. 矩阵乘和线性层也都需要input channel对齐。

transformer block的reorder如图所示。整个流程稍微有点绕,真正要落地到LLM大规模工程实践还有一些工作要做。


ATOM

ATOM: LOW-BIT QUANTIZATION FOR EFFICIENT AND ACCURATE LLM SERVING(https://arxiv.org/pdf/2310.19102)

Code: https://github.com/efeslab/Atom

Type: W4A4

ATOM几乎是W4A4类型的SOTA,也是之前各项工作的集大成者,提出了一系列针对LLM特性的量化策略和工程实践:

1. 进行混合精度量化,outlier activation值使用INT8,normal值使用INT4,复用了RPTQ的reorder方法对outlier进行重排并进行了算子融合。

2. 对weight和activation中的normal值使用group量化,由于各group scale不一致,所以先分别计算各group的中间结果,再反量化为fp16计算最终结果。为了降低计算开销也使用了融合GEMM技术。

3. 为提高精度对激活值进行动态量化,减少计算开销的方式也是采用了前算子融合的技术。

4. 对KVCache进行低比特非对称量化,在FP16计算前进行反量化。


OliVe

OliVe: Accelerating Large Language Models via Hardware-friendly Outlier-Victim Pair Quantization(https://arxiv.org/abs/2304.07493)

Type:W4A4

Olive从硬件层面上对离群值的计算进行了优化,之前的离群值感知量化方案采用的基本都是稀疏编码技术,即将离群值与正常值分开存储,其中过程需要全局协调。这将导致复杂的编码和解码硬件逻辑,它不是硬件最优的。OliVe提出了一个硬件友好地处理离群值和正常值的方式,它关键发现是离群值是重要的,而它们旁边的正常值则不太重要,因此可以牺牲这些正常值(称为受害者)以适应离群值,以本地化的方式处理离群值,提高硬件效率

OliVe首先将与离群值相邻的正常值修剪为零。这些被修剪过的正常值被称为受害者,为离群值腾出了空间。然后,我们利用受害者提供的额外空间,将异常值嵌入到低精度矩阵中,如下图所示。

Olive将这里的encoder和decoder过程做的非常精细,从硬件层面进行了架构设计,一般想要复现论文效果技术门槛很高,但这个算法和硬件架构协同设计的实现方案确实威力巨大,可以看看后续硬件架构的演进路线。

encodder时对(outlier, victim), (outlier,outlier),(normal,normal)pair进行分别处理,设计了victim的identifier, 设计了normal的数据类型(int4,fint4,int8),为outlier设计了专门的数据格式abfloat,关键思想是通过向指数上添加适当的偏差,所有编码值都可以跳过normal所在的区间,为outlier提供更多的范围。

deocder时对TensorCore等硬件特性进行了充分集成,使用Verilog设计了门电路进行解码、设计了针对(outlier,victim) pair的矩阵乘指令,优化层级非常深


Outlier Suppression

Outlier Suppression: Pushing the Limit of Low-bit Transformer Language Models(https://arxiv.org/abs/2209.13325)

Outlier Suppression+: Accurate quantization of large language models by equivalent and optimal shifting and scaling(https://arxiv.org/abs/2304.09145)

Code:

https://github.com/wimh966/outlier_suppression

https://github.com/ModelTC/Outlier_Suppression_Plus

Type: W8A8

之前的量化算法基本上都是对outlier进行保护处理以保证它对精度的影响,而outlier suppression做法相反,它另辟蹊径地想要抑制outlier对最终精度的影响。论文发现:

1.LayerNorm结构中的尺度参数γ作为一个离群值放大器,它放大了输出中的离群值。

2. 一些覆盖大面积的更激进的离群值可以被安全地剪切,不会降低精度。

于是它提出的优化手段:

  1. Gamma Migration,通过将离群值放大器γ迁移到后续模块中来产生一个更易于量化的模型,有点像smoothquant。

  2. 对outlier进行token-wise的剪切能够有效地找到一个使最终量化损失最小的剪切范围。

而outlier suppression+发现了异常值的一个新特征,即它们在不同通道间保持不对称的形状,这种离群的不对称呈现可能导致Tensor更广泛分布,更难于量化。于是它提出了通道shift+通道scale的操作来改造activation的分布,同时引入了一个统一的迁移模式,将这些操作的影响转移到后面的模块中,以维护等效的浮点运算逻辑,如下图所示。本质上其实和SmoothQuant的方向是一致的,让weight和activation做等效变化从而让它们更易于量化,只是outlier suppression+手段显得更有力一些,在多个模型和评测集上也超过了SmoothQuant的效果。


总结

本文提到的PTQ量化算法分类如下所示:

TypeW4A16W8A8W4A4
AlgorithmGPTQ
AWQ
SpQR
OWQ
SqueezeLLM
LLM.int8()
ZeroQuant
SmoothQuant
outlier suppression+
RPTQ
ATOM
Olive

从这些研究可以看出LLM PTQ量化方向已经形成了不少共识性的方法和研究方向。

对于权重量化,一个共识是需要区分不同的敏感度来进行差异性量化,而敏感度的度量和处理方式各有千秋。有用激活值来进行度量,有用Hessian矩阵进行度量的,有用近似的Fisher information来度量;而处理方式上有平滑的方式,有混合精度稠密稀疏分解的表示方式,以及围绕混合精度设计不同的硬件友好的表示方式。

对于激活值量化,一个共识需要对离群值做特殊处理,处理的方式有平滑的方式、内存重排的优化方式和混合精度的处理方式,甚至还有裁剪的方式,这些都能在一定程度上降低量化的难度,进而减少离群值对精度的影响。

工程实现上也有了大量的实践,最常用的量化、反量化算子融合和重排算子融合就是其中的代表。

以上方法都能够比较好地解决权重和激活值量化的问题,然而算法应用的广泛度不仅仅取决于算法的效果,易用性和简单性也是不可忽视的重要因素,这里AWQ就是一个比较好的例子,效果不错且应用简单因而得到较为广泛的推广。

随着LLM模型体量的增大相信接下来还会有更多W4A4类型的低比特量化算法出现,同时能够基于硬件进行深度优化,在保持精度的前提下进一步降低推理耗时,让我们拭目以待。


53AI,企业落地应用大模型首选服务商

产品:大模型应用平台+智能体定制开发+落地咨询服务

承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

与创始人交个朋友

回到顶部

 
扫码咨询