原文链接:https://www.yuque.com/yahei/hey-yahei/quantization.mxnet2
简单来说,量化就是将浮点存储(运算)转换为整型存储(运算)的一种模型压缩技术。如果按《当前深度神经网络模型压缩和加速都有哪些方法?-机器之心》一文的分类方式,量化属于参数共享的一种——将原始数据聚为若干类(比如int8量化为 2 8 = 256 2^8=256 28=256类),量化后的整型值就相当于类的索引号。
按照聚类中心是否均匀分布,可以把量化分为线性量化和非线性量化。
- 如《Deep Compression: Compressing Deep Neural Networks with Pruning, Trained Quantization and Huffman Coding(2016)》就是典型的非线性量化,作者采用不规则的聚类中心,通过KMEANS对浮点权重进行量化,并在训练过程中逐步修正聚类中心——不规则的聚类中心往往能在相同的比特数下取得更小的量化误差,但由于必须先查表取得原始数据再进行计算,所以对计算的加速没有任何帮助,这种方法更多是用来压缩模型文件大小。
- 与非线性量化不同,线性量化采用均匀分布的聚类中心,原始数据跟量化后的数据存在一个简单的线性变换关系。而卷积、全连接本身也只是简单的线性计算,因此在线性量化中可以直接用量化后的数据进行直接计算,不仅可以压缩模型文件的大小,还能带来明显的速度提升。
动机
- 更少的存储开销和带宽需求
使用更少的比特数存储数据,有效减少应用对存储资源的依赖(但现代系统往往拥有相对丰富的存储资源,这一点已经不算是采用量化的主要动机) - 更快的计算速度
对多数处理器而言,整型运算的速度一般(但不总是)比浮点运算更快 - 更低的能耗与占用面积
数据来源:《High-Performance Hardware for Machine Learning(NIPS2015)》
从上图可以看到,FP32乘法的能耗是INT8乘法能耗的18.5倍,芯片占用面积则是27.3倍——对芯片设计和FPGA设计而言,更少的资源占用意味着相同数量的单元下可以设计出更多的计算单元;而更少的能耗意味着更少的发热,和更长久的续航。 - 尚可接受的精度损失
量化相当于对模型权重引入噪声,所幸CNN本身对噪声不敏感(甚至在训练过程中,模拟量化所引入的权重加噪还有利于防止过拟合),在合适的比特数下量化后的模型并不会带来很严重的精度损失。按照gluoncv提供的报告,经过int8量化之后,ResNet50_v1和MobileNet1.0_v1在ILSVRC2012数据集上的准确率仅分别从77.36%、73.28%下降为76.86%、72.85%。 - 趋势
无论是移动端还是服务器端,都可以看到新的计算设备正不断迎合量化技术。比如NPU/APU/AIPU等基本都是支持int8(甚至更低精度的int4)计算的,并且有相当可观的TOPs,而Mali GPU开始引入int8 dot支持,Nvidia也不例外——
线性量化
常见的线性量化过程可以用以下数学表达式来表示:
r = R o u n d ( S ( q − Z ) ) r = Round(S(q - Z)) r=Round(S(q−Z))
其中,
q q q 是float32的原始值;
Z Z Z 是float32的偏移量,也可以量化为int32;
S S S 是float32的缩放因子;
R o u n d ( ⋅ ) Round(\cdot) Round(⋅) 是四舍五入近似取整的数学函数,除了四舍五入,向上、向下取整也是可以的;
r r r 是量化后的一个整数值。
而我们需要做的,就是确定合适的 S S S 和 Z Z Z
对称和非对称
参考:Algorithms - Quantization | Distiller
根据参数 Z Z Z 是否为零可以将线性量化分为两类——对称和非对称。
- <