量化(Quantization)模型的论文来自于 Google 发表的文章 On the efficient representation and execution of deep acoustic models。
量化方法的目的就是使用 8 位或 16 位的整型数来替代浮点数,这种方法试图利用定点点积来替代浮点点积,这很大程度上降低了神经网络在无硬浮点设备上的运算开销。同时,该方法在一些支持单指令流多数据流 SIMD 的硬件设备上优势就更加明显了,比如128-bit 寄存器 SSE 可以单个指令同时运算 4 个 32 位单精度浮点,8 个 16 位整型,16 个 8 位整型。显然 8 位整型数在 SIMD 的加持下,相比于单精度浮点运算速率要更快一些。另外,该方法还可以减少模型的内存和存储占用空间。
量化方法是一种类似于离差标准化的归一化方法,是对原始数据进行线性变换,使结果映射到一定范围内,具体公式如下:
Python实现如下:
# 根据参数和原始浮点数量化为定点数
def Quant(Vx, Q, RQM):
return round(Q * Vx) - RQM
# 根据量化参数还原回浮点
def QuantRevert(VxQuant, Q, RQM):
return (VxQuant + RQM) / Q
针对数组的量化和还原如下:
import numpy as np
def ListQuant(data_list, quant_bits):
# 数组范围估计
data_min = min(data_list)
data_max = max(data_list)
# 量化参数估计
Q = ((1 << quant_bits) - 1) * 1.0 / (data_max - data_min)
RQM = (int)(round(Q*data_min))
# 产生量化后的数组
quant_data_list = []
for x in data_list:
quant_data = Quant(x, Q, RQM)
quant_data_list.append(quant_data)
quant_data_list = np.array(quant_data_list)
return (Q, RQM, quant_data_list)
def ListQuantRevert(quant_data_list, Q, RQM):
quant_revert_data_list = []
for quant_data in quant_data_list:
# 量化数据还原为原始浮点数据
revert_quant_data = QuantRevert(quant_data, Q, RQM)
quant_revert_data_list.append(revert_quant_data)
quant_revert_data_list = np.array(quant_revert_data_list)
return quant_revert_data_list
下面两幅图,将原本在浮点分布的正弦曲线,经过量化和还原得到了另外两条曲线。类似图像上的降采样结果,4 位量化方式还原后的曲线出现了明显的锯齿形状,如下图:
然而,8 位量化方式在还原后,其连接曲线与原始曲线几乎重合,如下图:
关于定点/浮点的点积优化方法,可以看看下面几个开源项目:
- Google 开源的代码 gemmlowp: a small self-contained low-precision GEMM library ,结合 Tensorflow 的量化模型训练应该能发挥很好的『药效』。Google 很慷慨地公布了几种 GEMM 优化方法,比如基于 NEON / SSE 的 SIMD 指令、并行化运算、Cache 预热等优化方法。该 C++ 代码移植到目前市面上绝大部分的手持设备上应该不成问题。
- ARM 公司开源项目,针对自家嵌入式设计的词唤醒引擎架构 ML-KWS-for-MCU ,里面针对 DS-CNN / DNN 模型做了大量的定点计算优化工作,另外该项目还开放了基于 Tensorflow 的 8 位量化模型训练工具,移植到嵌入式设备上的底层优化算法库是来自自家的 CMSIS_5 。
- 如果 GEMM 优化还没入门,还可以从 OpenBlas 贡献者在 Github 发布的指导文档 How To Optimize Gemm 开始入手。
在展示优化结果前,需要引入语音识别中一项重要的参考指标——实时比(RTF)。假设一个 t 时长的音频,引擎处理完这段音频所花费的时间为 p,那么我们认为该引擎的实时比为 p / t。如果在某一平台上统计出来的实时比大于 1,则表面该引擎在该平台下的实时性无法保证。在一些对实时性要求比较高的系统中将无法使用。另外,在一些不支持幷行化处理的设备上,则会因为来不及消化录音缓存,而出现录音丢帧的状况从而导致设备工作异常。因而在保证一定效果的情况,应该让识别引擎的实时比应尽可能的低。
转载自: https://zhuanlan.zhihu.com/p/38328685