# code

AWQ,GPTQ,GGUF量化

📅 2026-03-04 ✍️ Layla

AWQ

AWQ,全称Activation-Aware Weight Quantization(激活感知权重量化)。

AWQ量化的核心思想就是,不是所有的权重都同等重要。在神经网络中,只有极少数(大约 $1\%$)的权重对模型的性能起到了决定性的作用。如果你把这些显要权重也进行粗暴的4-bit量化,模型的智力会迅速崩塌。

那么,如何定义哪些权重是“显要”的呢?AWQ 并没有看权重本身的大小,而是去看激活值。逻辑很简单:如果某个通道输入的信号特别强,那么与之相乘的权重即使只有微小的量化误差,也会在输出端被放大成巨大的偏离。因此,AWQ 的核心就在于通过观察模型推理时的激活分布,找出那些承载了大信号的权重列。

找到了这些重要的权重后,最直接的想法是把它们留在 FP16 精度,其他的量化。但这样做会导致硬件推理时非常低效,因为你得在一个矩阵里处理两种不同的数据格式。AWQ 优雅地避开了这个问题,它采用了一种自动缩放的策略。具体来说,它会给那些重要的权重列乘以一个大于 $1$ 的缩放因子 $s$,同时为了保持数学上的等价性,它会把对应的输入激活值除以相同的 $s$。

为什么给权重放大之后再量化误差更小?我们来举个例子说明:

直接进行线性量化

假设此时我们有一个非常强的输入信号 $X = 100$(这就是所谓的离群值),而对应的权重是一个很精细的浮点数 $W = 0.1234$。在理想的高精度计算中,结果应该是:

\[Y = 100 \times 0.1234 = 12.34\]

现在,我们要把这个 $W$ 塞进一个刻度只有整数(1, 2, 3…)的 4-bit 量化器里。按照四舍五入,$0.1234$ 只能变成 $0$。那么量化后的计算变成了:

\[\hat{Y} = 100 \times 0 = 0\]

误差直接就是 12.34,原来的信号特征全没了,这就是典型的量化灾难。

先放大再量化

AWQ 观察到了这个 $X=100$ 的强信号,它意识到这个 $W$ 非常重要,不能随便“舍入”掉。于是它决定引入一个缩放因子 $s = 10$。

第一步,它把权重 $W$ 放大 10 倍,变成 $1.234$。同时,为了保证数学上的结果不变,它把输入 $X$ 缩小 10 倍,变成 $10$。

这时候,公式变成了:$Y = (100 / 10) \times (0.1234 \times 10) = 10 \times 1.234$。

第二步,进行量化。现在权重是 $1.234$,再次放到那个整数刻度的量化器里。这次,$1.234$ 被四舍五入成了 $1$。

那么量化后的计算变成了:

\[\hat{Y}_{awq} = 10 \times 1 = 10\]

虽然仍然有误差,但比起直接把信号弄丢(变成 0),AWQ 成功保住了这个通道的大部分有效信息。


GPTQ

GPTQ 是一种针对大型语言模型的后训练量化(Post-Training Quantization, 即PTQ)技术,它的核心目标是把原本占用巨大显存的 FP16 精度权重,压缩到4-bit甚至更低,同时尽可能不让模型的智力掉线。

GPTQ 并不是简单的四舍五入,它的高明之处在于利用了所谓的二阶导数信息,也就是海森矩阵(Hessian Matrix)。在量化的过程中,它会逐层处理参数。每当一个权重被强制压缩时,GPTQ 会计算这个改动对输出造成的误差,然后利用海森矩阵的信息去补偿该层中尚未量化的其他权重。

利用海森矩阵补偿信息

如果我们对量化的误差函数在原始权重处进行泰勒展开,你就会发现,一阶导数(梯度)在模型收敛点附近几乎为零,所以真正主导误差变化的就是那个二阶导数项,也就是海森矩阵。

这个矩阵记录了函数表面的曲率信息:如果某个权重的二阶导数很大,说明这个点稍微动一下,整体误差就会爆炸;如果二阶导数很小,说明这个点比较迟钝,随便怎么压也不会出大问题。GPTQ 的核心思想,就是利用这个海森矩阵来指导权重的牺牲与补偿。

在实际操作中,GPTQ 采用的是一种逐列量化策略。想象一下,我们有一排权重需要量化,当我们决定把第一个权重从 $0.8765$ 强行压缩成 $1$ 的时候,这个“强行舍入”产生的误差就会被记录下来。这时候,二阶导数补偿就上场了。GPTQ 不会坐视这个误差不管,它会利用海森矩阵的逆矩阵,把刚才那个权重产生的误差按比例分配给这一行中剩下的、还没被量化的权重。也就是说,后面的权重会根据前面的误差进行微调,通过这种主动的“偏置”来抵消前面量化带来的扭曲。当你把整行权重都处理完时,虽然每一个数字都变粗糙了,但它们合力产生的输出,却惊人地接近原始的高精度状态。

想象一下,我们正在处理一行权重向量 $w$。当我们把第 $i$ 个元素 $w_i$ 量化为 $\hat{w}_i$ 时,产生了一个微小的扰动 $\delta = \hat{w}_i - w_i$。为了让这一层的总输出改变量最小,我们需要调整剩余的、还没量化的权重(也就是索引 $j > i$ 的那些元素)。

这里最关键的数学工具就是海森矩阵的逆矩阵 $H^{-1}$。在 GPTQ 的逻辑里,第 $i$ 个权重的量化误差对后面权重的补偿量,是正比于 $H^{-1}$ 的第 $i$ 列向量的。简单来说,补偿量 $\Delta w_{j}$ 的计算公式大致表现为:

\[\Delta w_{j} = - \delta \cdot \frac{[H^{-1}]_{ji}}{[H^{-1}]_{ii}}\]

这个公式告诉我们,后面每一个权重该变动多少,取决于它与当前量化权重之间的“协同敏感度”。

为什么是逆矩阵?在多维空间里,海森矩阵描述了误差曲面的形状。如果两个权重之间存在强烈的相关性(由海森矩阵的非对角线元素体现),那么量化其中一个产生的破坏,就必须由另一个进行大幅度的反向补偿才能抵消。

逆矩阵在这里充当了一个“相关性解码器”。通过 $[H^{-1}]_{ji}$ 这个比值,GPTQ 能够精确地计算出:为了抵消第 $i$ 个位置的精度损失,第 $j$ 个位置需要做出多大的补偿调整。

总结来说,GPTQ的核心思想就是抛弃注重单个权重量化产生的误差,而是通过利用当前权重量化误差去对后面还未量化的权重进行调整,从而使得整层网络输出的误差最小。


GGUF

GGUF 并不是一种单一的量化算法,它是一套完整的二进制文件格式和量化体系。它的核心逻辑不是在数学上高深的二阶导数,而是在工程实现和硬件适配上做到了极致的通用。

GGUF 最硬核的底层技术其实是 K-Quants(或者叫分块线性量化)。它不像 GPTQ 那样盯着全局的海森矩阵看,而是采取了极其细致的“网格化管理”。

想象一个巨大的权重矩阵,GGUF 会把它切成无数个小方块(通常是每 32 个或 64 个参数为一个 Block)。在每一个小块内部,它会独立寻找一个缩放因子和偏移量。这种做法的逻辑优势在于:它能局部地适应权重的剧烈波动。即便某一部分权重分布很诡异,它也只会影响那 32 个参数的量化精度,而不会像全局量化那样为了照顾几个离群值而毁掉整个矩阵的刻度。

混合精度

GGUF 的另一个精妙之处在于它提供了极其丰富的量化方案选择,也就是经常看到的 Q4_K_MQ5_K_S 等等。这里的“K”代表了不同的量化策略。

Q4_K_M(Medium)为例,它的逻辑非常聪明:它并不是把所有层都一刀切地压到 4-bit。它会识别出模型中哪些层对智力最关键(比如 Attention 的核心权重),并给这些层分配稍高的位宽(比如 6-bit),而对那些不那么敏感的层(比如多层感知机的某些部分)使用4-bit压缩。这种层间混合精度的平衡感,使得 GGUF 模型在同等体积下,往往能展现出比单纯线性量化更稳健的逻辑推理能力。

更广泛的硬件支持

传统的量化方案往往高度依赖 NVIDIA 的 CUDA 环境,而 GGUF 在设计之初就考虑到了 Apple Silicon(Metal)普通 CPU(AVX/NEON 指令集)

它的文件格式里包含了模型运行所需的所有元数据,比如分词器设置、层数、架构参数等。这意味着你只需要一个 .gguf 文件,就能在几乎任何计算平台上跑起来,而不需要再配置复杂的 Python 环境或依赖库。这种“开箱即用”的工程闭环,极大地降低了大模型的准入门槛。

虽然 GPTQ 在纯显卡环境下吞吐量更高,但 GGUF 在内存压缩和多硬件协同上的逻辑是无敌的。它支持把模型的一部分放在显存里,剩下的跑在内存里(Offloading),这让很多显存不足的用户也能跑起巨大的 70B 甚至更大的模型。

总结

维度 GPTQ AWQ GGUF
核心算法 OBQ误差补偿 激活感知保护 k-means聚类混合精度
硬件要求 NVIDIA GPU (CUDA) NVIDIA GPU (CUDA) CPU / GPU / Apple Silicon
推理速度(GPU) 最快 中等
推理速度(CPU) 不支持 不支持 最快(唯一选择)
量化质量 中等 最好 中等
长上下文表现 一般 中等
文件格式 多文件 多文件 单文件
消费级友好度
vLLM支持 支持 原生支持 有限支持

参考文章:https://www.zhihu.com/question/633365088/answer/2009931891990606483

# 研究讨论 / Discussions