一旦拥有训练好的模型和具有代表性的校准数据集,训练后量化(PTQ)的核心工作就是确定量化参数:比例因子(s)和零点(z)。这些参数定义了从校准期间观察到的浮点范围到目标整数范围(例如 INT8,通常为 [-128, 127])的映射。存在多种算法来计算这些参数,每种算法在简易性、对异常值的稳定性以及潜在的精度影响之间都有其自身的权衡。最常见的几种算法将被描述。
MinMax 量化
这是最简单直接的方法。它使用给定张量(或量化组)在校准数据中观察到的绝对最小值和最大值来确定范围。
工作原理:
- 在校准期间,跟踪被量化张量遇到的最小值(xmin)和最大值(xmax)。
- 直接使用这些值来计算比例因子和零点。
对于非对称量化,零点可以是目标范围内的任意整数,其公式为:
s=Qmax−Qminxmax−xmin
z=round(Qmax−sxmax)
这里,Qmin 和 Qmax 表示目标整数范围的最小值和最大值(例如,有符号 INT8 的 -128 和 127)。零点 z 本质上是对应于浮点值 0.0 的整数值。
对于对称量化,范围以零为中心,强制零点 z 为 0(对于有符号整数)。比例因子由观察到的最大绝对值确定:
s=Qmaxmax(∣xmin∣,∣xmax∣)
z=0
(这里,Qmax 对于有符号 INT8 将是 127,将范围 [−max(∣…∣),+max(∣…∣)] 映射到 [−127,127]。)
优点:
- 实现和理解起来非常简单。
- 保证所有观察到的校准值在量化后都落在可表示的范围内(没有基于校准数据的裁剪)。
缺点:
- 对异常值高度敏感。单个极端值,即使不常见,也会显著扩大所需范围(xmax−xmin 或 max(∣xmin∣,∣xmax∣))。这会使得比例因子 s 变大,意味着可用于表示大部分数据分布的整数值更少,可能导致明显的量化误差和精度下降。
直方图显示了包含和不包含异常值的数据分布。MinMax 量化使用包含异常值的整个范围(例如,高达 1.5),这可能会降低 0.1 到 0.3 之间更常见值的精度。
百分位数量化
为减轻 MinMax 对异常值的敏感性,百分位数量化使用分布尾部的值,但不是绝对的极端值。
工作原理:
- 在校准期间收集值的分布(通常以直方图形式)。
- 选择下限和上限百分位数阈值(例如,0.1% 和 99.9%,或 1% 和 99%)。
- 确定对应于这些百分位数的浮点值,我们称之为 plow 和 phigh。
- 在比例因子和零点计算公式中(无论是对称还是非对称),使用 plow 和 phigh 代替 xmin 和 xmax。
- 任何落在 [plow,phigh] 范围之外的原始浮点值在量化期间都将被截断(或饱和)到最小或最大可表示整数值。
优点:
- 比 MinMax 对异常值更具抵抗力。通过忽略最极端的值,它通常会得到更小的比例因子 s 和更好的数据分布精度。
- 实现相对简单,只需收集直方图和计算百分位数。
缺点:
- 对被截断的异常值引入饱和误差。如果这些异常值带有重要信息,截断它们可能会对精度产生负面影响。
- 需要选择合适的百分位数,这成为一个需要调整的超参数。最佳百分位数可能因不同层或模型而异。
熵(KL 散度)量化
该方法采用了一种更偏向信息论的方式。它旨在找到一个量化范围(由裁剪阈值定义),以最大程度地减少原始浮点分布与量化分布之间的信息损失。用于衡量这种信息损失最常用的度量是 Kullback-Leibler (KL) 散度。
工作原理:
- 从校准数据集中收集激活值的直方图。这表示原始概率分布 P。
- 遍历不同的可能裁剪阈值。对于每个阈值:
a. 根据阈值定义一个量化范围(通常是对称的,即 [−threshold,+threshold])。
b. 使用此范围量化阈值内的值。超出阈值的值将被饱和到最小/最大量化值。
c. 创建一个新直方图,表示量化后再反量化(将其映射回浮点近似值)后的分布 Q。由于量化误差和饱和,此分布 Q 将与 P 不同。
d. 计算原始分布 P 和量化分布 Q 之间的 KL 散度。DKL(P∣∣Q)。
- 选择导致最小 KL 散度的阈值。该阈值根据此标准定义了量化的最佳范围。
- 根据所选阈值计算最终的比例因子(s)和零点(z),类似于对称 MinMax,但使用最佳阈值而不是绝对最大值。
优点:
- 在常见 PTQ 算法中通常能达到最佳精度,特别是对于非均匀或偏斜分布,因为它直接尝试保持整体分布形状。
- 提供了一种更具原则性的方式来处理饱和(裁剪异常值)和量化误差(内部值精度)之间的权衡。
缺点:
- 在校准期间计算成本较高,因为需要进行直方图统计并迭代测试多个阈值以及计算 KL 散度。
- 结果可能对用于分布直方图表示的 bin 数量敏感。
算法选择
最佳 PTQ 算法通常取决于具体情况:
- 权重: 权重分布通常相对稳定且大致围绕零对称。MinMax 或百分位数方法(通常是对称的)常被使用且表现良好。
- 激活: 激活分布可能因输入数据和层类型而明显不同。它们通常是非对称的,并且可能存在明显的异常值。熵(KL 散度)或百分位数方法常用于激活,以更好地处理这些特点。非对称量化方案对于激活也更常见。
- 性能与精度: MinMax 在校准期间最快,但最容易因异常值导致精度损失。熵在校准期间最慢,但通常能提供最高精度。百分位数在这两者之间提供了一种平衡。
在实践中,Hugging Face Optimum 或 PyTorch 的量化模块等库通常提供这些算法的实现,让您能够尝试并选择最符合特定模型和任务精度及性能要求的方法。您甚至可以在同一模型中混合使用权重和激活的不同策略。