论文笔记:Quantizing deep convolutional networks for efficient inference: A whitepaper
地址:https://arxiv.org/abs/1806.08342
这篇白皮书统一介绍了当前将网络进行定点化的方法。下面将看到的重点记录下来。
为了降低深度神经网络的计算量以及带宽(内存占用量),一种简单可行的方式就是将浮点网络(网络权重都是float类型数值)转换成定点网络(网络权重都是或者部分是int8类型)具体来说,这么做的优势在于:
- 不用改变网络结构,不用重新训练
- 单个int8定点数的内存占用就已经是float32这种浮点数的1/4。显然这样的定点化转换能够降低模型的占用
- 降低运行时所需的带宽(内存占用量),降低功耗(因为很多时候功耗很大部分取决于内存的访问)
- 便于部署:目前许多平台都能为定点数的计算提供加速支持
量化器(Quantizer)的设计
这里说的量化器实际上做的就是指浮点数(取值范围)与定点数(取值范围,只能取整数)之间的映射。
Affine(Asymmetric quantizer)
这里我们只考虑线性映射:也就是包含2个参数,尺度(scale)和零点。其中
- 是一个整数,并且需要保证零点的量化是没有损失的(我理解是一个数 + 零点还是得等于它本身,有点抽象代数的意思)
- 因此需要做一个松弛,使得它能够包含数值0,如 需要松弛至
- 量化的过程如下表示:
- 指对数值进行截断至之间。
- 将量化数值转换回浮点的方式:
- 做卷积的时候则需要先将量化后的数减去相应的z(将数值中心化),然后再进行乘加操作
Symmetric quantizer
一种简化的方式是将零点和浮点数的0绑定,浮点的0对应定点数,意味着,将映射到[-128, 127],这样做的话公式会变得更加简单:
随机量化器
略,实际上就是在Asymmetric的基础上,对浮点数加上随机的扰动(个人认为加上随机数也起不了太大的作用,后面作者的实验也证实了这点)
量化训练的特殊化处理
如果按照上述的方式对卷积输出进行量化,有一个问题是:量化函数不连续,并且很多地方的导数为0。因此,如果要在训练时使用量化,则输出值只做截断,不会进行和相关的两种变换,而反向传播用的是输出值。
量化参数的计算
- TensorRT用的是最小化原始值和量化后的数值的KL散度从而得到和
- 本文提出了一种更简单的方法:
- 对于权重Weight,直接用实际的max & min去求(相当于将原始数值做一个缩放)
- 对于Actvation函数,则直接用几个batch之间的max & min的滑动平均数(也就是会用一个小的batch做标定)
量化粒度
- 对于一个NCHW的4维tensor,我们可以用一个来进行量化(Per-layer)
- 也可以用N个来进行量化(Per-layer)。显然这种方式增加了参数量,但提升了自由度,从而提升精度
量化预测实验
量化预测,指的是用浮点训,训完之后直接转换成定点。这里作者给出了几个实验结论:
- Per-channel 量化可以提供一个baseline,并且asymmetric的量化性能已经接近浮点
- 大模型(Resnet, Inception-v3)对于量化模型会更加鲁棒
- 如果用per-layer的量化会导致性能的大幅度下降(尤其是mobilenet)
- 大多数的性能下降都来自于weight而不是activation
定点模型的训练
这里指的是在训练的时候就已经是定点模型。列出值得注意的几点:
- 在做BP的时候,其实是维护2套参数:进行反向传播的时候,用的是浮点的权重,更新的也是浮点的权重。原因是因为当训练的后期,梯度会很小,如果这个时候还用定点数表示梯度或权重的话,会导致数值underflow,也就是由于精度问题被四舍五入至0
- 然后更新权重完之后再通过进行截断&缩放
这里总结了与定点模型训练的相关步骤:
- 一种推荐的方式是先得到一个浮点模型,然后在浮点模型的基础上finetune
- 修改量化相关的OP,将原有的浮点OP换成fake quantization的:输出是定点(截断),但反向传播时候用浮点
- 定点模型的训练,同时保存相关的scale & zero-point信息
- 训练结束之后做定点的转换(去掉之前的fake quantization)
- 模型的部署
Fake Quantitization Op
下图为卷积层的浮点OP以及定点OP的差异。对于浮点OP来说,就是简单地conv + bias,无需多解释。但是对于定点的OP,这里做需要先将weight做量化,然后做定点的相乘,然后再对结果进行量化。
BN的转换
**实际上,在定点模型预测的时候,是不包含BN的。**BN层是通过某种融合,与上一层卷积层的输出结果绑定在一起。具体我们从BN的定义入手。训练时:
预测时:
其中分别是的滑动平均值,分别是每个batch在该层输出的均值&方差。BN的作用在于对一层的输出做归一化,从而降低层与层之间的数值依赖,提升精度。
在定点模型中,这样的BN操作,被融合到了的weight中:
一些实验结论:
- 对于定点化训练,symmetric & asymmetric的量化是没有差别的
- 前面提到了如果用per-layer的量化会导致性能的大幅度下降。但是定点化训练能够使得更简单的量化方式(比如per-layer + symmetric)也能够得到近似于浮点模型的结果。
训练的最佳实践方式:
- 不要用随机的量化(stochastic quantization),会使得模型指标下降
- 先训一个浮点的模型,在此基础上进行定点化训练会得到更好的效果
- 将bn结构按预测进行匹配会降低数据抖动,提高模型精度
- 谨慎使用指数滑动平均