量化准确性调试
本文提供了一些高层次的策略来提升量化的准确性。如果量化后的模型相较于原模型存在误差,我们可以将其误差分为以下几类:
-
数据不敏感错误 - 由于模型量化的内在误差导致大量输入数据出现较大误差
-
数据敏感错误 - 由异常输入数据引起,输入数据中的小部分存在较大误差
-
实现错误 - 量化内核与参考实现不符
数据不敏感错误
通用提示
-
对于PTQ(训练后量化),确保用于校准的数据能够代表你的数据集。例如,在分类问题中,建议每个类别都有多个样本,并且总的样本数量至少为100。使用更多的数据进行校准除了会增加校准时间外没有其他负面影响。
-
如果你的模型包含 Conv-BN 或 Linear-BN 结构,建议将它们融合。在 FX 图形模式量化中,此操作会自动完成。而在 Eager 模式量化中,你可以手动使用
torch.ao.quantization.fuse_modules
API 来进行。 -
提高有问题的操作的数据类型精度。通常,fp32的准确度最高,其次是fp16,然后是动态量化int8,最后是静态量化int8。
-
注意:这是以牺牲性能来换取准确性的。
-
注意:不同后端中,每个操作和数据类型的内核可用性可能会有所不同。
-
注意:数据类型转换会增加额外的性能成本。例如,
fp32_op -> 量化 -> int8_op -> 去量化 -> fp32_op -> 量化 -> int8_op -> 去量化
的性能会低于fp32_op -> fp32_op -> 量化 -> int8_op -> int8_op -> 去量化
,因为前者需要更多的数据类型转换。
-
-
如果你在使用通道量化训练 (PTQ),考虑使用量化感知训练 (QAT) 来恢复部分由于量化的精度损失。
Int8 量化技巧
-
如果你使用的是逐张量权重量化,考虑改为逐通道权重量化。
-
如果你在fbgemm上进行推理,确保将reduce_range参数设置为False(如果您的CPU是Cooperlake或更新版本),否则设置为True。
-
检查输入激活分布在不同样本间的差异。如果差异较大,该层可能更适合动态量化而非静态量化。
数据敏感错误
如果你使用的是静态量化,而一部分输入数据导致了较高的量化误差,你可以尝试:
-
调整你的校准数据集,使其更好地代表你的推理数据集。
-
手动检查(使用Numeric Suite)哪些层的量化误差较高。对于这些层,可以考虑保持它们为浮点数,或者调整观察器设置以选择更合适的比例和偏移值。
实施错误
如果你在使用自定义后端的 PyTorch 量化时,可能会发现操作(例如 dequant -> op_fp32 -> quant
)的参考实现与目标硬件上该操作的量化实现(如 op_int8)之间存在差异。这可能意味着以下两种情况之一:
-
这些差异(通常很小)是因为目标内核在目标硬件上的表现与 fp32/cpu 不同而产生的,比如使用整数数据类型进行累加操作。如果内核不能保证与参考实现完全一致,则这种差异是正常现象。
-
目标硬件的内核存在精度问题。在这种情况下,请联系内核开发人员。