☰
模型量化实战指南:从PTQ、QAT选型到精度调优与部署避坑
2026/10/21 5:16:24 网站建设 项目流程

模型量化这个事儿,我以前总觉得是“训练完顺手加个参数”的小事,直到自己亲手把一个开源大模型塞进生产环境,被显存、延迟和精度同时按在地上摩擦之后,才意识到这压根是一整套系统工程。从理论到实践,中间隔着校准集、缩放因子、混合精度、算子融合,还有一堆文档里没写、只能靠踩坑才能总结出来的细节。

如果你正在做AI原生应用,比如把大模型部署成线上推理服务,或者在手机、边缘设备上跑本地模型,这篇文章就是写给你看的。我会完整拆解量化的核心原理、方案选型(PTQ、QAT、动态量化)、实操校准流程、精度调优方法和部署阶段的坑点,尽量做到看完就能照着动手。

1. 为什么AI原生应用绕不开模型量化

1.1 显存和带宽才是真正的瓶颈

很多人一提到模型推理,第一反应是“算力不够”,也就是FLOPs太高。但在实际部署AI原生应用的时候,尤其是跑大模型这种动辄几十上百亿参数的模型,最先卡住的往往是显存容量和显存带宽。

我举个例子算笔账:一个70亿参数的全精度模型(FP32),参数体积大概是28GB;哪怕换成BF16,也需要14GB。如果模型是自回归结构,推理时要频繁读取全部权重,显存带宽的占用会非常恐怖。你可能会说“我有A100/H100,显存管够”,但你要知道,AI原生应用不只是跑一个离线脚本,它往往要同时服务多个用户、多路并发请求。显存越大,能塞进去的并发实例才越多,单位成本才会降下来。

量化的核心思路很简单:用更少的bit去表示权重和激活值。把FP32转成INT8,理论上模型体积直接变成原来的四分之一;FP16转INT8,体积减半。加减速和降低延迟。更关键的是,显存占用降下来之后,单卡能承载的请求数量上涨,这在成本维度上带来的收益是实打实的。

1.2 什么场景必须量化,什么场景可以先缓缓

不是所有项目都需要一上来就跑量化。我自己的判断标准是分场景的:

  • 如果模型只在离线批量跑,比如数据处理管道、离线生成报告,一次跑几分钟也没关系,那量化可以往后放。
  • 如果是线上实时推理服务,需要低延迟、高并发,那量化基本是必选项。
  • 如果是边缘设备、手机端、嵌入式设备,内存和算力都有限,量化几乎是唯一的选择。
  • 如果目标硬件支持FP8或者BF16推理,而且显存充裕,可以先不量化为INT8,优先做其他优化。

另外提醒一句:量化不是免费的午餐。它会在一定程度上改变模型的数值分布,带来精度损失。不同模型对量化的敏感度差异巨大,有的模型量完几乎无损,有的一量就崩。所以科学的做法是“先评估后量化”,不要盲目跟风。

1.3 量化是一道数学题,更是一道系统题

很多人以为量化就是用工具跑一下,得到一个量化模型就完事了。实际上,量化模型落地要面对的问题包括:

  • 数值分布怎么统计才准(校准方法的选择);
  • 每个张量用同一个缩放因子还是每通道一个(per-tensor还是per-channel);
  • 量化后的算子是否能真正调用到硬件的低精度计算单元(比如GPU上的INT8 Tensor Core或CPU上的VNNI指令);
  • 混合精度怎么处理,哪些层必须保留高精度,哪些层可以激进量化;
  • 量化感知训练要不要做,需要多少数据和算力。

所以,量化绝不只是“int8 = fp32 / 255”这么简单。它涉及数值分析、系统架构、硬件的协同设计。这篇文章会尽量把这些层面都串起来讲清楚。

2. 量化方案选型:PTQ、QAT和动态量化怎么选

2.1 三种主流方案的原理对比

业界主流量化方案无非三类:训练后量化(PTQ, Post-Training Quantization)、量化感知训练(QAT, Quantization-Aware Training)、动态量化(Dynamic Quantization)。三者的根本区别在于“什么阶段引入量化误差”以及“如何获取量化参数”。

先看PTQ。它的流程最粗暴:拿一个训练好的模型,喂一小部分校准数据,统计激活值和权重的分布,然后计算出量化参数(缩放因子和零点),直接把权重从浮点转成整数,完成。整个过程不需要重新训练模型,成本低、速度快,是大多数AI原生应用的首选方案。我自己的经验是:现在很多开源模型在发布时已经做得比较“皮实”,直接PTQ到INT8往往就能保住90%以上的精度。

再看QAT。它的流程是在训练过程中,在前向传播里插入“伪量化节点”,也就是模拟量化误差,让模型在训练中逐步适应低精度带来的扰动。反向传播仍然使用浮点梯度来做更新。QAT的精度通常比PTQ更高,但代价是需要额外的训练资源、调整超参数,训练时间也拉长。不是每个团队都负担得起。

动态量化是另一种思路:权重提前量化成INT8,但激活值在运行时才按实际分布动态计算量化参数。好处是对激活值分布剧烈变化的情况更鲁棒,坏处是动态计算有额外开销,适合部分算子而不是全模型。

我做了一个简单对比表,方便你做选型判断:

特性PTQQAT动态量化
需要重新训练否是否
数据需求少量校准集完整训练数据少量校准集
实现成本低高中
精度表现良好,敏感模型可能掉点最优稳定,但有运行时开销
适用场景快速上线、算力有限精度要求高且资源充足CPU部署、分布动态变化大

2.2 量化粒度:Per-tensor还是Per-channel

选定PTQ还是QAT之后,紧接着要决定量化粒度。简单来说,per-tensor是整层所有数值共享一个缩放因子,per-channel是每个输出通道各算各的。

per-tensor实现简单,但问题在于:如果某些通道存在明显离群值(outlier),整体分布会被拉宽,导致其他通道的精度白白下降。per-channel能把每个通道的分布单独校准,精度更好,但硬件实现上更复杂,不是所有推理框架都原生支持卷积层外加per-channel量化。

有个通用经验:权重矩阵的量化,推荐per-channel;激活值的量化,如果框架支持,尝试per-tensor和per-channel都跑一遍,看哪个精度表现更好。大模型里的矩阵乘操作中,量化粒度对精度影响非常明显,有时候只是把weight的per-tensor改成per-channel,困惑度就能回升一大截。

2.3 后端硬件:量化也得看“厨具”

选型时最容易被忽略的就是目标硬件的指令集和数值格式支持。你费尽心思量化出的模型,如果推理引擎不调用硬件低精度指令,那前期收益都得打折扣。

在GPU上,通常要关注是否支持INT8的Tensor Core运算,这能大幅加速矩阵乘法。TensorRT、vLLM这些框架,对INT8的支持已经相当成熟。在CPU上,x86平台需要看是否支持VNNI或AMX指令;ARM平台要关注是否支持相应的INT8点积指令。在NPU上,各家情况更分裂,需要仔细查工具链支持的量化格式,比如是否支持对称量化、非对称量化、混合精度等。

我的建议是:先选硬件,再选推理框架,最后选量化方案。如果推理框架自带最好的量化工具链,就别重复造轮子。框架帮你解决算子融合、指令调度这类底层麻烦,比你自己蛮力优化靠谱得多。

3. 实操记录:把大模型量化并部署上线的完整流程

3.1 准备校准集:质量比数量重要

PTQ最关键的一步就是校准。校准数据的来源最好是真实业务里会出现的输入。比如你做的是聊天机器人,就准备一批用户问题;你做的是代码生成,就准备一批代码任务描述。随机从网上拉一批文本,往往效果不如几百条高质量业务样本。

校准集的数量不需要很多,通常256到1024条就够。但有一点要特别注意:校准集不能太“干净”。如果全部是短文本,那长文本输入下激活值分布没被覆盖,量化后一遇到长文本就可能表现异常。尽量让采样覆盖不同的长度、主题和表达方式。

在实际项目中,我自己会额外保留一份评估集,评估集和校准集严格不重叠,这样量化后的精度数据才有说服力。

校准集准备好之后,通常需要在模型的前向推理中统计每一层的激活值分布。很多框架提供了自动hook机制,不需要你手写前向逻辑。但如果你用的是一个比较底层的库,就需要自己注册hook或改写forward,把每层的输出分布记录下来。这一歩比较琐碎,但也是后面调优的基础。

3.2 计算缩放因子的两种常用方法

得到分布之后,就要计算每个张量的缩放因子。业界常用的两种方法是:

  • 最大绝对值法(MaxAbs):直接取统计区间内所有绝对值的最大值,然后用公式scale = max_abs / 127去算(INT8非对称量化还需另算零点)。实现简单,但对离群值非常敏感,分布有长尾时不好用。
  • KL散度法(Entropy/Percentile):这种做法是先尝试一堆候选的阈值,把被截断掉的部分和重新量化之后的分布做对比,找一个让信息损失最小的阈值。相比MaxAbs,它对偏态分布更友好,也是很多框架里默认的校准方式之一。

要注意的是,MaxAbs实现起来简单,但并不是说它总是差劲。如果模型已经做过类似归一化的处理,数值范围比较稳定,MaxAbs的差异其实不大。但大规模语言模型经常有Hidden State的极端值,这时KL散度或者百分位法通常更稳。

校准之后得到的是一个缩放因子表,一般以张量为单位保存。如果之后发现精度不够,可以考虑按层调试,而不是直接推倒重来。

3.3 量化后精度验证与误差定位

量化完不等于结束,必须做精度验证。大模型场景里最常用的两个指标是困惑度(Perplexity)和下游任务准确率。困惑度适合衡量语言模型的整体输出质量,下游任务(如问答、文本分类)可以反映实际业务效果。两个都测,不要只测一个。

一旦发现精度掉点,排查的顺序我建议是:

  1. 先看是权重的问题还是激活值的问题。可以把权重保持FP16,只量化激活值,然后反过来再试一次。
  2. 再看是哪些层掉点最严重。某些层(比如最后的输出层、Embedding层、Norm层)对精度极度敏感,直接排除在量化范围之外往往就能解决问题。
  3. 最后调整校准方法或校准集。把MaxAbs改成KL散度,或者增加校准数据,重新跑一遍。有时只换校准样本就能显著改善。

还有一种情况:量化本身没问题,但推理框架里某些算子不支持INT8,导致部分子图反复做反量化(dequantize),既慢又引入额外误差。所以精度验证时也要看算子是否都落到了低精度执行路径上。

4. 常见坑点与排查技巧实录

4.1 精度掉点严重,优先级怎么排

如果是刚接触量化,我见过太多人一上来就怀疑自己“做法不对”,然后反复重新校准,折腾半天没效果。实际上,精度掉点严重时,优先级应该是这样的:

  • 第一优先:检查异常值层。找出分布特别奇怪、离群严重的层,通过排除法确定这些层是不是拉低了全局精度。尝试对敏感层做混合精度,也就是保留FP16。
  • 第二优先:改校准方法。当前方法不好用就换一个,KL散度、百分位、MSE方法都可以试。也别只试一种校准集,多个校准集的结果对比一下。
  • 第三优先:换量化粒度或对称/非对称。把权重换成per-channel,把激活值换成per-tensor,看看效果。
  • 最后再考虑QAT。如果前面所有方案都救不回来,那就得付出训练成本了。

我遇到过最典型的案例是:某个模型的隐藏层里存在大量绝对值超过几十的离群点,直接导致INT8量化的缩放因子被拉得巨大,普通数值被压成接近0。后来减少离群层的量化范围,或者把离群通道单独处理,精度立刻回升。处理离群值的优先级真的很高。

4.2 量化后运行比理论慢,怎么找原因

还有一种常见情况是:量化之后模型体积变小了,但推理延迟没有任何改善,甚至更慢。这通常不是量化本身的问题,而是没吃到低精度计算的红利。

原因一般有这几种:

  • 算子融合没启用。调用框架时没有开启图优化,导致量化、反量化频繁发生,额外开销比省下的计算还大。
  • 模型里存在大量的非量化算子。比如某些激活函数、归一化层,它们在高精度下运行,需要不停地把数据从INT8转回FP32。
  • 数据排布问题。INT8在很多硬件上需要特定内存排布才能高效计算,如果排布不对,访问效率会大幅降低。
  • 小算子过多。对单次计算量很小的算子,低精度带来的收益远小于kernel启动和内存拷贝的开销。

排查方法也不复杂:先做一个逐算子的性能剖析。把耗时前20的算子列出来,看哪些还是Float32执行。然后针对性地开算子融合,或者手动改写子图。大模型推理场景里,把GELU、LayerNorm这些融合进前一个算子,收益往往立竿见影。

4.3 混合精度与敏感层处理

既然叫混合精度,那就意味着不需要从头到尾完全一致。整套模型里有大量层冗余度高,可以直接INT8,而少量关键层需要保留更高精度。

以典型Transformer结构为例,经验法则是:

  • Embedding层通常不需要量化,因为它的参数直接和词表映射有关,量化后可能导致Vibration;
  • 注意力模块里的QKV投影通常可以量化,但有些模型对这部分敏感,需要测了才知道;
  • 输出层的LM Head非常敏感,建议保持FP16/BF16,尤其是每一步生成都要计算词表概率的场景;
  • LayerNorm和激活值统计里的方差、均值最好保持浮点,因为它们动态性很强。

选择混合精度最简单的办法就是:先把全部层量化到INT8,然后逐个把敏感层恢复到FP16,比一次一个地观察指标变化。虽然有点费时间,但能得到“最小代价、最大收益”的组合。

5. 部署侧的经验:量化只是第一步

5.1 图优化与算子融合的配合

我见过不少团队把精力全花在校准和量化上,结果部署时因为算子融合没做好,性能远低于预期。预处理阶段,第一步往往是图优化:

  • 常量折叠:把不需要动态计算的常量提前算好,存成固定的数据。
  • 算子融合:把多个连续操作合并成一个。比如卷积或矩阵乘后面跟的偏置加法和激活函数,融合成一个算子,减少多次读写。
  • 去除冗余节点:把没有任何实际作用的identity节点清理掉。

在量化模型里,算子融合还有一个额外价值,就是减少量化和反量化来回切换的次数。数据从FP32变成INT8,传给算子,结果又要转回FP32给下一个算子用,来回转换非常伤性能。融合后这些边界消失,带宽消耗也下来了。

5.2 评估量化模型的几个核心指标

部署前,建议建立一套多维度的评估标准,不只盯一个指标。

  • 模型精度指标:困惑度、下游任务准确率,这决定量化后模型质量是否可接受。
  • 显存占用:加载量化模型后实际占用的显存/内存,决定并发容量。
  • 首Token延迟(TTFT):用户输入到看到第一个输出token的时间,这直接影响交互体验,尤其是流式输出场景。
  • 每个Token生成延迟:生成后续token的速率,在长文本生成里尤其重要。
  • 吞吐量( tokens/s):单卡总吞吐,直接影响成本和机器规模。

我自己习惯的做法是,每次量化实验都记录这四个维度的数据,并确保在同一条数据集、同一个输入长度分布下测试,否则数据没有对比价值。Quantization后能跑多快,绝不能靠“感觉”判断,要拿数据说话。

5.3 实操小技巧与一些体会

最后分享几个我在实践里总结的技巧:

  • 始终保留一份原始FP16模型。量化模型有问题时,能够快速回到高精度版本对比定位。
  • 校准集要做成长期可用的标准资产。每次模型迭代后,都用同一套校准集做评估,方便对比。
  • 调试量化时,记录每一层的统计信息。我一般会把各层激活值的min/max/均值/方差输出成一份报告,精度出问题时直接翻报告定位。
  • 如果使用某个推理框架,先确认其量化格式兼容性。不同框架对量化模型的格式要求不一,有的要ONNX,有的要自定义格式,提前对接好能少走很多弯路。
  • 千万别忽略批处理效应。真实部署时并发请求往往做了动态批处理,这和单请求评测的延迟数据差别很大,建议测试时直接模拟线上请求模式。

从理论到实践,模型量化本质上是一个“误差换性能”的博弈。它没有绝对的最佳方案,只有最适合你业务场景的方案。做量化的核心流程其实是有章可循的:先选硬件和推理框架,再决定PTQ、QAT还是混合精度,然后用有代表性的校准集去量化,用多维度的指标去验证,最后在部署侧做好算子和图优化。每一步都有细节,也都可能踩坑。希望这篇内容能帮你在启动量化项目时少走一点弯路,尤其是遇到精度掉点或者性能没提升的时候,不要慌,对照上面的排查顺序,一个一个去测、去调。量化不是一个可以“一把梭”的自动流程,但顺着这条链路走下来,你会发现它其实是可控、可复现、可优化的事情。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询