模型量化实战
在前面的实战章节中,为了在消费级显卡上加载大模型,我们已经初步体验了量化技术的魔力——只需几行代码配置 BitsAndBytesConfig,庞大的模型就能“塞”进显存。但你是否好奇,这背后的 int8 或 nf4 到底发生了什么?除了微调时用到的 BitsAndBytes,还有哪些量化技术更适合推理部署?
一、小资源干大活
1.1 冗余与压缩
量化,听起来是一个复杂的数学概念,但实际非常简单,就是用较少的信息来表示数据,在尽量不损失模型性能的前提下,降低资源开销。深度学习模型(无论是 CV 还是 NLP 领域)普遍表现出显著的参数冗余性。早在 1989 年,Yann LeCun 等人就在论文《Optimal Brain Damage》 1中指出神经网络中存在大量参数可以被删除而不影响准确率;而后续著名的“彩票假设”(The Lottery Ticket Hypothesis) 2更是进一步证明,密集网络中包含一个极小的子网络(“中奖彩票”),它的性能可与原始网络媲美。量化技术正是利用这一特性,通过降低非关键参数的数值精度(例如从 FP16 降至 INT4),在大幅减少显存占用和计算量的同时,尽可能保持模型的原始性能。
比如一张原本几十 MB 的高清无损照片(如 RAW 格式),在压缩为几百 KB 的 JPG 格式后,虽然丢失了大量人眼难以察觉的色彩细节(精度降低),但我们依然能清晰地识别出照片中的人物和风景。这种现象说明原始数据中包含大量对于“视觉理解”来说非必须的冗余信息。量化的过程也是类似,我们试图找出模型参数中那些对最终输出影响不大的微小精度,将其削减,在大幅降低显存占用的同时,保留模型的核心能力,实现**“瘦身不降智”**。
1.2 量化的价值
量化技术主要带来两方面的巨大收益:
(1)降低显存开销:通常模型以 FP16(16位浮点数)格式存储,若量化为 INT8(8位整数),显存占用直接减半;若进一步量化为 INT4(4位整数),显存占用仅为原来的 1/4。原本需要多张 A100 才能加载的千亿模型,量化后可能只需一张消费级显卡即可运行。
(2)提升推理速度:数据量的减少意味着内存带宽(Memory Bandwidth)压力的降低。在 LLM 推理这种典型的“内存受限(Memory-bound)”场景下,更快的权重加载速度直接转化为更快的 Token 生成速度。
二、从“装不下”到“跑得动”
2.1 精度与显存的关系
模型权重通常以浮点数形式存储,不同的精度决定了每个参数占用的字节数:
- FP32(Full Precision):单精度浮点数,占用 4 Bytes。这是深度学习训练的默认精度,但在推理时通常不需要这么高。
- FP16 / BF16(Half Precision):半精度浮点数,占用 2 Bytes。
- FP16:传统的半精度,数值范围较小,容易溢出。
- BF16(BFloat16):Google 提出的格式,牺牲了小数位精度以换取与 FP32 相同的数值范围(指数位),训练更稳定,是目前大模型训练的主流选择。
- INT8:8 位整数,占用 1 Byte。
- INT4:4 位整数,占用 0.5 Byte(即 4 bit)。
2.2 显存估算公式
在动手实践之前,我们需要学会如何估算一个模型到底需要多少显存。在计算机存储单位中,1 GB = 1024 MB,1 MB = 1024 KB。但在估算模型参数量(如 7B = 7 Billion)和显存(GB)时,为了方便,通常近似认为 $1 \text{ GB} \approx 10^9 \text{ Bytes}$。如果追求精确计算,记得除以 $1024^3$。模型所需显存大小的通用估算公式如下:
$$ \text{权重显存占用} \approx \text{模型参数量} \times \text{每参数占用字节数} \tag{13.1} $$以我们之前学习过的 Qwen2.5 为例,这里选择 Qwen2.5-7B(约 70 亿参数,即 $7 \times 10^9$):
(1)FP16 / BF16 精度(2 Bytes/参数):
$$ 7 \times 10^9 \times 2 \text{ Bytes} \approx 14 \text{ GB} \tag{13.2} $$(2)INT8 量化(1 Byte/参数):
$$ 7 \times 10^9 \times 1 \text{ Byte} \approx 7 \text{ GB} \tag{13.3} $$(3)INT4 量化(0.5 Byte/参数):
$$ 7 \times 10^9 \times 0.5 \text{ Byte} \approx 3.5 \text{ GB} \tag{13.4} $$这只是模型权重的静态占用。实际运行时,还需要预留显存给:
- KV Cache:上下文缓存,与序列长度(Context Length)成正比,上下文越长,占用越大。
- 激活值:中间层计算结果,与 Batch Size 和序列长度相关。
- 框架开销:PyTorch / CUDA context 本身会占用一定开销。
所以,实际显存需求通常比估算值高 20%~30%。例如加载 7B 的 INT4 模型(3.5GB 权重),推荐显存至少 6GB 起步。
三、Transformers 中的主流集成方案
虽然量化方法层出不穷,但在 Hugging Face Transformers 的官方文档与实践中,最常用的三类集成方式是加载 GPTQ、AWQ 以及 bitsandbytes(bnb)。在代码层面,它们通常通过 AutoModel*.from_pretrained(..., quantization_config=...) 搭配相应的配置类(如 GPTQConfig、AwqConfig、BitsAndBytesConfig)实现相对统一的调用体验。
如果从使用场景来区分,GPTQ 和 AWQ 主要面向推理部署与加速,它们属于 PTQ(Post-Training Quantization)算法,生成的模型通常以量化后的检查点形式保存,加载后显存占用低且推理速度快。bitsandbytes 则既常用于 8bit/4bit 推理,也是诸如 QLoRA 在内的一系列低显存微调方案的核心依赖,尤其擅长让大模型在单卡上完成 4-bit 训练。
3.1 面向生成式模型的高效量化
GPTQ (Generative Pre-trained Transformer Quantization) 3是一种面向大规模生成式 Transformer 的训练后量化(Post-Training Quantization, PTQ)技术。它是经典的 OBQ (Optimal Brain Quantization) 算法在超大模型上的高效进化版,基于近似二阶信息实现了一次性权重量化(one-shot weight quantization)。GPTQ 解决了以往简单的“四舍五入”(Round-to-Nearest, RTN)量化在模型参数超过百亿级时会导致严重精度崩塌的问题,成功将 1750 亿参数的超大模型压缩至 3-bit 或 4-bit,且几乎不损失精度。
GPTQ 的量化目标是最小化量化前后激活值的平方误差:
$$ \min_{\widehat{\mathbf{W}}} \| \mathbf{WX} - \widehat{\mathbf{W}}\mathbf{X} \|_2^2 \tag{13.5} $$其中,$\mathbf{W}$ 为原始权重矩阵,$\mathbf{X}$ 为输入激活值矩阵,$\widehat{\mathbf{W}}$ 为量化后的权重矩阵。
GPTQ 的成功依赖于三个关键机制:
(1)二阶信息补偿:它利用海森矩阵(Hessian Matrix,$\mathbf{H} = 2\mathbf{X}\mathbf{X}^\top$)的二阶信息来判断权重的重要性。这就是识别“冗余参数”的重要数学工具。海森矩阵描述了损失函数曲面的曲率,如果某个权重方向上的曲率很小(平坦),说明该权重的微小变化对总误差影响不大,它是相对“冗余”的;反之则是“关键”参数。GPTQ 利用其逆矩阵 $\mathbf{H}^{-1}$ 来更新剩余权重,以补偿当前权重量化带来的误差 $\delta$:
$$ \boldsymbol{\delta}_F = - \frac{w_q - Q(w_q)}{[\mathbf{H}_F^{-1}]_{qq}} \cdot (\mathbf{H}_F^{-1})_{:, q} \tag{13.6} $$其中,$w_q$ 是当前被量化的权重,$Q(w_q)$ 是其量化值,$\boldsymbol{\delta}_F$ 是对剩余未量化权重集合 $F$ 的更新向量,$\mathbf{H}_F^{-1}$ 是对应当前未量化权重的海森矩阵逆矩阵。
这里给出的只是 GPTQ 在分块/局部参数子集上的近似更新形式,省略了部分实现细节,主要是理解它利用二阶信息做误差补偿的思想。
(2)任意顺序与延迟批量更新:GPTQ 发现大模型不需要像 OBQ 那样进行昂贵的“贪心排序”,只需按顺序量化即可。同时,它引入了 Lazy Batch-Updates(延迟批量更新) 策略,将计算密集型的更新操作分块执行(如 128 列为一组),大大提升了 GPU 利用率。
(3)Cholesky 分解:为了解决大模型下海森矩阵逆计算的数值不稳定性问题,GPTQ 引入了 Cholesky 分解,确保了算法在千亿参数规模下的稳健运行。
GPTQ 的量化过程是分块进行的。如图 13-1,加粗的列块(Block)表示当前正在处理的列。左侧灰色部分是利用 Cholesky 分解预先计算好的逆 Hessian 信息。在处理当前块(橙色部分)时,算法会递归地逐列量化(中间白色列),并将量化误差利用预计算的 Hessian 信息“推”给后续未量化的权重(右侧蓝色部分)进行更新补偿,从而最大程度保留模型精度。

图 13-1 GPTQ 量化过程示意图
得益于上述优化,GPTQ 能以极快的速度(如 1750 亿参数仅需 4 小时)完成量化。实验表明,模型规模越大,GPTQ 带来的相对精度损失反而越小。如图 13-2,在 OPT 模型家族中,随着参数量增加(横轴向右),传统 RTN 方法(蓝线)的困惑度(PPL)急剧上升,意味着模型“崩了”;而 GPTQ(红线)则紧贴全精度基线(黑虚线),展现了极强的鲁棒性。生成的 INT4 模型配合 ExLlama 等专用内核,推理速度可达 FP16 的 3~4 倍。

图 13-2 GPTQ 与 RTN 在不同规模模型上的 PPL 对比
3.2 激活感知权重量化
AWQ (Activation-aware Weight Quantization) 4 提出了一种更符合直觉且高效的量化思路,特别适合端侧部署。与 GPTQ 依赖复杂的二阶信息进行误差补偿不同,AWQ 另辟蹊径,发现权重的“重要性”并不取决于权重本身的大小,而取决于它所处理的激活值的大小。实验表明,仅保留 1% 的“显著权重”(即对应激活值较大的通道)为 FP16 精度,就能极大恢复模型性能。有趣的是,如果按权重本身的 L2 范数来选这 1%,效果和随机选差不多;但如果按激活值幅值来选,效果立竿见影。
为了工程落地,AWQ 并没有真正把这 1% 的权重存成 FP16(混合精度会拖累推理速度),而是采用了一种精妙的数学等价变换。如图 13-3 所示,(a) 中简单的 RTN 量化导致 PPL 高达 43.2,模型基本“报废”;(b) 展示了如果保留 1% 显著权重为 FP16,PPL 能降回 13.0,但混合精度效率低。AWQ 的做法是 (c):找出那些对应较大激活值的权重通道,给它们乘上一个放大系数 $s$(Scale up),同时在输入 $x$ 上除以 $s$。
原理:在不改变线性层输出(例如 $y = \mathbf{w}\mathbf{x}$)的前提下,将“重要通道”的权重按系数 $s$ 放大、并将对应输入按 $1/s$ 缩小,使得整体计算在数学上保持等价,但被放大的权重在量化时的相对误差更小。
效果:当权重被放大后,其数值范围变大,相对量化误差(Relative Quantization Error)就会变小。AWQ 的优化目标是找到一组最优的缩放因子 $\mathbf{s}$,使得量化误差最小:
$$ \mathbf{s}^* = \arg \min_{\mathbf{s}} \mathcal{L}(\mathbf{s}) \tag{13.7} $$$$ \mathcal{L}(\mathbf{s}) = \| Q(\mathbf{W} \cdot \text{diag}(\mathbf{s})) (\text{diag}(\mathbf{s})^{-1} \cdot \mathbf{X}) - \mathbf{WX} \| \tag{13.8} $$其中,$Q(\cdot)$ 表示量化函数,$\mathbf{W}$ 为原始权重,$\mathbf{X}$ 为输入特征,$\mathbf{s}$ 为我们需要寻找的最佳缩放因子向量,$\text{diag}(\mathbf{s})$ 是由 $\mathbf{s}$ 构成的对角矩阵。这就好比用一把尺子去量物体,把物体放大后再量,读数的相对精度自然就高了。最终 AWQ 在全 INT 量化下也能达到与混合精度相当的性能(PPL 13.0)。

图 13-3 AWQ 量化原理示意图:(a) RTN 导致精度崩塌;(b) 混合精度效果好但效率低;(c) AWQ 通过等价缩放实现全 INT 量化下的高性能
通过表 13-1 的实验结果可以看到,在 Llama-2-7B/13B/70B 等不同规模的模型上,AWQ(W4-g128)的困惑度始终低于 RTN 和 GPTQ。特别是在 70B 模型上,AWQ 的 INT4 量化效果(PPL 3.41)几乎与 FP16 全精度基线(PPL 3.32)持平,证明了其在保护模型性能方面的优越性。
| PPL ↓ | Llama-2 | LLaMA | ||||||
| 7B | 13B | 70B | 7B | 13B | 30B | 65B | ||
| FP16 | - | 5.47 | 4.88 | 3.32 | 5.68 | 5.09 | 4.10 | 3.53 |
| INT3 | RTN | 6.66 | 5.52 | 3.98 | 7.01 | 5.88 | 4.88 | 4.24 |
| GPTQ | 6.43 | 5.48 | 3.88 | 8.81 | 5.66 | 4.88 | 4.17 | |
| g128 | GPTQ-R | 6.42 | 5.41 | 3.86 | 6.53 | 5.64 | 4.74 | 4.21 |
| AWQ | 6.24 | 5.32 | 3.74 | 6.35 | 5.52 | 4.61 | 3.95 | |
| INT4 | RTN | 5.73 | 4.98 | 3.46 | 5.96 | 5.25 | 4.23 | 3.67 |
| GPTQ | 5.69 | 4.98 | 3.42 | 6.22 | 5.23 | 4.24 | 3.66 | |
| g128 | GPTQ-R | 5.63 | 4.99 | 3.43 | 5.83 | 5.20 | 4.22 | 3.66 |
| AWQ | 5.60 | 4.97 | 3.41 | 5.78 | 5.19 | 4.21 | 3.62 | |
表 13-1 不同量化方法在 LLaMA/Llama-2 上的 PPL 对比
在 LLaMA、Mistral 等模型上,AWQ 的 INT4 量化几乎能达到 FP16 的无损性能水平。而且它具有端侧友好性,配合论文提出的 TinyChat 推理框架,作者展示了在高配 Jetson Orin 上以小 batch 形式运行 Llama-2-70B 的可能性;在树莓派等资源更受限的设备上,理论上也可以以 INT4 形式跑 7B 模型,但整体更偏 Demo/实验性质,速度和体验都会受到一定限制。
3.3 BitsAndBytes (BNB)
在前面的实战中,我们其实已经尝试使用了 BNB,通过配置 BitsAndBytesConfig 轻松实现了 4-bit 量化加载。如果说 GPTQ 和 AWQ 是侧重于“精打细算”的量化算法,那么 BNB 则是承载了 LLM.int8() 5和 QLoRA 等前沿研究的工程基石。它不仅是一个底层的 CUDA 库,更包含了一整套处理大模型量化难题的解决方案。BNB 的主要贡献是解决了大模型量化中一个棘手的**“离群值”问题。研究发现,当模型参数规模超过 67 亿(6.7B)时,Transformer 层中会系统性地涌现出少量数值巨大的离群特征(Emergent Outliers)**。虽然这些特征只占所有参数的约 0.1%,但它们对模型性能非常重要。传统的 8-bit 量化会将这些巨大的数值强制截断或粗糙量化,导致模型精度瞬间崩塌(如困惑度暴增)。如图 13-4,在 6.7B 参数规模处,普通 8-bit 量化(橙线)的准确率急剧下降,而 LLM.int8()(蓝线)则保持了与 16-bit 基线一致的性能。

图 13-4 模型规模与量化性能的关系
LLM.int8() 解决这一问题的主要原理是混合精度分解(Mixed-precision Decomposition)。它就像一个智能筛子,在推理过程中动态探测特征值的大小。对于 99.9% 的常规数值,使用**向量级量化(Vector-wise Quantization)**把它们压缩为 8-bit 进行矩阵乘法,以节省显存:
$$ \mathbf{C}_{f16} \approx \frac{1}{\mathbf{c}_{x} \otimes \mathbf{c}_{w}} \mathbf{C}_{i32} \tag{13.9} $$其中,$\mathbf{C}{f16}$ 是近似的 FP16 输出结果,$\mathbf{C}{i32}$ 是 INT8 矩阵乘法得到的 INT32 结果,$\mathbf{c}{x}$ 和 $\mathbf{c}{w}$ 分别是输入 $\mathbf{X}$ 和权重 $\mathbf{W}$ 的量化缩放因子(Scaling Factors)。
而对于那 0.1% 超过阈值(如 6.0)的“离群”维度 $O$,则自动拆分出来,保持 FP16 高精度计算。最后将两部分结果合并(见图 13-5):
$$ \mathbf{C}_{f16} \approx \underbrace{\sum_{h \in O} \mathbf{X}_{f16}^h \mathbf{W}_{f16}^h}_{\text{离群值 (FP16)}} + \underbrace{S \cdot \sum_{h \notin O} \mathbf{X}_{i8}^h \mathbf{W}_{i8}^h}_{\text{常规值 (INT8)}} \tag{13.10} $$其中,$h$ 代表特征维度,$O$ 是离群特征维度的集合,$S$ 是去归一化项(对应上面的缩放因子乘积)。为了便于理解,这里对缩放因子 $\mathbf{c}{x}$、$\mathbf{c}{w}$ 和 $S$ 的张量维度及广播方式做了简化,实际工程实现中会针对 batch/head/channel 等维度分别维护缩放因子。
这种“抓大放小”的策略,让我们可以在几乎不损失任何精度的情况下,用 INT8 的显存开销运行超大模型。

图 13-5 LLM.int8() 混合精度分解示意图
在此基础上,BNB 进一步演进,成为了微调技术 QLoRA 的主要依赖。它引入了 NormalFloat4 (NF4) 数据类型,这是一种专门为正态分布权重量身定制的 4-bit 类型,比标准的 INT4 具有更高的信噪比。如今,通过 BitsAndBytesConfig,我们可以轻松调用这些技术,在单张消费级显卡上不仅能加载大模型,还能进行高效的微调。
四、Qwen2.5 模型推理量化实战
了解了量化的基本原理后,让我们进入实战环节使用 llmcompressor 库对 Qwen/Qwen2.5-1.5B-Instruct 模型分别进行 GPTQ 和 AWQ 的量化测试。
4.1 环境准备
4.1.1 llmcompressor 简介
LLM Compressor 6 是一个易于使用的库,目标是优化大语言模型以便使用 vLLM 进行部署。它能够实现高达 5 倍的推理速度提升,并显著降低成本。作为一个综合性的工具包,提供了以下核心功能:
- 算法支持丰富:支持包括 GPTQ、AWQ、SmoothQuant、SparseGPT 等在内的多种权重量化、激活量化和剪枝算法。
- 无缝集成:与 Hugging Face 的 Transformers、Models 和 Datasets 深度集成,使用体验流畅。
- vLLM 友好:支持基于
safetensors的压缩模型存储格式,可直接被vLLM加载。 - 高效处理:借助
accelerate库,支持对超大模型进行高性能压缩。
如图 13-6 所示,LLM Compressor 的工作流程首先输入准备好的 Hugging Face 模型和(可选的)校准数据集;接着在压缩阶段,使用 llmcompressor 库应用量化算法(如 GPTQ、AWQ 等);随后输出压缩后的模型检查点(Compressed Model Checkpoint);最后在部署阶段,将压缩模型直接加载到 vLLM 中进行高效推理,最终服务于上层应用。

图 13-6 LLM Compressor 工作流程图
4.1.2 环境安装
接下来先安装 llmcompressor 库,它提供了一套统一的 API 来执行各种量化算法,简化了 auto-gptq 或 autoawq 等底层库的调用。
| |
验证安装是否成功:
| |
如果得到类似这样的输出就说明安装成功了:
| |
4.2 GPTQ 量化实战
4.2.1 初始化环境
这里我们不仅需要 transformers 来加载模型,还需要从 llmcompressor 中导入量化修饰器 GPTQModifier 和一键量化函数 oneshot。
| |
4.2.2 定义量化策略
接下来是量化的核心步骤。需要通过 GPTQModifier 来定义量化的具体策略。
| |
scheme="W4A16":W4 代表权重(Weights)被量化为 4-bit 整数,将模型体积压缩为原来的 1/4;A16 代表激活值(Activations)在计算时保持 16-bit 浮点精度(FP16/BF16)。这种组合既降低了显存占用,又利用了 GPU 的 INT4 Tensor Core 进行加速,同时保持了较高的计算精度。targets="Linear":指定量化仅应用于线性层(Linear Layers)。Transformer 模型的大部分参数都集中在这些全连接层中。ignore=["lm_head"]:这是一个必须注意的细节。模型的输出头(LM Head)负责将高维特征映射回词表空间,对数值精度极其敏感。对其进行 4-bit 量化往往会导致输出乱码或逻辑崩坏,所以通常将其排除在量化范围之外。
4.2.3 执行 One-Shot 量化
定义好策略后,就可以开始执行量化了。llmcompressor 提供的 oneshot 函数将加载模型、应用算法并保存结果,全流程一气呵成。
| |
执行该函数后,终端会打印出详细的量化进度日志。我们可以看到 llmcompressor 正在逐层(model.layers.0, model.layers.1…)对模型的线性模块(q_proj, k_proj…)进行压缩:
| |
在这个过程中,校准(Calibration) 是不可或缺的一环。与微调不同,GPTQ 是一种 Post-Training Quantization (PTQ) 方法,它不需要全量训练,但需要少量的真实数据来“观察”模型的激活值分布。
dataset="open_platypus":GPTQ 依赖于计算海森矩阵来判断权重的重要性。我们需要输入一些具有代表性的文本数据。当前选用的open_platypus是一个高质量的指令微调数据集,涵盖了逻辑推理、代码生成等多种任务,能够很好地代表真实场景的输入分布,防止量化后的模型在特定领域能力退化。num_calibration_samples=128:通常情况下,128 到 512 个样本就足以计算出准确的统计信息。过多的样本不仅增加耗时,边际收益也递减。
4.2.4 加载与效果验证
量化完成后,生成的模型本质上还是一个 Transformer 模型,但其内部的权重层结构发生了变化。我们可以像加载普通模型一样加载它,并检查其结构。
| |
输出如下:
| |
加载完成后,我们检查一下模型结构。
| |
输出如下:
| |
可以看到输出的层类型变成了 CompressedLinear,说明原本庞大的 FP16 线性层已经被成功替换为支持压缩张量计算的专用层。同时,quantization_config 中清晰地记录了量化策略:weights 部分显示 num_bits: 4 和 group_size: 128,确认模型已按照 W4A16 的分组量化策略进行了压缩。为了验证量化后的模型没有“变傻”,我们可以进行一次简单的推理测试。
| |
输出如下:
| |
可以看到模型依然能够生成逻辑清晰、内容准确的回答,证明 4-bit 量化在大幅压缩模型体积的同时,依然很好地保留了模型的核心能力。
4.3 AWQ 量化实战
4.3.1 定义 AWQ 策略
AWQ 的配置流程与 GPTQ 非常相似,主要区别在于使用 AWQModifier。
| |
虽然参数看起来一样,但就像前文所介绍的那样,它们背后的算法逻辑是截然不同的。AWQ 不像 GPTQ 那样依赖海森矩阵的逆,而是依据激活值的幅度来搜索最优的缩放因子(Scaling Factor),将那些对应较大激活值(即更重要)的权重通道进行“放大”保护。这种机制使得 AWQ 在某些特定场景(如代码生成或逻辑推理)下能保留更多的细节能力。
4.3.2 执行量化与对比
| |
整个过程同样依赖校准数据集来统计激活值的幅度。执行后,会看到类似如下的日志输出,特别是在每一层(model.layers.*)的注意力机制中,系统会进行“平滑”操作(SmoothQuant)并应用量化:
| |
在 AWQ 量化时,日志中出现的 SmoothQuant 或 Smoothing 阶段,是 llmcompressor 在实现 AWQ 时对平滑/缩放步骤采用的内部命名,算法本身依然是 AWQ(与 SmoothQuant 论文中的方法不同)。这个过程本质上是在执行一次网格搜索(Grid Search),所以我们会发现 AWQ 的量化过程比 GPTQ 要慢很多。因为 GPTQ 的核心计算(海森矩阵求逆)是确定性的数学解析过程,计算量相对固定;而 AWQ 需要针对每一层,在校准数据上反复尝试不同的缩放因子 $s$,来找到让量化误差最小的最优解。这个迭代搜索的过程自然比单次矩阵运算更耗时。不过,这种额外的时间投入换来的是对离群点的鲁棒性。大模型中常存在极少数数值巨大的激活值(尖峰),如果不加处理直接量化,会带来巨大的精度损失。AWQ 的 Smoothing 过程相当于将这些“尖峰”的压力平滑地分摊到了权重上,从而在不增加推理计算量的前提下,显著降低了量化噪声。而且,AWQ 的这种设计使其生成的模型在 vLLM 等推理引擎中往往能获得更好的原生加速支持。量化完成后,可以使用与 GPTQ 相同的方式加载和测试模型。
参考文献
LeCun, Y., Denker, J. S., & Solla, S. A. (1989). Optimal Brain Damage. Advances in Neural Information Processing Systems, 2. ↩︎
Frankle, J., & Carbin, M. (2019). The Lottery Ticket Hypothesis: Finding Sparse, Trainable Neural Networks. ICLR 2019. ↩︎
Frantar, E., et al. (2023). GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers. ICLR 2023. ↩︎
Lin, J., et al. (2024). AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration. arXiv preprint arXiv:2306.00978. ↩︎
Dettmers, T., et al. (2022). LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale. NeurIPS 2022. ↩︎