趋近智
训练后量化 (PTQ) 提供了一种实用方法,可以在无需模型重训练的显著成本和复杂性的情况下,实现低精度推理的性能优势,这与量化感知训练 (QAT) 不同。主要思路是获取一个预训练的浮点模型,并在训练完成后,将其权重和激活值转换为INT8或FP8等低精度格式。编译器在此转换自动化中扮演主要角色,负责转换模型表示、优化量化图,并最终生成高效的低精度代码。
典型的PTQ编译流程包含几个不同阶段,旨在将高层模型图转换为优化过的低精度可执行版本。
大多数PTQ流程的第一步是校准。由于我们正在从连续浮点范围转换为离散定点范围(例如,INT8的256个级别),因此需要确定最优映射。此映射由每个需要量化的张量(权重和激活值)的尺度 (s) 和零点 (z) 参数定义。这种关系通常是仿射的:
浮点值≈s×(量化值−z)为了找到合适的 s 和 z 值,编译器或专用量化工具会分析每个张量内的值分布。这需要一个有代表性的数据集,通常称为校准数据集。模型以浮点模式运行,并使用此数据集的输入,收集权重和中间激活值的运行时统计信息(范围、分布)。
常见的校准方法包括:
校准完成后,编译器就获得了每个目标量化张量所需的 s 和 z 参数。
收集到校准数据后,编译器会修改模型的中间表示 (IR)。主要转换是向图中插入 quantize(量化) 和 dequantize(反量化) 操作(通常缩写为 q 和 dq)。
quantize 操作接收一个浮点张量及其学得的尺度/零点,生成一个低精度张量(例如INT8)。dequantize 操作执行逆向转换,使用其关联的尺度/零点将低精度张量转换回浮点数。一个原始的FP32操作,如 Conv2D,被替换为如下序列:
输入 (FP32) -> quantize -> 输入 (INT8)
权重 (FP32) -> quantize -> 权重 (INT8)
输入 (INT8), 权重 (INT8) -> Conv2D_INT8 -> 输出 (INT32 or INT8)
输出 (INT32 or INT8) -> dequantize -> 输出 (FP32)
这种初步插入创建了一个图,其中计算以低精度执行,但操作之间的接口可能仍然涉及转换回FP32。校准期间确定的尺度和零点作为属性嵌入到这些 quantize、dequantize 以及IR中新的低精度算子节点内。
Q/DQ 节点的简单插入通常由于过多的转换而导致次优性能。因此,编译器会应用针对量化图的特定优化处理步骤:
QDQ 取消: 使用相同(或兼容)量化参数的相邻 dequantize -> quantize 对是冗余的,可以去除。当一个量化层的输出直接作为另一个层的输入时,这种情况经常发生。
量化算子合并: 标准算子合并(例如合并 Conv + Bias + ReLU)需要考虑量化。目的是将 Q/DQ 操作 结合 到主要计算核中。
quantize 操作通常可以合并到 消费 操作中(例如,INT8卷积读取FP32输入并在内部量化)。dequantize 操作通常可以合并到 生产 操作中(例如,INT8卷积写入FP32输出,并在内部执行反量化)。再量化: 当一个INT8操作的输出(可能累积在更宽的整数类型如INT32中)需要作为另一个INT8操作的输入时,需要一个 requantization(再量化)步骤。这涉及将中间结果(例如INT32累加器)重新缩放到下一层INT8输入所期望的尺度和零点。这通常涉及通过计算出的尺度因子(源自输入、权重和输出尺度)进行整数乘法,然后进行右移操作。
(注意:确切的公式取决于具体的量化方案和硬件实现,通常涉及尺度因子 sinsw/sout 的定点算术近似。)
以下图表说明了优化如何转换图的简化视图:
PTQ 图转换视图。初步插入量化/反量化节点(左侧),随后进行优化处理步骤,例如合并(右侧),其中Q/DQ操作被吸收到计算核中。
图级优化之后,编译器将高层量化操作(例如 int8_conv2d)降低为更底层的IR构造,可能包括显式整数算术、用于再量化的移位以及适用的向量操作。这种降低后的表示随后被后端用于生成目标特定代码,如果可用,则采用专门的低精度硬件指令(例如Intel VNNI、ARM NEON点积指令、NVIDIA Tensor Core IMMA指令)。
尽管PTQ显著简化了量化模型的部署,但它并非万能。
PTQ 编译流程是机器学习部署工具包中的重要组成部分,通过自动化模型转换、优化和低精度执行的代码生成等复杂过程,提供了相对快速的性能改进途径。了解这些流程有助于工程师有效应用PTQ并诊断可能与准确性或性能相关的问题。
这部分内容有帮助吗?
© 2026 ApX Machine Learning用心打造