量化精度调优指南
概述
本文档提供了一套系统化的量化精度调优方法论,遵循“确认精度问题可信→调整离群值抑制算法→调整量化策略→调整校准集→量化回退”的递进路径。
核心要点:
- 优先使用Iterative Smooth、Flex Smooth Quant等离群值抑制算法抑制激活离群值。
- 根据场景选择minmax/ssz/gptq/autoround等量化方法。
- 通过优化校准集和敏感层回退进一步提升精度。
文档详细介绍了各步骤的操作方法、算法对比和配置示例,帮助用户在可接受的精度损失内实现模型的高效量化部署。
调优路径概览:
精度调优是一个系统性过程,遵循以下递进路径:
步骤1:确认精度问题可信
↓
步骤2:调整离群值抑制算法(关键步骤)
↓
步骤3:调整量化策略
↓
步骤4:调整校准集
↓
步骤5:量化回退(最终手段)
核心目标:
在可接受的精度损失内,实现模型的高效量化部署。
使用前准备
安装 msModelSlim 工具,详情请参见《msModelSlim工具安装指南》。
调优步骤详解
步骤1:确认精度问题可信
在开始调优前,必须排除环境干扰,确保问题真实存在:
| 验证项 | 具体操作 |
|---|---|
| 推理引擎验证 | 先用浮点模型在目标推理引擎上测评,确认是否能复现原始精度 |
| 测评结果检查 | 检查量化模型的测评输出,确认无上下文截断、超时等非量化问题 |
| 确定波动范围 | 了解测评数据集本身的精度波动范围,判断当前精度损失是否异常 |
步骤2:调整离群值抑制算法(关键步骤)
核心问题:激活值中的离群值会大幅扩展量化范围,占用有效量化比特,导致精度损失。
解决思路:使用离群值抑制算法,将激活的量化难度“转移”到权重上。
总结建议
- 优先选用Iterative Smooth算法:运行速度快,精度较高,是大多数场景下的首选方案。
- 对称性选择:非对称离群值抑制算法在大多数情况下优于对称方案,但需提前确认推理引擎是否已完成对非对称离群值抑制算法的适配支持。
- 参数调优:若Iterative Smooth算法的量化精度未达预期,可通过调整
alpha参数进行针对性优化。 - 进阶方案:若调整后精度仍无法满足需求,可进一步尝试启用Flex Smooth Quant算法,或通过叠加QuaRot算法实现协同优化。INT4/w4a8可以使用Flex AWQ SSZ算法。
步骤3:量化算法选择
根据量化对象(权重/激活)和比特数选择合适算法。量化算法选择包括权重量化方法选择和激活量化方法选择两部分。
权重量化
配置示例 (YAML)
在量化配置文件中,权重量化通常在 linear_quant 处理器的 qconfig.weight 部分进行配置(autoround 则需使用专门的 autoround_quant 处理器):
- type: "linear_quant" # 处理器类型:线性层量化
qconfig:
weight: # 权重量化配置
scope: "per_channel" # 权重量化粒度:逐通道量化
dtype: "int8" # 量化数据类型。默认:int8
symmetric: true # 是否对称量化。默认:true
method: "minmax" # 量化方法。默认:minmax
总结建议
- INT8权重量化:优先使用
minmax方法,在保证精度的同时速度最快。 - INT4等低比特权重量化:优先使用
ssz方法,若精度不足再尝试autoround、gptq。 - 量化粒度 (
scope):权重量化建议使用逐通道(per_channel),这比逐张量(per_tensor)粒度更细,能获得更高的量化精度。 - 对称性 (
symmetric):权重量化通常设置为true(对称量化),计算更简单高效。 - AutoRound:高精度上限。适用于对精度极度敏感的场景,虽然运行较慢,但量化效果最接近浮点。
激活值量化
激活量化方法对比
| 量化方法 | 特点 | 量化精度 | 量化速度 | 适用场景与建议 |
|---|---|---|---|---|
| minmax | 统计激活张量的最小值和最大值来确定量化范围,方法简单,计算速度快 | ★ | ★★ | 通用首选。适用于绝大多数模型量化场景 |
| histogram | 通过分析直方图分布,搜索最优截断区间以过滤激活离群值 | ★★ | ★ | 当激活分布存在长尾且 minmax 效果不佳时尝试,有助于提升 W8A8 精度 |
| fa3_quant | 针对 MLA 架构中 Q/K/V 的 Per-head(逐头)粒度 INT8 量化 | ★★ | ★★ | DeepSeek-V3/R1 系列专属。适应不同注意力头的分布差异,需使用专门的 fa3_quant 处理器 |
激活值量化粒度选择
激活值量化支持多种粒度,对精度和性能有直接影响:
| 粒度类型 | 特点 | 适用场景 |
|---|---|---|
| per_tensor | 整个张量使用一组量化参数。静态量化。计算简单,性能最好,几乎所有硬件都支持。但当张量内数据分布差异大时,量化误差显著 | 追求最佳性能时使用 |
| per_token | 每个token独立使用一组量化参数。动态量化。量化粒度更细,能获得更高的量化精度,但计算也更复杂,性能较差 | 追求更高精度时使用 |
| pd_mix | prefill阶段使用 per_token,decode阶段使用 per_tensor。混合策略。旨在平衡精度和性能 |
需要平衡精度和性能时使用,有助于提升 W8A8 精度 |
配置示例 (YAML)
在量化配置文件中,激活值量化通常在 linear_quant 处理器的 qconfig.act 部分进行配置:
- type: "linear_quant" # 处理器类型:线性层量化
qconfig:
act: # 激活值量化配置
scope: "per_tensor" # 静态量化标识:整个张量共用量化参数
dtype: "int8" # 量化数据类型。默认:int8
symmetric: false # 是否对称量化。默认:false
method: "minmax" # 量化方法。默认:minmax
weight: # 权重量化配置
scope: "per_channel" # 权重量化粒度:逐通道量化
dtype: "int8" # 量化数据类型。默认:int8
symmetric: true # 是否对称量化。默认:true
method: "minmax" # 量化方法。默认:minmax
总结建议
- 量化方法:优先使用
minmax方法,当精度不足时可尝试histogram方法。 - 量化粒度 (
scope):- 追求性能时,使用
per_tensor(静态量化)。 - 追求精度时,使用
per_token(动态量化)。 - 需要平衡精度和性能时,使用
pd_mix(混合策略)。
- 追求性能时,使用
- 对称性 (
symmetric):激活值量化通常设置为false(非对称量化),以更好地适应非零中心的数据分布。 - PDMIX:平衡策略。旨在平衡推理过程中的激活量化精度与计算性能。
步骤4:校准集调整
当算法调整效果有限时,通过优化校准数据来提升量化模型精度。校准集的质量直接影响量化参数的准确性。
校准集优化策略
| 调整策略 | 具体操作 | 优化目的 |
|---|---|---|
| 增加数据量 | 适当增加数据量(建议10-50条样本) | 提升量化参数估计的准确性 |
| 匹配应用场景 | 使用与模型应用场景匹配的数据(如中文模型用中文数据,代码模型用代码数据) | 使校准数据更贴近实际应用场景 |
| 平衡数据分布 | 从多个数据集中抽取样本混合,平衡数据分布 | 提升数据分布的多样性和均衡性 |
| 删除异常数据 | 删除导致精度显著下降的校准数据 | 减少异常样本对量化参数的干扰 |
| 加入badcase | 加入模型在该数据集上的badcase数据,以更好地反映模型真实输入分布 | 帮助量化模型学习困难样本,提升精度 |
总结建议
- 数据量:建议使用10-50条样本,过少可能无法充分估计量化参数,过多则可能增加量化时间。
- 场景匹配:优先使用与模型应用场景匹配的数据,确保校准集能代表实际使用场景。
- 数据质量:及时删除异常数据,避免对量化参数产生负面影响。
- 困难样本:适当加入badcase数据,有助于提升模型在困难样本上的量化精度。
步骤5:量化回退(最终手段)
当通过算法和校准集调整仍无法满足精度要求时,对模型中最敏感的层进行回退,使其保持高精度(FP16/BF16),以挽回量化带来的精度损失。
使用场景:
- 通过步骤1-4调整后,精度仍无法满足精度要求
- 需要在精度和性能之间寻求更精细的平衡
- 某些特定层对量化极度敏感,需要保持高精度
操作流程
第一步:敏感层分析
使用msModelSlim提供的敏感层分析工具识别量化敏感层。详细使用方法请参考《量化敏感层分析使用指南》。
功能说明:
- 自动评估:工具会自动评估模型中线性层对量化操作的敏感程度,并为每个可分析对象生成量化敏感度评分。
- 决策依据:用户根据生成的敏感度评分,决定哪些高敏感层需要回退。
第二步:配置回退
根据第一步的分析结果,在量化策略的YAML配置文件中,通过exclude字段排除需要回退的高敏感层。
配置示例
apiversion: modelslim_v1 # 协议版本
spec:
process: # 处理器列表
- type: "linear_quant" # 处理器类型:线性层量化
qconfig:
act: # 激活值量化配置
scope: "per_tensor" # 静态量化标识:整个张量共用量化参数
dtype: "int8" # 量化数据类型。默认:int8
symmetric: false # 是否对称量化。默认:false
method: "minmax" # 量化方法。默认:minmax
weight: # 权重量化配置
scope: "per_channel" # 量化粒度。逐通道量化
dtype: "int8" # 量化数据类型。默认:int8
symmetric: true # 是否对称量化。默认:true
method: "minmax" # 量化方法。默认:minmax
include: ["*"] # 包含的层,支持通配符。默认:["*"]
exclude: ["*model.layers.*.mlp.down_proj*"] # 排除的层。默认:[]。此处回退所有mlp.down_proj层
总结建议
- 优先回退对象:根据经验,
mlp.down_proj层通常是量化敏感度最高的层之一,应优先考虑回退。 - 权衡代价:回退会部分减少量化带来的性能提升和内存节省收益,需要根据具体的业务目标来决定回退的层数和范围。
- 回退策略:建议从敏感度最高的层开始,逐步回退,在精度和性能之间找到最佳平衡点。