你刚用 8GB 显存的笔记本想跑一个 70 亿参数的模型,但权重就有 14GB(FP16),内存爆了。然后你听说量化能把模型压到 4 位,直接塞进显存。你心里犯嘀咕:把数字从 16 位压到 4 位,那精度不得掉成渣?

结果你试了一下,发现模型好像还能用,甚至有时候跟原版难分高下。这怎么回事?4 位只有 16 个离散值,而 16 位能表示 65536 个数字,信息量差了 4096 倍,凭什么能力还在?
这就是量化最迷人的地方:它压缩的不是模型的“知识”,而是参数的“冗余表达”。大部分权重值根本不需要那么精确,它们聚集在很小的范围内,用 4 位足以表达它们的相对关系。真正需要担心的是少数极端值,以及激活值(activations)的分布——这才是精度损失的主要来源。
量化到底在做什么?一句话:把连续数值映射到离散整数
模型参数通常是 FP16 或 BF16 格式。量化要做的是,找到权重分布的范围(比如最小值到最大值),然后把这个范围均匀切成 2^N 段,每段对应一个整数。比如 4 位量化,就是切 16 段。推理时,把整数映射回一个浮点值(通常是段的中点),参与计算。
看起来很简单对吧?但你马上会遇到一个问题:如果权重里有一个特别大的异常值,比如 100,而其他权重都在 -1 到 1 之间,那么切成 16 段后,大部分段都浪费在表达“100”附近的区域,其他权重全被挤压到同一个段里,精度瞬间崩掉。
这恰恰是 LLM 权重里常见的情况。尤其是激活值,经常有少量维度异常大。最早的 LLM.int8() 论文发现,当模型规模超过 6.7B 参数时,激活值中会出现“极端异常值”,让常规量化方法直接失效。后来很多量化方法的核心,就是怎么对付这些异常值。
从 RTN 到 GPTQ 到 AWQ:量化方法的进化
最朴素的方法是 RTN(Round To Nearest,四舍五入),直接按比例把浮点值舍入到最近的整数。简单,但精度损失大。
然后来了 GPTQ(2022 年,基于 Optimal Brain Quantization 思想)。它的思路很巧妙:量化某个权重时,不只看它自己的误差,还要看这个误差对下一层输出的影响,并通过调整其他未量化的权重来补偿这个误差。这相当于把量化误差“分摊”到邻居身上。GPTQ 能把 1750 亿参数的 OPT 模型量化到 4 位,精度损失极小,而且速度快。
接着是 AWQ(Activation-aware Weight Quantization,2023 年)。它发现一个反直觉的事实:权重的“重要性”不取决于权重本身的大小,而取决于对应激活值的大小。如果某个通道的激活值普遍很大,那么量化这个通道的权重误差影响就更大。所以 AWQ 只按激活值统计来缩放权重,不动权重本身。实现简单,效果比 GPTQ 更稳。
| 方法 | 核心思想 | 需要校准数据? | 典型损失(4-bit) |
|---|---|---|---|
| RTN | 直接舍入 | 否 | 较大,容易崩 |
| GPTQ | 逐层最小化输出误差 | 是(少量文本) | 极小,但敏感任务有可感知下降 |
| AWQ | 按激活值缩放权重 | 是(少量文本) | 比 GPTQ 更稳,尤其是在小模型上 |
顺便一提,还有个 LLM.int8() 方法,只做 8 位量化,但把异常值单独用高精度处理,相当于混合精度。它证明了:均匀量化对付不了所有情况,得“看人下菜碟”。
精度损失到底多少?用数据说话
我看了不少论文和实际评测,大概给你一个直觉。以 LLaMA 系列为例,用 GPTQ 做 4 位量化(4-bit,通常指权重 4 位,激活保持 FP16):
- 在困惑度(perplexity)上,7B 模型从 5.68 涨到 5.83(WikiText2),13B 从 5.09 涨到 5.15——听起来涨了,但如果你见过不同模型间的差异,这点差距基本等于“没变”。
- 在 MMLU 这类知识问答上,7B 模型从 35.1 掉到 34.5,下降不到 1 个点。13B 模型从 46.2 掉到 45.7,也差不多。
- 但在代码生成(HumanEval)或数学推理(GSM8K)上,损失会更明显。比如 LLaMA-7B 的 GSM8K 准确率可能从 11% 掉到 8%,虽然基数很低,但相对下降了 27%。
这说明什么?量化对“常识性”任务几乎无损,但对“精确推理”任务有实打实的伤害。原因是推理任务对参数中的微小模式更敏感,4 位的离散化会抹掉这些模式。
为什么模型被压成 4 位还能用?因为冗余不在知识,而在表示
神经网络有大量冗余。训练时为了梯度能顺利传播,参数需要足够精细;但推理时,这些精细度就是浪费。就像一个程序员写代码时用 float64,但部署时用 float32 就够了——中间数位根本用不到。
此外,量化的本质是一种压缩,类似 ZIP。它利用权重分布的统计规律,用较少的比特表达主要信息。但和 ZIP 不同的是,它是有损的,而且损失无法完全恢复。
有个关键点:量化感知训练(QAT)比训练后量化(PTQ)效果好得多。QAT 在训练时就模拟量化误差,让模型自己去适应。不过 QAT 成本高,一般只用在生产环境或小型模型上。现在大多数开源模型用 PTQ,因为便宜,而且对大模型来说已经够用。
我的认知转变:从“量化就是降精度”到“量化是重新分配信息”
我最早做量化实验时,直接用 PyTorch 的 `quantize_per_tensor` 把模型压到 8 位,结果准确率掉了一大截。当时我以为量化就是这么“伤筋动骨”。后来看了 GPTQ 论文,才意识到问题出在哪:我量化的是整个张量,而且没有考虑异常值。换成逐通道(per-channel)量化,误差立刻小了一个数量级。
再后来我理解到:量化误差的传播不是线性的。它经过 ReLU、LayerNorm、注意力等非线性变换后,可能被放大,也可能被吸收。所以有的层特别怕量化,有的层无所谓。聪明的量化方法会自动找到那些敏感层,给它们多留点比特。
举个例子:我在一个小模型上测试,只把 attention 层的权重保持 8 位,其他层压到 4 位,效果比全部压到 4 位好了很多,而体积只增加了一点点。这就是混合量化的力量。
FAQ:量化常见疑问
4 位量化后模型体积能缩小多少?
权重部分约为原来的 1/4,加上激活值和优化器状态,总体积取决于推理框架。如果你原来用 FP16 加载,4 位量化后显存占用基本是原来的 35%-40%,因为还有 KV cache 等开销。
为什么有 4 位比 8 位更好的情况?
听起来反直觉,但有的模型在 4 位量化后,MMLU 分数反而略高于 8 位。原因可能是量化过程引入的轻微噪声,恰好帮助模型泛化(类似正则化)。不过这个现象不稳定,别指望它。
量化后还需要微调吗?
如果任务对精度不敏感,不需要。如果做数学或代码,建议用 QAT 或至少做一小步适配微调(如 LoRA)。
INT4 和 FP4 有什么区别?
INT4 用 4 位整数表示,FP4 用 4 位浮点(包括指数和尾数)。FP4 能表示更大的范围,但精度更低。当前主流是 INT4(如 GPTQ 使用),FP4 在 NVIDIA 新卡上开始流行(如 FP4 硬件加速)。
量化会破坏模型的“创造能力”吗?
对生成多样性影响很小,因为采样过程本身的随机性远大于量化误差。但如果你用贪婪解码,可能会发现输出略有变化。
进阶:量化与其他压缩技术的区别
量化压缩的是“数值表达”,剪枝压缩的是“参数数量”,蒸馏压缩的是“模型规模”。三者可以叠加。但量化是最廉价的——不需要重新训练,只用几十分钟跑一下校准。
所以,值得为了显存把模型压到 4 位吗?
我的判断是:如果任务是聊天、摘要、翻译等“语义”场景,放心用 4 位,损失微乎其微;如果是代码生成、数学推理、逻辑判断,尽量用 8 位或混合量化,至少保留关键层的高精度。
量化也不是没有失败的时候。我遇到过一个模型,4 位量化后直接开始胡言乱语,检查后发现是某个极端权重在量化时被截断成了 NaN。这种问题在参数稀疏或训练不充分的模型上更容易出现。所以量化前一定要跑一遍冒烟测试,不要相信“所有模型都能无损量化”这种话。
最后给你一个实用的建议:如果要用 4 位,优先选 AWQ 或 GPTQ,别用 RTN。而且一定要做逐通道量化,不要用逐张量。就这两步,能让你的模型在 4 位下保住大部分能力。
量化不是一个“要不要做”的问题,而是“怎么做、在哪些层做”的工程问题。理解了这一点,你就能在显存和精度之间找到最合适的平衡点。
原创文章,作者:guanweilu,如若转载,请注明出处:https://guanweilu.cn/article/206.html