如何将Pytorch模型进行量化处理?
摘要:在深度学习中,量化指的是使用更少的bit来存储原本以浮点数存储的tensor,以及使用更少的bit来完成原本以浮点数完成的计算。这么做的好处主要有如下几点: 更少的模型体积,接近4倍的减少; 可以更快的计算,由于更少的内存访问和更快的int
在深度学习中,量化指的是使用更少的bit来存储原本以浮点数存储的tensor,以及使用更少的bit来完成原本以浮点数完成的计算。这么做的好处主要有如下几点:
更少的模型体积,接近4倍的减少;
可以更快的计算,由于更少的内存访问和更快的int8计算,可以快2~4倍。
一个量化后的模型,其部分或者全部的tensor操作会使用int类型来计算,而不是使用量化之前的float类型。当然,量化还需要底层硬件支持,x86 CPU(支持AVX2)、ARM CPU、Google TPU、Nvidia Volta/Turing/Ampere、Qualcomm DSP这些主流硬件都对量化提供了支持。
PyTorch对量化的支持目前有如下三种方式:
Post Training Dynamic Quantization:模型训练完毕后的动态量化
Post Training Static Quantization:模型训练完毕后的静态量化
QAT (Quantization Aware Training):模型训练中开启量化
在开始这三部分之前,先介绍下最基础的Tensor的量化
量化基础
量化函数
量化:$$公式1:xq=round(\frac{x}{scale}+zero\_point)$$
反量化:$$公式2:x = (xq-zero\_point)*scale$$
式中,scale是缩放因子,zero_point是零基准,也就是fp32中的零在量化tensor中的值
scale是输入范围与输出范围的比例:$scale=\frac{_max - _min}{q\_max - q\_min}$
其中[min, max]是输入的裁剪范围,即允许输入的边界。[q_min, q_max]是量化输出空间中的范围。对于int8量化,输出范围$q\_max -q\_min \le (2^8-1)$
zero_point充当偏差 以确保输入中的0完美映射到量化空间中的0:$zero\_point=q\_min-\frac{min}{scale}$
校准
选择输入限幅范围的过程称为校准。最简单的技术(也是 PyTorch 中的默认技术)是记录运行过程中的最小值和最大值。TensorRT还使用熵最小化(KL 散度)、均方误差最小化或输入范围的百分位数。
在 PyTorch 中,Observer模块收集输入值的统计信息并计算scale和zero_point。不同的校准方案会产生不同的量化输出,最好凭经验验证哪种方案最适合您的应用程序和架构(稍后会详细介绍)。
