资讯动态

4bit量化不是把模型变笨:GPTQ与AWQ如何用好16个格子

发布时间:2026/10/23 5:14:13 来源:尧图企业网站定制
4 bit 量化之后一个权重参数只能在 015 之间取值也就是只有 16 个“格子”。第一次看到这个数字的人几乎都会问同一个问题16 个格子凭什么能装下一个动辄几百亿参数的大模型这个问题并不外行它刚好切中了低比特量化的核心矛盾量化损失的本质就藏在这 16 个格子怎么分配、怎么使用里。更准确地说4 bit 量化不是把 16 个格子平均撒在整个权重范围上而是让一小段权重共享一把“局部尺子”让格子的位置跟着数据分布移动。GPTQ 和 AWQ 是两种最有代表性的移动尺子、分配量化误差的技术路线。读懂它们你就能理解为什么 4 bit 大模型能在精度几乎不明显损失的情况下跑起来也能避免在实际部署时选错方案、调错参数。AI Infra 对量化的关注也不只是因为“位宽数字听起来更小”。大模型推理的瓶颈往往是显存带宽同样一个 7B 模型FP16 权重大约占 14GB4 bit 后降到 3.5GB 左右从显存搬运权重的带宽成本直接下降约 4 倍。所以真实的问题不是“16 个格子还能用吗”而是“16 个格子怎么用才不伤模型”。这篇文章分层拆开这 16 个格子先看量化误差从哪来再分别讲 GPTQ 和 AWQ 的核心机制最后落到部署时需要关注的参数、验证方法和常见排查路径。如果你正在做推理优化、边缘部署或者准备给团队调研低比特量化方案这篇文章可以帮你少走一些弯路。1. 为什么“16个格子”不够但实际又能用1.1 量化到底在压缩什么量化是把连续浮点权重映射到一组离散整数的过程。以 4 bit 为例量化后的每个权重只能取 0 到 15 中的一个整数代码。反量化时再用一个统一的比例因子scale和零点zero_point把它还原成浮点值得到一个近似原权重的新权重。可以用一个很小的公式来描述q round((x - zero_point) / scale) x_hat q * scale zero_point这里的 scale 决定两个整数之间对应的浮点间隔。4 bit 只有 16 个整数代码在相同的动态范围下间隔往往比 8 bit 更大。比如原始权重分布在 -2.0 到 2.0 之间均匀 4 bit 量化的步长大约是 0.25很多小权重会被吸到同一个整数上于是每个权重都产生一定误差。问题就来了模型里动辄上百亿个权重每个权重都有误差这些误差难道不会累积成灾难吗关键在于4 bit 量化并不是对每个权重独立使用一把全局尺子。它通常把一个矩阵切成若干分组每组共享自己的 scale 和 zero_point。这样一来16 个整数代码在每个分组里对应完全不同的浮点数值。组 A 的代码 5 可以是 0.13组 B 的代码 5 可以是 -0.87。所以准确的说法是每个权重在编码时只能用 015 这 16 个编号但编号还原出来的浮点值并不是全模型统一的一一对应关系。一个模型里有成千上万套 16 个格子每套格子只服务一小段权重。1.2 权重分布决定了误差的性质大模型的权重分布并不是均匀的。大多数权重集中在零附近绝对值很小只有少数权重的绝对值比较大类似一种中间高、两边低的钟形分布。如果只用一套全局尺度就会出现两个极端为了覆盖最右侧的大权重scale 会被拉大导致零附近的小权重被“颗粒化”大量细节直接丢失如果为了照顾小权重把 scale 调小大权重又会超出量化范围必须截断产生巨大误差。分组量化解决的就是这个问题。每一组内部的权重分布相对集中scale 可以随着该组动态范围去调整。组内变化越小16 个格子的“布局”就越贴近这组权重的真实分布量化误差越小。这也是为什么 group_size 是低比特量化最重要的参数之一。它在本质上决定了“局部尺子”的分辨率。1.3 误差会被模型结构消化掉一部分还有一个容易被忽视的事实单个权重的微小误差并不会直接决定模型输出。矩阵乘法是大量乘加操作的累加误差有正有负在求和过程中会部分抵消。残差连接、注意力加权、多层非线性变换也会对噪声做一定程度的“平滑”。量化误差更像给模型加了一层噪声而不是把模型的一部分直接删除。只要这个噪声不是系统性地偏向某一类输出模型通常能保持主体能力。GPTQ 和 AWQ 要解决的问题就是尽量减少这种噪声中“尤其危险”的部分并避免误差逐层累积。2. 从朴素量化到分组量化16个格子是如何“移动”的2.1 三种尺度per-tensor / per-channel / per-group量化尺度可以作用于不同粒度的数据粒度共享尺度的范围优点代价per-tensor整个张量共享一套实现最简单动态范围大误差最大per-channel每个输出/输入通道各一套能适配通道差异元数据稍多per-group每个固定大小的权重块一套精度高广泛用于 4bit元数据比 per-channel 更多4 bit 量化场景里per-tensor 往往不够用per-channel 在很多大模型里也还有压力所以主流方案会进一步使用 per-group常见 group_size 为 128 或 64。2.2 group_size 改变的是什么当 group_size128 时每 128 个权重共享一组 scale 和 zero_point也就是共享一套 16 个格子。这 128 个权重可以来自同一输出通道的相邻输入特征也可以是一个矩阵中的连续块具体切法取决于框架实现。group_size 越小意味着有更多的“局部尺子”16 个格子的覆盖范围越精准量化误差越小。但代价也很直接需要存储的 scale 和 zero_point 数量更多显存开销和反量化计算量会上升。实际部署中128 是一个比较常见的平衡点64 会更稳但收益不一定足够明显。2.3 对称与非对称量化对称量化通常把整数范围中心设在 0不需要 zero_point非对称量化则增加了一个零点能让 16 个格子更好地覆盖偏斜的分布。权重分布通常比较对称许多量化方案会首选对称量化实现更简洁但激活值分布常常偏斜所以一些量化配置会在激活侧或特定层使用非对称量化。对于 4 bit 权重量化非对称配合 group_size 能进一步提升精度代价是反量化时多一个参数参与计算。这里的关键结论是16 个格子本身不是限制限制在于每个分组里格子的分布是否与权重分布匹配。分组、缩放、零点都是为了让格子的“位置”和“间距”尽量贴合局部数据。3. GPTQ用误差传播补偿来“挽救”量化3.1 核心理念最小化层输出的变化而不是单个权重误差GPTQ 的全称是 Generative Pre-trained Transformer Quantization但它的核心思想并不是某种大模型专属公式而是把量化看成一个优化问题。普通量化只关注“把 W 变成 \hat{W}让 ||W - \hat{W}|| 尽量小”。GPTQ 则认为真正重要是“用 \hat{W} 替换 W 之后这一层的输出变化尽量小”。也就是说目标不是让每个权重都接近原值而是让整个层的输出接近原输出。用数学语言表达GPTQ 对每一层解决类似这样一个问题给定校准数据 X希望找到量化后的权重矩阵 \hat{W}最小化 ||WX - \hat{W}X||。因为是线性层的输出误差经过 X 加权后不同位置的权重对输出的影响并不相同。这种思路让 GPTQ 可以在量化一个权重的同时通过修改同一层其他未量化权重去抵消前面已经产生的误差。3.2 算法流程逐层重建、二阶信息、权重更新GPTQ 的实际实现是逐层、逐块处理的。它并不直接对所有权重同时做全局搜索那在百亿参数模型上不现实。它的流程可以概括为几个关键步骤用一小段校准文本比如几百条 C4 语料跑一遍模型记录每一层输入作为该层的校准数据 X对当前层用 X 构造近似二阶信息矩阵用来估计“如果这个权重被量化下一个权重应该往哪个方向调整”按一定顺序逐列/逐块量化权重每完成一个块就根据量化误差更新后续的未量化权重所有层都重建完之后保存量化后的权重以及每一层的 scale、zero_point 等参数。这里不需要人工设计如何调整半步是核心的数学优化。实际工程中会用到 Cholesky 分解、块坐标下降、阻尼项这些工具目的都是让更新过程在可接受的时间内完成。用伪代码看大致是这样对每一层 H 2 * (X * X^T) 阻尼项 # 近似二阶信息 for 每个需要量化的列块: 对块内每个权重做量化 计算量化误差 利用 H 的逆更新剩余权重抵消误差GPTQ 最大的特点是“不需要知道哪些权重更重要”而是通过误差传播自动调整。它把量化误差重新分配到了那些对层输出影响更小的位置上。3.3 GPTQ 的优势与潜在问题GPTQ 在 4 bit 量化上效果通常很好这也是它成为社区早期最常见方案之一的原因。它适合一次性离线量化大模型量化过程可以跑在 CPU/GPU 上不一定需要目标推理硬件。但它也有明显的工程限制量化过程耗时较长尤其是大模型逐层重建时需要大量矩阵运算对校准数据有一定敏感性校准集如果和实际任务分布偏差很大精度会打折扣二阶信息矩阵在超大模型上显存消耗不小权重会被“更新”成一组新的值不再是原始预训练权重这会让一些依赖权重分布的调试和分析变得复杂。所以 GPTQ 更适合“花时间换取精度”的离线量化场景。只要校准数据选得稳量化结果通常非常接近 FP16。4. AWQ用激活值决定哪些权重更重要4.1 权重本身没有绝对的重要性重要性要看激活值AWQ 全称 Activation-aware Weight Quantization名字已经把核心写清楚了权重的重要性不由权重本身决定而由它对应的激活值决定。同样是两个绝对值相同的权重如果一个位于激活值很大的通道上它对输出贡献就更大如果一个位于激活值接近 0 的通道上即使量化误差再大对最终输出也可能无关紧要。AWQ 的思路非常直观先跑一小段校准数据观察每一层的激活分布找出哪些输入通道上的激活值普遍较大。这些通道对应的权重就是需要“重点保护”的对象。这件事在传统剪枝里叫“重要性分析”在量化里同样有价值。GPTQ 是通过后验误差调整来保护整体输出AWQ 则是先验地找到重要位置在量化前就把保护措施做好。4.2 AWQ 的三步统计激活、缩放权重、再平衡AWQ 的做法不是直接改权重数值而是对重要通道的权重乘一个缩放系数 s。如果某一个通道的权重普遍很小而激活值普遍很大这个通道的权重一旦量化相对误差会被放大。给这些权重统一乘上一个大于 1 的系数可以让它们落在量化格子中占据更多档位从而降低量化相对误差。但是权重变大了输出也会变大所以需要在激活侧也做一次反向缩放把放大抵消掉。最终的效果是权重侧重要通道的权重被放大量化误差相对变小激活侧重要通道的激活被缩小保证矩阵乘法的数学结果不变部署时反向缩放可以融合到相邻的 LayerNorm、线性层或反量化参数中不增加推理计算量。换句话说AWQ 并不是把权重重写成一个“更聪明”的新矩阵而是给重要通道换了一把更合适的尺子。这把尺子在量化后又被悄悄融进网络的其他部分所以用户感知不到额外开销。4.3 为什么 AWQ 能比 GPTQ 更轻量GPTQ 需要反复更新权重依赖二阶信息矩阵量化过程比较重。AWQ 主要靠激活统计和缩放搜索不需要对权重做在线重建量化速度快很多。当然AWQ 也离不开校准数据。没有校准数据模型就无法知道哪些通道重要。它的优点是把大部分额外计算放到预分析阶段量化过程本身更简洁。AWQ 在 4 bit 和更低位宽场景下表现稳定在多模态模型、视觉语言模型和边缘部署上尤其受关注。原因是这类模型里不同模态、不同层的激活分布差异很大先看激活值再决定保护策略往往比统一做后验误差补偿更直接。4.4 AWQ 的局限性AWQ 不是万能的。如果校准数据无法代表真实推理时的输入分布统计出来的“重要通道”可能并不准确。另外缩放系数s的选取方式会影响最终效果不同实现里的搜索策略也不完全一样。对比来看GPTQ 更像“事后补救”AWQ 更像“提前布局”。两者目标一致但路径不同实际效果与模型结构、校准数据和量化配置都有关系。5. GPTQ vs AWQ核心对比与选型对比维度GPTQAWQ核心思路量化后用误差补偿更新剩余权重量化前用激活值保护重要通道是否修改权重数值会权重被重建基本不重建主要做缩放是否依赖校准数据依赖依赖是否需要二阶信息需要计算较重不需要主要统计激活分布量化过程速度较慢尤其大模型较快典型工具链AutoGPTQ、ExLlama、transformers、LMDeploy 等AutoAWQ、vLLM、MLC-LLM、transformers 等常见位宽配置4bitgroup_size 1284bit也常用于更低 bit 和多模态特色优势逐层输出误差控制能力强轻量、快速、对激活分布敏感场景友好选型时最直接的判断是如果你要一次性离线量化一个比较大的模型对时间不敏感想要一个成熟稳定的方案GPTQ 依然是可靠选项。如果你在反复试验不同量化位宽或者模型是多模态、任务输入分布变化大又或者在边缘设备上做部署AWQ 的轻量特性会更有优势。不过没有必要把两者看成互相替代的关系。同一个模型用不同方案量化后评价指标可能非常接近真正拉开差距的往往不是方案本身而是校准数据质量和参数配置。6. 16个格子在真实工程中的配置6.1 常见量化参数解释一个 4 bit 量化配置通常包含下面这些字段。先看一份典型 JSON{ bits: 4, group_size: 128, desc_act: false, sym: false, damp_percent: 0.01, calibration_dataset: c4 }字段含义bits量化位宽4 表示用 015 共 16 个格子group_size每组权重数量128 是最常用配置之一desc_act是否按激活值顺序处理权重列。开启后精度可能更好但计算量增加部分框架下速度更慢sym是否对称量化。false 表示使用非对称量化保留 zero_pointdamp_percent为二阶信息矩阵加的阻尼比例主要用于数值稳定性calibration_dataset校准数据集名称GPTQ 系列里常见的是 C4。这些参数看起来简单但对最终模型质量影响很大。尤其是 group_size从 128 改成 64显存和计算代价会变高但精度可能并没有明显提升从 128 改成 256显存省了但量化误差会变大必须通过评测确认是否可接受。6.2 使用 AutoGPTQ 量化模型下面是一个用 AutoGPTQ 做 4 bit 量化的通用示例。不同版本 API 可能会有少量差异但整体流程一致。from transformers import AutoTokenizer from auto_gptq import AutoGPTQForCausalLM, BaseQuantizeConfig model_path meta-llama/Llama-2-7b-hf quant_path ./llama2-7b-gptq-4bit quantize_config BaseQuantizeConfig( bits4, group_size128, desc_actFalse, damp_percent0.01, ) tokenizer AutoTokenizer.from_pretrained(model_path, use_fastTrue) model AutoGPTQForCausalLM.from_pretrained( model_path, quantize_configquantize_config, ) examples [ tokenizer(Attention is all you need., return_tensorspt), tokenizer(The quick brown fox jumps over the lazy dog., return_tensorspt), ] model.quantize(examples) model.save_quantized(quant_path)这段代码的作用是加载原始模型声明 4 bit、group_size128 的量化配置用少量校准文本触发逐层重建最后把量化模型保存到本地目录。实际使用时校准文本应该覆盖任务相关的风格和领域数量也往往需要几百条而不只是两句。6.3 使用 AutoAWQ 量化模型AutoAWQ 的量化流程更短核心是告诉它位宽、分组大小和是否使用 zero_pointfrom awq import AutoAWQForCausalLM from transformers import AutoTokenizer model_path meta-llama/Llama-2-7b-hf quant_path ./llama2-7b-awq-4bit quant_config { zero_point: True, q_group_size: 128, w_bit: 4, version: GEMM, } tokenizer AutoTokenizer.from_pretrained(model_path, use_fastTrue) model AutoAWQForCausalLM.from_pretrained(model_path) model.quantize(tokenizer, quant_configquant_config) model.save_quantized(quant_path)与 GPTQ 相比AWQ 量化过程通常更快因为不需要逐层做高代价的权重更新。它主要依赖校准文本的激活统计来决定缩放策略。6.4 加载量化模型进行推理量化完成后生产环境通常不会再用量化脚本加载模型而是用推理框架直接读量化权重。以 transformers 为例AutoGPTQ 生成的模型可以直接加载from transformers import AutoTokenizer, AutoModelForCausalLM quant_path ./llama2-7b-gptq-4bit tokenizer AutoTokenizer.from_pretrained(quant_path) model AutoModelForCausalLM.from_pretrained( quant_path, device_mapauto, torch_dtypeauto, ) inputs tokenizer(4bit量化为什么能保持效果, return_tensorspt) outputs model.generate(**inputs, max_new_tokens64) print(tokenizer.decode(outputs[0], skip_special_tokensTrue))如果使用 vLLM、LMDeploy 等服务框架加载 AWQ/GPTQ 模型的命令通常会显式声明量化方式例如vllm serve ./llama2-7b-awq-4bit/ \ --quantization awq \ --max-model-len 4096到这里16 个格子已经从“理论问题”变成了“工程参数”。你不再需要关心格子到底长什么样只需要关心 group_size、sym、desc_act 这些参数是否匹配以及模型在目标任务上的表现是否达标。7. 量化模型部署后的验证与常见问题7.1 效果验证的两条路径量化之后不能只看显存下降就认为万事大吉。建议至少跑两条验证线第一条是损失/困惑度验证。用固定评测集中计算模型在量化前后的困惑度或验证集 loss对比 FP16 baseline。正常的 4 bit 量化困惑度增加通常很轻微如果你的量化模型 loss 明显变差甚至出现乱码大概率是校准集不合适、位宽/分组配置不合理或者加载参数和量化参数不一致。第二条是任务指标验证。常见做法是跑一组与业务强相关的 few-shot 评测比如代码生成、数学推理、指令跟随。任务指标比单一 loss 更能反映实际体验。7.2 常见问题排查表问题现象可能原因排查方式解决方案加载模型失败或报权重大小不匹配量化库版本与生成模型版本不一致查看错误堆栈检查模型目录里的量化配置统一量化库版本重新导出模型生成结果乱码、胡言乱语加载时的 dtype/设备配置与量化配置不匹配检查加载参数里的 torch_dtype、device_map改为与导出时一致或使用官方推理脚本量化后指标下降明显校准集太小或与业务分布偏差大扩大校准集加入领域语料后重新量化重新量化尝试 group_size64掉点集中在长尾内容group_size 过大或 desc_act 开启状态不合适对比不同 group_size 的指标差距优先把 group_size 调整为 128 或 64推理速度反而变慢量化后权重被反量化回 FP16或算子未走优化路径检查是否调用优化 kernel看 profiling使用 vLLM、LMDeploy 等优化好量化算子的框架显存下降但吞吐没提升模型未真正使用整数/反量化后的低带宽读取用 profiler 观察权重搬运量确认推理框架支持 quantized GEMM多模态模型量化后能力失衡不同模态对量化敏感度不同分别评测视觉/文本子任务考虑混合精度对敏感模块保留更高位宽排查时最重要的一件事是先保留 FP16 baseline。没有 baseline你无法判断量化后的差距到底是方案问题还是本身评测噪声就很大。8. 什么时候16个格子真不够用低比特量化不是免费的午餐。以下情况里16 个格子可能真的不够用第一模型本身很小。参数量越少单个权重对能力的贡献越大量化误差缺乏统计稀释空间。一个 1B 模型做 4 bit 量化的风险通常高于 70B 模型。第二任务对数值精度高度敏感。比如某些数学推理、时间序列预测、科学计算场景可能对绝对值精度要求更高量化误差会被放大。第三校准数据无法覆盖实际分布。无论 GPTQ 还是 AWQ都依赖校准数据。如果校准数据来自英文通用语料部署时却大量处理代码、中文、方言或多语种重要权重可能出现误判。第四想继续压到 2 bit 以下。4 bit 的 16 个格子已经是比较紧张的边界再往下走每个权重只有 4 个格子或 2 个格子就必须配合稀疏化、混合精度、量化感知训练等手段单纯靠校准很难稳住。未来低比特量化的方向其实已经不是“16 个格子怎么用”而是如何让不同部分使用不同位宽、不同表示方式甚至跳过某些参数。1.58 bit 这样的极端位宽也被反复讨论背后思路和 AWQ 一脉相承把有限表达能力集中到真正重要的部分上。9. 最后一个建议如果你正准备在项目里引入 4 bit 量化我的建议是不要一上来就迷信某一个框架或某一种配置。先拿一个和业务最接近的小模型跑通 FP16 baseline、4bit GPTQ、4bit AWQ 三组实验记录困惑度和任务指标再看显存与吞吐收益是否值得。绝大多数踩坑根源都是校准数据不匹配、group_size 设置不谨慎和加载参数不一致而不是“16 个格子”本身。把位数从 16 bit 降到 4 bit本质上不是把模型变笨而是把误差重新分配到不影响输出的地方。GPTQ 用后验补偿做到了这一点AWQ 用激活感知做到了这一点。理解了这个前提再去看各种量化工具的文档很多参数你一眼就能判断该不该调。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑