把一个大语言模型塞进本地机器跑起来,我最常被问到的问题不是“推理框架选哪个”,而是“模型怎么从14GB变成4GB”。这个体量差距,靠的就是LLM量化。量化不是魔法,它本质上是在回答一个工程问题:在显存、内存、硬盘都卡脖子的前提下,怎么用尽量小的精度损失,把模型塞进能用、跑得动的状态。
这篇文章我会从最基础的数值原理讲起,把业界常用的几种量化方案掰开揉碎对比一遍,再给出我实测过的完整操作流程和评估方法。不管你是第一次接触这个概念,还是已经量化过几个模型但总在精度和速度之间纠结,文中这些经验应该都能直接借鉴。
1. 先把“量化”这件事看透:它到底在优化什么
1.1 模型的体积从哪来:参数数量与表示位宽
一个大模型的体积,最直白的公式就是:参数量 × 每个参数占用的比特数。以某个70亿参数规模的开源模型为例,在默认的FP16(16位浮点数,每个数占2字节)精度下,光权重就是70亿 × 2字节 ≈ 14GB。这还只是权重,没算激活值、KV缓存和运行时开销。一台消费级显卡如果是24GB显存,看起来够,但一旦撑起长上下文对话,KV缓存会快速吃掉数GB空间,再加上每次生成要保留的中间激活,显存立刻告急。
量化的思路很简单:既然每个参数都是一个数,而这个数不一定非要拿16位甚至32位来表示,那就用更少的bit位去近似它。4bit整数每个数只占0.5字节,同样70亿参数,权重能压到3.5GB左右,相当于FP16的1/4。这个体量意味着很多场景都能解锁:模型装进中端显卡、装进Mac统一内存、装进纯CPU内存做推理,甚至塞进手机端离线运行。
不过要警惕一个常见误区:量化“压缩”的不是文件,而是数值本身。文件压缩是把冗余信息消掉,解压后还能还原;量化是直接把每个浮点参数映射成一个更粗糙的整数,解压不回去,是真正的有损压缩。我们做的所有努力,都是在控制这个“损”的程度。
1.2 量化背后的数值映射:从浮点空间到整数空间
量化的数学本质并不复杂。给定一组浮点数值,我们想用有限的整数格子去表示它,这就需要一个缩放因子S和一个零点Z,把浮点值r映射为整数值q。公式可以写成:r ≈ S(q − Z)。
最常用的是线性量化,有两种方式:
- 对称量化:Z=0,正负范围对称,适合激活值和权重大致对称分布的情况,计算最简单。
- 非对称量化:保留Z,用整数格子的范围和浮点真实范围做对齐,能更精细地利用每个bit位,代价是多一次偏移运算。
举个例子,还是70亿参数的模型,某一层权重的取值范围是 [-2.1, 1.7],如果用INT8量化(256个格子),对称量化会把这256个格子均匀铺在[-2.1, 2.1]区间,等于整数值-128对应-2.1,127对应2.1。问题是1.7以下的区域只用了127个格子里的约92个,有大约30%的整数表示能力被浪费了。非对称量化则会按真实范围[-2.1, 1.7]调整零点和缩放,把256个格子铺满,分辨率更高。
另一个直接影响精度的参数是分组粒度。同样的量化公式,可以按整层张量去计算一个缩放因子(per-tensor),也可以按每个输出通道去算一个因子(per-channel),还可以把通道维度再切成小块,比如每128个数一组、每组单独算因子(group-wise)。分组越细,每个块的数值范围越集中,量化误差越小,但存储缩放因子和零点也要额外开销。在4bit场景里,组大小128是精度和开销之间一个非常常见的平衡点,业界大量方案都落在这附近。
1.3 为什么模型量化后还能用:冗余、分布与统计规律
神经网络对量化误差的容忍度远高于一般数值计算,这件事很多人不理解。我换句话解释:训练好的模型,权重里天然存在大量冗余信息,很多相近的参数对最终输出贡献几乎一样,除非误差恰好落在关键参数上,否则整体行为不会出现质变。
更深一层的原因是,神经网络本质是在做特征提取和概率映射,激活值的分布呈现明显的“小范围集中、少数值偏离”形态。大量数值都落在零附近,只有极少数通道的激活值特别大。这种分布让量化有了精准打击的可能:如果量化格子均匀铺开,会为了照顾少数的大数值而牺牲零附近大部分小数值的分辨率,导致误差变大;所以后来的量化算法都在想办法处理那些“少数偏离值”,这就是SmoothQuant、AWQ这类方案的切入点。
但容忍不等于无代价。量化的本质是把一个连续分布离散化,任何信息损失都可能在层与层之间被放大。预训练得越充分、原始模型越稳定,量化后的稳健性通常也越好。所以“选一个本身质量高的底座模型”比“选一个高级量化方案”更影响最终效果,这个观点我后面还会反复提到。
2. 主流量化方案选型:不同路线背后的设计取舍
2.1 基础路线分歧:训练后量化与量化感知训练
按是否需要重新训练,量化方案可以分成两大类:训练后量化(PTQ)和量化感知训练(QAT)。
PTQ只需要准备少量校准数据,跑一遍前向过程统计数值分布,然后对权重做量化,整个过程通常几十分钟内完成,成本很低。QAT则把量化的噪声纳入训练过程,让模型在学习过程中适应低bit表示,精度通常更高,但要重新训练模型,对大多数开发者来说计算成本不可接受。所以社区里绝大多数本地部署方案走的都是PTQ路线,QAT更多被模型厂商在发布时就内置,或者用在某些对精度极度敏感的场景。
在PTQ的内部还能继续分:直接对权重做舍入处理是最简单的,但误差不可控;加上误差补偿逻辑的,会反复校准每一层的前后误差,让量化后的层尽量“仿真”出量化前的行为。后面要讲的GPTQ就属于这一类。
2.2 几种核心方案对比:权重舍入、逐层补偿与激活感知
现在部署场景里最常见的几类方案,我列一个我自己的认知框架:
- 直接舍入法:把浮点权重四舍五入到最近的整数格子。这个方法在8bit下效果尚可,但4bit下误差比较随机,容易出现某几层误差叠加导致模型输出质量明显下降。适合快速验证流程,不适合作为生产方案。
- 逐层误差补偿方法:代表思路是GPTQ,它把量化过程拆解成“先量化一层、反推误差、在下一层权重里补偿误差”的迭代过程,等价于用最小二乘的思想去最小化整层输出误差。这种方法在4bit权重量化上效果非常突出,是业界最流行的PTQ方案之一。它需要校准集,因为补偿的方向依赖于激活值的统计。
- 激活感知方法:代表思路是AWQ,它不再只看权重的数值分布,而是看哪些通道对最终激活值的影响更大,然后对这部分通道保留更精细的量化尺度,其他通道可以粗粒度量化。它本质上是利用“重要通道少数、普通通道多数”的分布规律做加权分配,不需要精确的误差反向传播,鲁棒性更好。
- 纯整型方案:以GGUF出现为代表,常见的量化格式如Q2_K、Q4_K、Q5_K、Q6_K等,实际上是按不同块大小和混合精度策略打包的整型表示。这类方案对CPU推理特别友好,因为整型运算在CPU上是原生支持的,不需要额外特殊指令集就能高效跑起来。
- 高阶层面的低bit浮点方案:比如FP8。它不是整数映射,而是直接降低浮点数的尾数和指数位数。优势是动态范围大、几乎不需要额外校准,缺点是目前只有较新的硬件原生支持,老设备跑不起来,而且省显存的程度不如4bit整型那么极致。
这些方案不是互相替代的关系,而是不同场景下的互补选择。如果只看GPU部署和精度,逐层补偿类和激活感知类是最常见的两条路;如果目标是CPU或者边缘设备,纯整型格式会方便得多;如果是新硬件上追求低延迟同时不想做太细致的校准,低bit浮点则更省事。
2.3 方案选型的决定性因素:硬件、部署方式与精度敏感度
我做过不少次量化选型,最后发现决定选择方案的核心因素其实就三个:跑在什么硬件上、部署形态是什么、业务对精度的容忍度如何。
如果是NVIDIA系GPU上跑,直接考虑逐层补偿或激活感知方案,因为它们能以4bit权重做到很低的精度损失,推理框架支持也成熟。如果是CPU推理,纯整型格式会更实际,因为大部分消费级CPU没有针对低bit浮点做专门加速,整型计算反而又快又稳。如果是Apple Silicon这种统一内存架构,对显存大小的限制相对宽松,更多要平衡速度与内存占用,整型低bit格式也非常顺手。
如果你对精度非常敏感,比如模型涉及代码生成、数学推理这类容错率极低的任务,我会优先考虑高bit量化或纯FP8路线,而不是硬上4bit。反过来说,做闲聊类应用、内容摘要、文本分类,4bit全家桶通常足够用,性价比最高。
3. 实操过程:从FP16到4bit完整量化部署
3.1 准备工作:底座模型选择与校准数据集构建
开始量化之前,最重要的一件事是选一个稳定可靠的开源底座模型。量化不能把坏底座变好,只能尽可能保持原样。我通常先干两件事:第一,跑几个query看原始FP16模型输出是否稳定;第二,确认显存和内存能够装下FP16版本的模型来执行量化进程,因为量化过程需要加载原始权重做前向校准。
校准数据集是PTQ的灵魂。它不要求数量大,但要求覆盖广。经验上几百条典型样本就足够了,关键是样本不能和评测集重叠,否则量化后的精度指标非常好看,一上线就原形毕露。样本内容应该尽量贴近真实使用场景:如果模型主要用来做摘要,就准备摘要类文本;如果用来对话,就准备多轮对话样本。我自己的做法是把训练集、验证集、用户真实输入脱敏后各取一部分,混合成200到500条的校准集,再做一次去重和去脏处理,保证文本长度、语体多样性都覆盖到。
3.2 量化执行的关键步骤与参数选择
整个量化流程,按我常用的顺序拆解如下:
- 以FP16精度加载底座模型,跑一遍校准集,收集每一层的激活统计信息。
- 选择量化位宽和分组大小。权重4bit、组大小128是一个万金油起点;如果精度不够再降到3bit或提升到常规组大小,如果显存还宽裕就升到6bit甚至8bit。
- 执行逐层量化。从第一层开始,对每个Linear层做量化、计算输出误差、按方案进行补偿,逐层向后推进,最后保存量化后的权重文件。
- 转换模型格式。把量化后的权重转成目标部署格式,注意保持元数据完整,否则加载时容易踩坑。
- 在目标推理环境下加载量化模型,分别跑一个精度验证集和一组延迟测试。
这里面最容易出问题的是执行逐层量化时显存不够,因为要同时保留FP16权重副本和正在量化的层。如果显存吃紧,我的建议是减少校准集batch大小、按层分块处理,必要时用CPU内存做权重暂存,速度慢一点但能跑通。
还有一个参数容易被忽略:校准集batch size。太大容易把激活统计平滑掉,导致少数关键分布细节丢失;太小则统计噪声大,量化后跳动明显。我一般控制在4到16之间,具体数值取决于模型大小和显存余量,批量太大反而精度变差是我踩过的坑。
3.3 部署阶段:上下文长度、KV缓存与推理配置
量化完成之后,部署阶段才是真正考验工程能力的地方。很多人以为模型体积变小了,显存就一定够,实际上推理时的隐性开销远比想象中大。
以4bit的7B模型为例,权重约3.5GB,看起来很宽裕。但KV缓存是按层数、注意力头数、上下文长度、精度四个维度共同决定的。比如一个拥有32层、每层2个KV头、维度128的模型,跑4K上下文,KV缓存大约是32×2×128×4096×2字节×2(因为有K和V) ≈ 134MB,看起来不大。一旦到32K上下文,就超过1GB;如果还要考虑其他额外开销,显存立刻吃紧。真相是:模型体积只是显存占用的起点,不是终点。
部署时我还建议注意两点:一是线程数和批处理大小要按硬件实测调整,而不是闭眼用默认值;二是核对推理框架是否真的启用了GPU加速和KV缓存优化,有些所谓CPU推理模式默认配置并不适合长上下文。实测下来,同一次推理,如果上下文长度从2K调到8K,首token延迟和吞吐量都会出现明显差异,这是很正常的,不必怀疑模型坏了。
4. 量化效果的验证与评估:数字指标说了不算
4.1 精度评估的关键指标与陷阱
量化后怎么判断效果?最简单的做法是看困惑度(PPL)和几个下游任务分数。困惑度越低越好,它能快速反映模型对文本的概率预估能力是否受损。但它有一个隐蔽的坑:困惑度对局部异常不敏感,有时候PPL只涨了一点点,但用户实际使用中会发现个别句子的输出质量断崖式下降。
所以我的习惯是组合评估:
- 困惑度对比:量化前 vs 量化后,上升幅度超过5%需要警觉。
- 下游任务抽样:选和真实场景一致的任务各跑100条,对比准确率。
- 人工抽检:拿20条典型prompt,肉眼对比输出完整性、重复性、逻辑连贯性。
有几个现象特别值得注意:量化后模型开始频繁输出重复词句,这是误差累积的信号;或者长文本生成越来越偏离主题,这常见于注意力层的KV量化引入的误差被逐步放大;还有特定领域的专业术语开始“一本正经胡编”,这也说明量化的数值扰动干扰了模型的知识记忆区域。
4.2 速度与资源占用的测量方法
精度之外,量化的另外两个价值是省显存和提速度。但这两者测量起来各有各的门道。
显存占用直接看推理框架的日志或系统监控即可,但要注意:加载模型时的峰值显存、稳定推理时的常驻显存、长上下文时的动态显存是三回事,只看其中一个会得到错误结论。速度指标则要分两个维度:首token延迟(TTFT)代表“用户等第一句话要多久”,吞吐量(tokens/s)代表“单位时间能生成多少内容”。量化通常会让TTFT更稳定,但对吞吐量的提升取决于硬件是否支持低bit运算加速。在普通CPU上,4bit整型量化会显著提升吞吐,因为计算强度降低了很多底层数据搬运压力;而在某些高端显卡上,如果硬件没有为INT4做专门加速,量化提升可能不如预期。所以拿到一个量化模型后,我建议先用固定prompt跑50次取中位数,再下结论快不快。
5. 常见问题与排查技巧实录
5.1 量化后输出质量崩坏:优先排查校准集与关键层
如果量化后模型输出明显乱掉,我的排查顺序是:先看校准集质量,再看分组大小和位宽,最后看关键层是否被异常压缩。校准集如果和真实场景偏差过大,比如用英文文本校准、中文场景部署,量化算法会把错误的分布当成目标,结果误差集中爆发。分组大小和位宽则直接影响误差上界:组大小越细,误差越小,但存储开销越大。我曾经把一个模型的量化bit从4bit提升到5bit,精度没有任何可感知提升;但把组大小从128调细到64,一个数学任务准确率直接回升了10个百分点。这个现象让我意识到,组大小的作用常常被人低估。
最后一个排查点是量化过程中是否遗漏了特殊层。有些模型里的Embedding层、Layernorm层、最后的输出层不应该做低bit量化,因为它们要么参数极少、要么对数值精度极敏感。把这些层保留FP16,往往能换来肉眼可见的稳定提升。这也是很多新手的盲区:动不动就把全部层一刀切量化,结果Edding层被压成4bit,嵌入向量全变了形,模型输出当然乱七八糟。
5.2 推理速度没有提升:问题可能在存储带宽
很多人量化完跑起来,发现速度提升不大,甚至更慢了。这个现象在CPU场景里尤其常见。大模型推理本质上是一个访存密集型任务,瓶颈往往不在计算,而在把权重从内存搬到计算单元的过程。4bit模型数据量降为FP16的1/4,搬运成本理论上应该显著下降,但如果你的内存通道很窄、内存频率很低,计算公式效率又不高,总耗时可能没有明显变化;更糟的是如果推理库实现本身对低bit格式支持不好,还要做额外的解包工作,反而变慢。
我见过一个典型场景:同一台老笔记本上,FP16的7B模型每秒只能生成2个token,换成4bit量化后提升到6个token,看起来不错。但换到一台新配置的主机,FP16能跑到每秒12个token,4bit反而只有10个。原因就是新主机的内存带宽已经足够快,而推理库对4bit包的解码开销成了新瓶颈。所以量化提升速度是有前提的:只有当数据搬运确实是瓶颈时,把模型变小才最有效。这个规律也提醒我,在选量化方案之前,先搞清楚自己的瓶颈是算力还是带宽,否则容易白折腾。
5.3 显存还是不够:别忽略KV缓存和运行时开销
还有一种情况:模型已经压到3.5GB了,但一跑长对话还是会爆显存。这时候要检查的是KV缓存和运行时的中间缓冲,而不是继续压缩权重。很多模型默认会预留非常大的最大上下文长度,即便当前对话才聊了几句,推理框架也可能按最大上下文预分配KV缓存空间。解决方法是显式限制上下文长度为实际所需值,比如从默认的32K压到8K甚至4K,显存立刻能腾出一大块。另一个实用技巧是开启系统级或框架级的KV缓存调度方案,让缓存在显存与内存之间动态换入换出,虽然偶尔会慢一点,但至少不爆。
5.4 量化方案选得不合适:换一种思路可能更有效
如果你用了某个量化格式后效果始终不满意,不妨重新检查一遍选型。有位同行曾经试过用整型4bit格式量化一个代码生成模型,结果代码正确率掉了两成,换成逐层误差补偿方案后只掉了不到5%。问题不在4bit这件事本身,而在整型格式的静态标定没有抓住代码生成场景里激活值的细节分布。这也说明,不同推理任务对量化的敏感度差异极大。代码生成、数学推导这类任务长尾逻辑强、局部数值敏感,对量化的容忍度低;内容分类、情感分析这类任务对整体分布偏移不敏感,用激进一点的4bit反而很稳。
6. 实操心得:量化不是越激进越好
最后聊点个人的体会。量化工程里头没有“最先进的方案”,只有“最适合你硬件和场景的方案”。我在给某个场景做长文本摘要模型时,试过把模型压到3bit,省下来的显存确实可观,但生成质量时好时坏,尤其是长段落收尾时经常丢关键信息。后来老老实实回到4bit,那部分显存通过缩短上下文长度省回来,效果反倒扎实很多。
所以我现在选量化参数有一套默认的稳健配置:权重4bit,组大小128,关键层保留FP16,校准集提前脱敏。这个组合在绝大多数CPU和GPU场景下都能拿到“不是最好但最稳”的效果。碰到显存特别紧张的情况,我优先降上下文长度而不是降bit;碰到精度特别敏感的场景,优先换激活感知类方案而不是靠提高bit硬扛。
另外,我这几次做量化,有一个小习惯值得提一下:所有量化完的模型,哪怕指标看起来再好,我都会先复现一次“用户视角测试”。不是跑标准评测集,而是模拟真实用户那样连续追问、切换话题、给局部错别字的输入。很多问题都是在这种“脏输入”下暴露出来的,标准测试集根本测不出。这个习惯救过我很多次,也建议你保留。