闲话模型压缩之量化(Quantization)篇

1. 前言

这些年来,深度学习在众多领域亮眼的表现使其成为了如今机器学习的主流方向,但其巨大的计算量仍为人诟病。尤其是近几年,随着端设备算力增强,业界涌现出越来越多基于深度神经网络的智能应用。为了弥补算力需求与供给的鸿沟,近几年来模型压缩成为了业界的热点之一。模型压缩又可细分为多个子方向。之前在《浅谈端上智能之计算优化》中有过一些简单的论述,同时在《闲话模型压缩之网络剪枝(Network Pruning)篇》中更加具体地整理了些关于网络剪枝(network pruning)的东西,本文就再将目光放到另一类方法上-量化(Quantization)。模型量化可以带来多方面的好处:

  • 计算效率提升:很多处理器整数计算指令都要比相应的浮点计算高效。以CPU为例,浮点运算指令的latency平均会长于对应的整数运算指令,早期的CPU尤其如此。对于FPGA来说,浮点运算就更麻烦了。而且乘法的复杂度通常与操作数bit-width的平方成正比,因此将表示精度降低可以有效降低复杂度。
  • 内存和存储占用减少:量化对模型的『瘦身』效果可谓立杆见影,它所带来的好处是两方面的:其一,减少memory footprint。我们知道很多时候推理性能的瓶颈不在于计算而在于访存,在这种情况下提高计算密度会对耗时有显著的优化效果;其二,节省存储空间,减少应用的size,同时便于软件的升级更新。
  • 减少能耗:我们知道功耗主要来自计算和访存两部分。一方面 ,以乘加运算为例,8位整型与32浮点相比能耗可有数量级的差异。另一方面,访存是耗电大户。假设原本只能放在DRAM中的模型经过量化能放入SRAM,那不仅提升性能,而且减少了能耗,简直完美。

正如其它模型压缩方法一样,对模型的量化基于一个共识。那就是复杂的、高精度表示的模型在训练时是必要的,因为我们需要在优化时捕捉微小的梯度变化,然而在推理时并没有必要。也就是说,网络中存在很多不重要的参数,或者并不需要太细的精度来表示它们。另外,实验证明神经网络对噪声鲁棒,而量化其实也可看作是噪声。这就意味着我们在部署模型前可以将之化简,而表示精度降低就是化简的重要手段之一。我们知道,大多深度学习训练框架默认下模型的参数是32位浮点的,计算也是32位浮点的。模型量化的基本思想就是用更低精度(如8位整型)来代替原浮点精度。听起来似乎非常的简单,但是细看之下会发现这个坑比想象中大得多。从相关的文献可以看到各大巨头公司都或多或少地参于其中,似乎成为了兵家必争之地。量化最核心的挑战是如何在减少表示精度的同时不让模型的准确度掉下来,即在压缩率与准确率损失间作trade-off。这就衍生出很多有趣的子问题,比如量化对象是什么(weight,activation,gradient),量化到几位(8位,4位,2位,1位),量化参数(如step size,clipping value)如何选择,量化参数是否可以自动优化,不同层是否需要不同的量化参数,如何在量化后恢复准确率或者在训练时考虑量化,等等。。。

2. 原理与分类

这里先非常简单列一下基本原理。 由于相关的介绍与文献非常多,这里不细展开,主要为了统一下术语。对于典型的浮点到整型的量化,其本质上是将实数域中的某一段映射到整数。如果使用的是线性量化,其一般形式可表示为:
q = r o u n d ( s ∗ x + z ) q = round(s * x + z) q=round(sx+z)
其中的 x x x q q q分别为量化前和后的数, s s s称为scaling factor, z z z称为zero point。这个zero point即是原值域中的0在量化后的值。在weight或activation中会有不少0(比如padding,或者经过ReLU),因此我们在量化时需要让实数0在量化后可以被精确地表示。

为使量化后在指定位数整数表示范围内(如 n n n位),这里scaling factor可以取:
2 n − 1 max ⁡ x − min ⁡ x \frac {2^n - 1}{\max_x - \min_x} maxxminx2n1
其中 min ⁡ x \min_x minx max ⁡ x \max_x maxx分别为量化对象(如weight或activation)的dynamic range下界与上界。那么问题来了,如果这个dynamic range很广,或者有些很离奇的outlier,那这样做就会便得比特位被浪费在那些并不密集的区域,导致信息的丢失。因此,还有种做法就是对dynamic range先做clip,把那些含信息少的区域切掉。即:
q = r o u n d ( s ∗ c l i p ( x , α , β ) + z ) q = round(s * clip(x, \alpha, \beta) + z) q=round(sclip(x,α,β)+z)
其中 α \alpha α β \beta β分别为clip的上下界,作为量化参数clipping value。这个取值也是门艺术,大了浪费比特位,小了把就把太多有用信息“切”掉了,如何选取后面会再讨论。

以上方法中由于对原值域和量化后值域都不要求关于0对称,故称为非对称(Asymmetric)量化。如果将上面的zero point设为0,则称为对称(Asymmetric)量化。可以说对称量化是非对称量化的特例。另外因计算机内部用补码表示,其表示范围不是关于0对称的。因此对于对称量化,会将整型值域最小值去掉,如8位有符号整型表示范围[-128, 127],截取后变成[-127, 127]。这样整型值域才是直正的对称,否则会产生偏差。相比而言,非对称量化优点是能够更充分利用比特位,因为对于对称量化而言,碰到dynamic range关于0两边严重不对称的话(比如经过ReLU后的activation),会比较低效。但这也是有代价的,即计算更加复杂。以乘法为例,对于对称量化来说,量化后乘法只是原值乘法再乘以一个缩放因子: s x x ∗ s y y = s x s y x y s_x x * s_y y = s_x s_y xy sxxsyy=sxsyxy;而对于非对称量化来说,就要复杂一些了: ( s x x + z x ) ∗ ( s y y + z y ) = s x s y x y + s x x z y + s y y z x + z x z y (s_x x + z_x) * (s_y y + z_y) = s_x s_y xy + s_x x z_y + s_y y z_x + z_x z_y (sxx+zx)(syy+zy)=sxsyxy+sxxzy+syyzx+zxzy。总得来说,对称与非对称量化各有利弊,得看用在什么地方。如实际中weight的分布通常是关于0对称的高斯分布,那比较适用用对称量化。而ReLU后的activation是没有负数的,因此适用于非对称量化。另外,如果非对称量化中整个值域都落在正区间,那就可以用无符号整型表示,否则用有符号整型。

量化方法还分为均匀(Uniform)量化与非均匀(Non-uniform)量化。最简单就是让量化的等级间距离相等,这类量化称为均匀量化。但直觉上这样会有更多的信息丢失,因为一般来说dynamic range中肯定有些区域点密集,有些稀疏。相应地,有均匀量化就有非均匀量化,它是指量化等级间不等长,如log quantization。再高级一点,那就是通过学习来得到更大自由度的映射(可通过查找表表示)。直觉上,非均匀量化似乎能达到更高的准确率,但它的缺点是不利于硬件加速。

对于量化对象,主要有以下三个。当然,实际中可能是量化其中的多个甚至全部。

  • weight(权重):weight的量化是最常规也是最常见的。量化weight可达到减少模型大小和memory footprint等目的。
  • activation(激活函数输出):实际中activation往往是占内存使用的大头,因此量化activation不仅可以大大减少memory footprint。更重要的是,结合weight的量化可以充分利用整数计算获得性能提升。
  • gradient(梯度):相对上面两者略微小众一些,因为主要用于训练。它主要作用是在分布式计算中减少通信开销,单机训练时也可减少backward时的开销。

对于量化位数,可以有很多种选择。大体可分为几类:

  • float16量化是比较保险的做法,大多数情况下可以不丢失太多精度的情况下有明显的性能提升。因为都是浮点,相对来说容易,就不细展开了。
  • 8位是比较常见的,也是相对成熟的。相关的研究很多,各种主流框架也基本都支持。
  • 8位以下目前而言学界相对玩得多些,工业界有少量支持,但还没有太成熟。8位以下主要是4,2和1位(因为位数为2的幂次性能会更好,也更容易实现)。如果精度低至1位,也就是二值化,那可以用位运算进行计算。这对处理器而言是很友好的。

按量化过程中是否需要进行训练可分为两类:

  • PTQ(Post-training quantization):顾名思义,就是在模型训练后做的量化。又可细分为两种:
    • 需要calibration数据,这些数据主要用来统计得到量化参数,因此是不需要打标的,一般百来张即可。
    • 完全不需要数据集。这适用于那些完全拿不到训练环境和数据的场景。
  • QAT(Quantization aware training):又可分是要从头训练还是fine-tuning。基本上到4位及以下量化由于信息丢失较多,因此很多方法中(也不绝对)需要训练介入。

一般来说,QAT可以得到更高的准确率,但同时也会有更强的假设,就是有训练数据,训练环境和所需的成本。在一些场景下这个假设很难满足。比如云服务上,对于给定的模型,不可能还要求提供数据和训练环境。

以量化参数的共用范围或者说粒度来分,可分为:

扫描二维码关注公众号,回复: 11674194 查看本文章
  • Per-axis/per-channel:对tensor的单个轴有单独的量化参数,如per-channel就是weight的每个channel使用单独的量化参数。
  • Per-tensor/per-layer:每个tensor有单独的量化参数。对于卷积或全连接层这些的话这也就意味着每层独立的量化参数。
  • Global:即整个网络使用相同的量化参数。一般来说,对于8位量化,全局量化参数影响不明显,但到更低精度,就会对准确率有较大影响。

3. 业界方法

其实很早就有对神经网络量化的研究,如1990年Fiesler等人的《Weight Discretization Paradigm for Optical Neural Networks》。而今天,深度学习的兴起和对准确率的追求使得神经网络越来越重,因此这方面的需求也重新成为了热点。

3.1 基于压缩的方法

量化最简单粗暴的做法的是rounding。2015年IBM的论文《Deep Learning with Limited Numerical Precision》中描述了两种将浮点转为定点的rounding方法:一种是Round-to-nearest,即就近取整;另一种是Stochastic rounding,即以一定概率(与向下取整点的距离成正比)确定向上还是向下取整。与前者相比,它是一种无偏的估计。

另外一个直观的思路就是将之看作一个数据压缩问题。2016年Stanford、清华和NVIDIA的经典论文《Deep Compression: Compressing Deep Neural Networks with Pruning, Trained Quantization and Huffman Coding》中的量化部分就是采用了先将weight进行聚类,生成codebook,再通过weight sharing达到对weight压缩的目的。数据压缩中VQ(Vector quantization)是一类常见的方法,它在最近邻搜索问题中应用得比较多,其基本思想是将D维空间的数映射到codebook(包含codeword的集合)中的codeword。这种映射就称为quantizer。像K-means,product quantization都属于此类方法。K-means任何一本机器学习教材都会详细说,不多说。PQ(Product quantization)主要针对空间非常大以至codeword指数增加的情况,它将原向量空间分为M个低维子空间(将D维空间向量看作M个D/M维子向量的联接),并且将每个子空间进行量化,最后将这些codeword进行联接。感觉VQ/PQ的路子Facebook是比较喜欢的,似乎在这个方向上一直有研究。从2014年的论文《Compressing Deep Convolutional Networks using Vector Quantization》将之引入神经网络的weight量化到2019年的《And the Bit Goes Down: Revisiting the Quantization of Neural Networks》通过最小化activation的reconstruction error提升PQ效果,再到2020发表的论文《Training with Quantization Noise for Extreme Model Compression》提出在每次迭代中只随机选取一部分weight做量化,从而减少STE带来的梯度估计偏差影响。另外,2015年华盛顿大学与NVIDIA的论文《Compressing Neural Networks with the Hashing Trick》中提出HashedNets用于神经网络中weight间的随机共享。为了降低内存使用,它使用hash来建立共享的映射关系。

3.2 如何确定量化参数

前面的讨论还遗留下来一个灵魂拷问,即量化会带来精度损失,那怎么选取量化时所用参数(如scaling factor,zero point,clipping value)可以尽可能地减少对准确率的影响呢。量化误差来自两方面,一个是clip操作带来的,一个是round操作带来的。而这两者间是有trade-off关系的。总得来说,选取合适的量化参数是非常考究的问题,事实上大多数业界的研究正是为了解决这个问题。业界主要有如下几类方法,其实和之前network pruning中介绍的几类方法的精神是类似的。

3.2.1 基于统计近似的方法

对于均匀量化中的量化参数clipping value,除了手工设定之外,一个简单的做法就是统计下要量化的对象,取最大值和最小值。但这样的问题在于如果有outlier,就会使得clipping value的绝对值很大,从而影响要量化区间的精度。2016年Stanford的论文《Convolutional Neural Networks using Logarithmic Data Representation》提出了一种非均匀量化方法,即将weight和activation在log域中进行表示,并给出了在该表示下将向量乘加用位运算实现的方法。它的clipping value是一个超参,通过少量数据tune出来的。文中指出相比线性均匀量化,这种方法对量化更加鲁棒。2018年Intel的论文《Highly Efficient 8-bit Low Precision Inference of Convolutional Neural Networks with IntelCaffe》主要讨论了Intel优化版Caffe中对于8位精度推理的支持。它基于经典的线性量化建模,其中的scaling factor参数通过基于calibration数据集来统计量化对象的最大值来得到。2019年上海科技大学与商汤的论文《Fully Quantized Network for Object Detection》提出基于percentile的activation clamping方法。它从训练集中采样一部分作为calibration set,然后在这个集合上进行模型推理并记录它的activation。假设activation为高斯分布,通过统计得到均值和方差,然后基于 γ \gamma γ-th和 ( 1 − γ ) (1-\gamma) (1γ)-th percentiles来进行weight clipping。2020年得克萨斯大学和Google Brain的论文《Post-training Quantization with Multiple Points: Mixed Precision without Mixed Precision》提出multi-point quantization,使用低位数据的多个向量的线性组合来近似,而传统方法中使用单个低精度数的方式。该方法通过贪心选择来构建multi-point quantization,然后基于与输出的误差自适应地决定低精度点的数量。

3.2.2 基于优化的方法

定义误差的测度为优化目标,然后利用优化方法来求解。这样问题就归结为如何定义误差。一种常见的是量化误差(Quantization error),设量化函数为 Q ( w ) Q(w) Q(w),那目标就是对于输入数据分布,使量化误差最小化,可形式化为:
Q ∗ ( x ) = arg ⁡ min ⁡ Q ∫ p ( x ) ( Q ( x ) − x ) 2 d x Q^*(x) = \mathop{\arg\min}_{Q} \int p(x) (Q(x) - x)^2 dx Q(x)=argminQp(x)(Q(x)x)2dx
不少的方法都是基于该目标或类似目标。

2017年大疆的论文《Towards Accurate Binary Convolutional Neural Network》提出ABC-Net(Accurate-Binary-Convolutional)以量化误差为优化目标。它比较特色的是将weight和activation表示成一系列二进制基的线性组合。如weight可表示为 W ≈ ∑ i = 1 M α i B i W \approx \sum_{i=1}^{M} \alpha_i B_i Wi=1MαiBi,其中 B i B_i Bi W W W同维度但元素为-1或+1。这样,优化问题就是一个线性回归问题。这种方式与类似的多bit-width量化方案相比,在计算上有优势。如在计算时能将输出限制在{-1, +1},从而节省硬件资源。2017年阿里巴巴的论文《Extremely Low Bit Neural Network: Squeeze the Last Bit Out with ADMM》解耦了连续空间中的参数学习和量化所要求的离散化约束,将量化模型的训练建模为MIP(Mixed integer programming)问题。通过引入辅助变量,使问题变成可用ADMM(Alternating Direction Method of Multipliers)来解的形式。ADMM的每步迭代分为三步:连续空间下的proximal step,离散空间下的projection step和dual update。这样就将原NP-hard问题分解为多个更易解的子问题。2018年微软在论文《LQ-Nets: Learned Quantization for Highly Accurate and Compact Deep Neural Networks》中提出非均匀量化方法LQ-Nets,在训练中同时学习weight和quantizer。它可对weight和activation进行任意位精度的量化。为了使量化对位运算兼容,它将quantizer建模成一系列浮点数组成的basis vector(替换传统的 [ 1 , 2 , . . . , 2 K − 1 ] [1, 2, ..., 2^{K-1}] [1,2,...,2K1])的线性组合。训练过程中weight还是与传统方法一样训练,而量化参数是在forward中通过QEM(Quantization Error Minimization)算法优化求解的。QEM目标是最小化量化误差,它通过交替最小化编码系数与basis vector来进行迭代优化 。2018年Intel与以色列理工学院的论文《Post Training 4-bit Quantization of Convolutional Networks for Rapid-deployment》提出ACIQ方法,它适用于weight和activation,且不需要训练。以最小化tensor级别的量化误差为优化目标,并给出最优clipping value和bit-width的解析解。类似地,2019年华为的论文《Low-bit Quantization of Neural Networks for Efficient Inference》也基于MSE来找最优的clipping value。2019年华为的另一论文《Low-bit Quantization of Neural Networks for Efficient Inference》将线性量化任务形式化为Minimum Mean Squared Error(MMSE)问题,然后用迭代方式求解。它针对weight与activation,可以量化到4位,且不需要网络的fine-tuning。只是在一些步骤中(如activation量化,scaling factor refinement)需要calibration data。2020年Samsung的论文《Post-Training Piecewise Linear Quantization for Deep Neural Networks》提出了一种post-training量化方法Piecewise linear quantization(PWLQ)。它主要针对具有长尾的bell-shaped分布。该方法将量化范围切分成不相交的区域,每个区域赋于相同的量化水平。最优的切分点是通过最小化量化误差来得到的。

之前很多基于优化方法的工作将最小化量化误差作为目标。但最小化量化误差是否就意味着loss最小呢?只能说前者是后者的一个思路,但并不等同。显然,后者才是我们更关注的东西。因此,也有些基于优化的工作开始将loss纳入考虑 。2016年香港科技大学的论文《Loss-aware Binarization of Deep Networks》直接关于二值化的weight最小化loss,然后用proximal Newton算法,其中的Hessian矩阵通过Adam optimizer中的second moments进行近似。2018年香港科技大学的论文《Loss-aware Weight Quantization of Deep Networks》用类似的思路拓展到三值化网络。2019年Intel和以色列理工学院的论文《Loss Aware Post-training Quantization》从量化参数对于loss的表面形态影响出发,指出对于小bit-width量化,loss函数表面会变得非常凹凸陡峭(以Gaussian curvature为测度),层间的step size相互依赖也更明显,从而让最优量化参数的选择变得十分困难。另外,有时传统基于 L 2 L_2 L2范数的MSE未必达到最好的准确率。基于这些考虑,文中提出一个三阶段方法-LAPQ(Loss aware post-training quantization),它优化的目标为相对于step size的网络损失函数。首先,考虑单层找到多种 L p L_p Lp范数下最小化量化误差的step size。然后,基于前一步的结果采样,再通过插值得到二次函数近似并找到最优解。最后,以前一步得到的最优解为初始值,通过gradient-free优化方法(Powell’s method)进一步得到最终最优解。

3.2.3 基于可微分的方法

主要思想是使优化目标相对于量化参数可微,这样就可以通过SGD在训练网络时顺便也把量化参数给学习了。而且这个训练以准确率为目标,不会像上面优化方法中一样,优化目标与最终目标还存在偏差。2018年三星和KAIST的论文《Joint Training of Low-precision Neural Network with Quantization interval Parameters》提出QIL(Quantization interval learning)方法。它将weight与activation的量化区间作为可学习参数,对于每一层通过两参数指定区间的中心与到中心的距离。在训练模型同时也学习量化参数。2018年IBM的论文《PACT: Parameterized Clipping Activation for Quantized Neural Networks》提出PACT(PArameterized Clipping acTivation)方法。它将ReLU替换成带clipping参数的激活函数,并且在训练中优化它来找到scaling factor。PACT允许activation量化到任意bit-width。论文表明在大量的模型和数据集上,将weight和activation同时量化到4位可以维持和原始精度模型类似的准确率。2018年IBM又在论文《Bridging the Accuracy Gap for 2-bit Quantized Neural Networks》中将适用于activation的PACT方法与用于weight的SAWB(Statistical-aware weight binning)方法结合,用于2位的量化。SAWB基于训练时采集的统计信息以最小化MSE为目标找到最优的scaling factor。2019年Sony在论文《Differentiable Quantization of Deep Neural Networks》中提出DQ(Differentiable Quantization)方法,通过构造可微的量化器,可以通过梯度下降来学习每个weight和activation的量化参数,如step size, dynamic range,然后可以推导出bit-width。2019年IBM的论文《Learned Step Size Quantization》将基于学习的方法拓展到step size,并提出LSQ(Learned Step Size Quantization)方法,它延续了将step size作为可训练参数(每层有单独的step size),然后在训练过程中进行学习的做法。文中主要提出一种量化函数关于step size参数的梯度计算方法。与之前的QIL与PACT方法相比,这种梯度对于transition point敏感,符合在transition point处step size的变化会引起量化后值大的变化的intuition。另外提出对step size梯度进行缩放以保证其数值大小上与weight的梯度差不多。该方法在将weight和activation都量化到2,3,4位时仍能在ImageNet这样的大型数据集上达到高准确率,尤其是3位的量化网络能达到全精度网络的准确率。2019年中科大、阿里与南加州大学发表的论文《Quantization Networks》提出一种可应用于weight与activation且适用于任意位量化的方法。它将量化函数形式化为可微分的非线性函数。量化函数被表示为一些sigmoid函数的线性组合,这些sigmoid函数具有可学习的参数。这样,便可以以一种end-to-end的方式来学习这些量化参数。2019年北航,商汤和北京理工的论文《Differentiable Soft Quantization: Bridging Full-Precision and Low-Bit Neural Networks》提出DSQ(Differentiable Soft Quantization)方法。它通过分段的tanh函数构建可微的soft quantization function,二值量化是其特殊形式。因为该函数相对于量化参数可微,因此可以在网络的训练中一起学习。

3.2.4 基于贝叶斯的方法

贝叶斯方法以其优雅的理论基础一直是机器学习中非常流行的方法。在模型压缩领域也不例外。2017年阿姆斯特丹大学的论文《Bayesian Compression for Deep Learning》将weight以group为单位,并引入使weight稀疏的先验,再基于变分推理方法估计后验分布,最后基于后验分布的variance确定每层最优的bit-width。同年阿姆斯特丹大学另一篇论文《Soft Weight-Sharing for Neural Network Compression》基于soft weight-sharing的思想,在re-training过程中同时做了quantization和pruning。Soft weight-sharing体现在针对weight使用高斯混合模型(GMM)作为先验,然后将variational lower bound(negative variational free energy)作为目标,通过gradient descent进行优化,同时学习weight与GMM中的参数。在后处理中,将weight设为它所在component的均值,同时通过component间KL divergence为测度,合并小于指定阀值的两个component。2017年俄罗斯斯科尔科沃创新中心等机构的论文《Variational Dropout Sparsifies Deep Neural Networks》将之贝叶斯理论中的变分推理方法用于网络模型的裁剪。它扩展Variational Dropout并提出Sparse VD(Variational Dropout)方法。它将weight表示成参数 θ \theta θ与高斯噪声 N ( 1 , α ) \mathcal{N}(1, \alpha) N(1,α)的乘积,使weight变成以 θ \theta θ α \alpha α为参数的高斯分布并对其施加log-uniform先验(它可以使weight变得稀疏),然后以SGVB(在variational lower bound上使用reparameterization trick得来,具体见《Auto-encoding Variational Bayes》)为优化目标学习参数,最后通过学习到的参数与给定阀值比较决定对特定weight是否要做裁剪。2018年Bosch和亚琛工业大学的论文《Variational Network Quantization》扩展了Sparse VD方法提出VNQ(Variational Network Quantization)将变分推理方法引入量化任务。我们知道贝叶斯方法中先验的设计是很tricky的。本文针对量化引入了multi-modal的先验(称为quantizing prior),该先验分布在codebook中值(如[-r, 0, r])会有"spike"。然后通过最大化ELBO得到最优的变分参数。由于先验的影响,参数的后验会聚集在几个codebook中的值上,接着就可以对每个weight通过argmax得到它该量化为codebook中的那个。2019年北航和百度等机构发表的论文《Bayesian Optimized 1-Bit CNNs》利用贝叶斯学习来提升bit-width为1的CNN的表现,提出了BONNs(Bayesian optimized 1-bit CNNs)方法。它在loss中引入双峰高斯混合模型作为先验分布,使后验分布趋向于双峰。该模型可以通过SGD方法进行end-to-end的训练。

3.3 让模型更容易量化

之前的主要思路是给定一个训练好的网络,如何找到最优的量化参数。对于量化目标对象,其分布影响着量化的效果。即有些分布利于量化,而有些分布不利于量化。因此,一个改进的思路就是如何让量化目标对象的分布变得更适合量化(所谓适合就是量化后不容易掉准确率)。2019年康奈尔大学的论文《Improving Neural Network Quantization without Retraining using Outlier Channel Splitting》针对weight/activation的分布中的outlier,提出outlier channel splitting(OCS)。它基于功能不变的网络变换,使outlier往中间靠。网络经过修改后,按常理是要重新训练的,但文中使用了Net2Net方法来给出新结构中的weight从而节省了训练开销。2019年高通的《Data-Free Quantization Through Weight Equalization and Bias Correction》提出DFQ(Data-free quantization)。作为一种8位量化方法,它不需要fine-tuning和超参选取。该方法利用了激活函数的scale-equivalence性质(即对于一个层,单独的output channel可以被缩放,只要它的下一层被相应地反向缩放),对网络中的weight range进行跨层的均衡。对于引入的bias通过bias correction对其进行吸收。这样处理后更适合量化。DFQ算法主要分四个阶段:cross-layer equalization,bias absorption,Quantization,bias correction。2019年Hailo发表的论文《Same, Same But Different:Recovering Neural Network Quantization Error Through Weight Factorization》也给出了类似的观点,即对于给定层,单独的output channel可以乘以一个缩放因子,只要下一层的相应weight乘以这个缩放因子的相反数。这种改变网络的weight但不改变其功能(即输出)的equivalent weight arrangement,可以用来减少量化带来的degradation。在量化中,每一个层的dynamic range都是被具有最大绝对值的channel(称为dominant channel)确定的,而其它的channel如果能增大到与这个dominant channel差不多的话便可以减少量化带来的噪声,前提是下一层需要做相应的补偿。2020年Intel与以色列理工学院的论文《Robust Quantization:One Model to Rule Them All》引入KURE(KUrtosis REgularization)项加入到模型的损失函数中。通过特定kurtosis值,可以让模型分布适应量化噪声有高的容忍度。文中从理论上证明了相对于正态分布,均匀分布对量化参数的变化更加鲁棒,而通常情况下weight和activation趋向于正正态分布。这样的好处是在布署模型时,如果由于低精度加速硬件的限制需要使用不同的量化参数(如step size),不会引起大的准确率损失。而传统的如QAT方案,需要在训练时确定量化策略,一旦训练好后模型其实就和所选量化策略绑定了。这时一旦加速硬件不支持就很麻烦。

不仅量化目标对象的分布对量化效果有影响,网络结构的调整也可用于提升量化效果。2017年Intel在论文《WRPN: Wide Reduced-Precision Networks》中提出WRPN(Wide reduced-precision networks)。文中指出当batch size增大,activation所占memory会随之增大。当batch size到128时,训练时activation达到98%的memory footprint。文中提出的主要方法是通过增加filter map(即加宽layer)的方式补偿精度损失。文中指出对于许多网络(如AlexNet, ResNet-34和Inception),2位的weight和4位的activation足够保持模型准确率。2019年高通在论文《A Quantization-Friendly Separable Convolution for MobileNets》提出在MobileNet V1中主要引起量化误差的是BN和ReLU6,然后它提出了一种对量化友好的深度可分离卷积。文中指出定点量化过程中会引入5种精度损失:input quant loss, weight quant loss, runtime saturation loss, activation re-quantization loss和可能的clipping loss。它使用SQNR(Signal-to-quantization-noise ratio),即量化的信噪比来衡量误差。注意用于量化weight的最大/最小值是基于所有channel的,但有些channel中会出现都是0(MobileNet V1中常见),从而使quant range变得很大,这称为zero-variance issue。

3.4 量化中的训练

PTQ因为是拿已有的32位精度模型进行量化,对数据集和训练环境没有依赖。实际中对于大型模型通常效果很好,但对于小模型会引起较大的准确率损失。因此,为了降低量化后准确率的损失,不少方法会在训练时引入量化操作。但问题来了,神经网络的训练是基于链式求导法则,但量化操作是个阶跃函数,它的导数要么不存在要不为0。这就给基于链式求导的神经网络训练带来了麻烦。针对该问题,业界有一些方案,比较经典的有:

  • 使用最广泛的可能就是STE(Straight through estimator)了。由2012年Hinton的《Coursera Lectures: Neural Networks for Machine Learning》和Bengio等人2013的论文《Estimating or propagating gradients through stochastic neurons for conditional computation》提出。思路和做法都很简单,它就用把量化操作的导数用1近似,也就是说做backward时有和没有量化操作是一样的。在量化到8位以下时它会带来较大误差影响准确率。STE本质上是量化函数梯度的近似,它会导致forward和backward时激活函数不一致(如sign vs. hard tanh),所以会有gradient mismatch problem。
  • 另一思路是既然量化函数不可微,那就用一个可微的函数近似或逼近它。2016年Google,剑桥大学与斯坦福的论文《Categorical Reparameterization with Gumbel-Softmax》与DeepMind与牛津大学的《The Concrete Distribution: A Continuous Relaxation of Discrete Random Variables》针对网络中需要对categorical distribution采样的情况,提出了一种连续可微的estimator(在两篇文章中分别称为Gumbel-Softmax distribution和Concrete distribution)。2018年阿姆斯特丹大学,QUVA Lab和高通的论文《Relaxed Quantization for Discretized Neural Networks》提出Relaxed Quantization方法。它将前面的思想引入量化,将weight与activation看作是quantization grid上的categorical distribution,结合前述方法,就可以定义一个完全可微的量化过程,从而利用stochastic gradient优化方法。2017年清华大学与伊利诺伊大学芝加哥分校的论文《HashNet: Deep Learning to Hash by Continuation》中提出基于continuation method,从一个光滑的目标函数开始,随着训练的进行让之逐渐变得不光滑,从而逼近原问题。具体来说,对于不光滑的sign函数,用带参数的tanh函数来逼近。
  • 再就是EBP方法。2014年哥伦比亚大学和以色列理工学院的论文《Expectation Backpropagation: Parameter-Free Training of Multilayer Neural Networks with Continuous or Discrete Weights》基于变分贝叶斯方法,将EP(Expectation Propagation)引入带神经网络的训练,提出了EBP(Expectation BackPropagation)算法,可适用于连续或离散的weight。

如何更有效地训练低精度量化网络仍是一个持续讨论的问题。业界还有不少相关的工作,如2017年华盛顿大学的论文《Deep Learning as Mixed Convex-Combinatorial Optimization Problem》中将量化模型的学习建模成mixed convex-combinatorial优化问题。基本思路是先通过组合优化方法找到层的输入输出(称为target)的可行解,然后在给定的这些可行解下再优化weight。2017年阿德莱德大学等机构的论文《Towards Effective Low-bitwidth Convolutional Nerual Networks》考虑了量化网络训练难的问题,提出了三种方法优化训练过程。一是将weight与activation分开量化的两阶段优化策略。二是progressive优化方法,即逐步降低bit-width。三是高精度与低精度模型联合训练。2019年Hailo Technologies的论文《Fighting Quantization Bias With Bias》指出对于一些适合端上的轻量网络(如MobileNet)由于参数冗余度较小,量化会给activation带来比较明显的均值偏移,称为MAS(Mean activation shift)。文中给出的解决方案是通过bias项来作补偿,并基于这个基本思想提出了IBC(Iterative bias correction)与BFT(Bias fine tuning)两种方法。

3.5 超低精度量化

超低精度(Ultra-low precision)量化是这几年一直很火的topic。这里的超低精度量化指的1位或者2位的量化。这类量化会引起非常大的精度损失,所以也需要一些非常手段来维持准确率,值得专门聊一下。在超低精度量化中,最极端的就是将bit-width限制为1位,即二值化网络。除了模型大小的数十倍减少外,更加吸引人的是这样就可以用硬件友好的位运算来代替耗时的乘法。 对于元素为-1和1的两个 N N N维向量 x x x y y y,它们的内积可以表示为 x ⋅ y = N − 2 ⋅ popcount ( xnor ( x , y ) ) x \cdot y = N - 2 \cdot \text{popcount}(\text{xnor}(x, y)) xy=N2popcount(xnor(x,y))

比较早期的工作有2014年的首尔大学的论文《Fixed-point Feedforward Deep Neural Network Design using Weights +1, 0, and -1》,它将weight量化为三值(-1, 0, +1)。为了解决量化模型的训练问题,它采取的方法是同时维护高精度与低精度的权重,权重的累计是在高精度下完成的,然后通过量化得到低精度的weight。2015年蒙特利尔工程学院和蒙特利尔大学的论文《BinaryConnect: Training Deep Neural Networks with Binary weights during Propagations》中提出的BinaryConnect(BC)方法引入了binary weight的概念(即-1和1)。这样MAC中的乘法可以用加和减来替代。在训练过程中,forward中对于weight w w w使用deterministic ( sign ( w ) \text{sign}(w) sign(w))或者stochastic(以hard sigmoid σ ( w ) \sigma(w) σ(w)为概率随机赋于+1或-1)的方式来进行二值化。weight更新时仍以浮点精度进行累积。为了避免二值化带来的零值梯度问题采用了等效STE的方法。实验主要限于一些小型数据集(如MNIST, CIFAR-10, SVHN)。2016年蒙特利尔大学、以色列理工学院等机构的论文《Binarized Neural Networks: Training Neural Networks with Weights and Activations Constrained to +1 or -1》提出了BNN的一种训练方法,除了weight外,它将activation也做了二值化。为了解决sign函数导数几乎处处为零的问题,文中在backward时使用hard tanh来近似量化操作。另外,为了进一步减少训练时BN的开销,文中给出了基于shift操作的SBN(Shift-based batch normalization)。这里实验仍限于小型数据集。2017年UC San Diego、微软和旷视的论文《Deep Learning with Low Precision by Half-wave Gaussian Quantization》重点研究了activation的量化,提出用于forward和backward时ReLU的近似。该方法考虑了activation输出通常符合对称高斯分布以及ReLU只保留正数域的性质。HWGQ(Half-wave Gaussian quantizer)定义为正数域上的step-wise constant函数,其参数可根据统计数据通过Lloyd’s algorithm求得MSE意义下的最优解。而对于backward中的ReLU近似,考虑到outlier的影响,文中提出了Clipped ReLU和Log-tailed ReLU两种近似。2016年Allen Institute for AI与华盛顿大学论文《XNOR-Net: ImageNet Classification Using Binary Convolutional Neural Networks》中提出了两种方法:BWN(Binary Weight Networks)与XNOR-Networks。两者的一个大的差别在于前者只二值化weight而后者对weight和activation都二值化。它们引入了一些改动来减少准确率的损失,如将输出乘以一个scaling factor来恢复其dynamic range,保持第一和最后一层FP32的精度,和使用归一化来减少activation的dynamic range。这篇文章的实验开始涉及ImageNet这样的大型数据集。2016年旷视的论文《DoReFa-Net: Training Low Bitwidth Convolutional Neural Networks with Low Bitwidth Gradients》中提出了DoReFa-Net。它基于STE,并将量化对象扩展到weight、activation和gradient。这样训练和推理中的卷积都可用位运算来加速。特别地,对于gradient的量化,加入了随机噪声。另外它还将量化的bit-width拓展到任意位。2016年中科院与陌上花发表的论文《Ternary Weight Networks》对BWN进行了扩展,提出了TWN方法将weight进行三值化(即-1, 0, 1)。它为每层使用threshold和scaling factor量化weight。与BWN一样,backward中梯度是相对于量化后的weight。2017年清华大学、Stanford和NVIDIA《Trained Ternary Quantization》的论文提出了TTQ。它也是基于三值网络,并在此基础上进行了改进,它允许正负两边有不同的scaling factor,并将之作为可学习参数。2017年阿里巴巴的论文《Extremely Low Bit Neural Network: Squeeze the Last Bit Out with ADMM》也主要用于超低精度量化,前面有提不再赘述。2017年Intel的《Incremental Network Quantization: Towards Lossless CNNs with Low-Precision Weights》提出INQ(Incremental network quantization)方法将weight限制在2的幂,并引入一些方法来降低准确率的损失。它包含三个独立的操作:weight partition,group-wise quantization和re-training。首先将预训练模型占的weight通过某种测度分成两组。第一组通过变长编码方法量化。第二组用于re-training,负责补偿量化带来的准确率损失。这三个操作以一种迭代的方式重复执行,直到所有的weight被量化成低精度。2018年香港科技大学、腾讯和华中科技大学《Bi-Real Net: Enhancing the Performance of 1-bit CNNs with Improved Representational Capability and Advanced Training Algorithm》提出了Bi-Real Net,它将实数的activation与后续block的activation通过identity shortcut连接来强化网络的表达能力。除此之外,它还对于训练提出多项改进,包括sign函数导数的更好近似-piecewise polynomial函数,magnitude-aware gradient(使梯度不仅与符号相关还与当前weight的绝对值相关),以及在预训练时将ReLU替换成clip函数。另外还有前面提到过的2019年北航、百度等机构发表的论文《Bayesian Optimized 1-Bit CNNs》,和2019年中科大、阿里与南加州大学发表的论文《Quantization Networks》。

3.6 混合精度

一个神经网络中不同的层的重要程度或者说冗余度是不一样的。Network pruning中也曾经提到会对不同的层采用不同的裁剪参数。类似地,不同的层对量化的敏感度也是不一样的。因此在量化方法中,最好也可以对不同的层使用不同的bit-width。但是,为每层找寻最优的bit-width是一个组合优化问题,其搜索空间是随着层数的增加指数增加的。暴力搜索的话其复杂度为 O ( M N ) O(M^N) O(MN),因此得想其它法子。

一类比较直觉的路子是heuristic-based的方法。主要思想是定义对量化敏感度的测度,越敏感的层使用最多的位。而这个敏感度测度的定义就非常关键了。2018年中科大的论文《Adaptive layerwise quantization for deep neural network compression》基于weight与activation的entropy来确定每层的bit-width。因为熵可以表示信息量,而熵越大表示信息量越大,直觉上也需要更多位数也表示。2019年Berkeley的论文《HAWQ: Hessian AWare Quantization of Neural Networks with Mixed-Precision》提出了HAWQ方法。它的主要思想是利用了二阶信息(由Hessian矩阵表示)。该方法采用multi-stage quantization,即每一个stage中只量化部分网络,然后进行quantization-aware fine-tuning。具体地,sensitivity由Hessian的特征值来衡量。根据MDL(Minimum Description Length)理论,要描述平坦的区域需要较少的位,要描述曲率很大的表面则需要较多的位。而block(一层或多层)的Hessian eigenvalue越大则表示曲率越大,也就是意味着需要更大的bit-width。在multi-stage fine-tuning过程中,需要确定block顺序。这里也同样用到了Hessian eigenvalue,即先fine-tune那些曲率大的,因它们量化后带来的扰动更大。同年论文《HAWQ-V2: Hessian Aware trace-Weighted Quantization of Neural Networks》针对HAWQ缺点做了改进:一是由原先敏感度的测度从Hessian的最大特征值改为Hessian的特征值均值;二是通过基于Pareto frontier的方法进行bit-width的选取,取代手工选取;三是将该方法拓展到activation的混合精度量化。2020年,北京大学与Berkeley联合发表论文《ZeroQ:A Novel Zero Shot Quantization Framework》提出zero-shot的post-training quantization方法,无需训练集和验证集。首先,通过建模distillation optimization选取distilled data,它的目标是选取部分输入数据,并使得它们的统计量和BN中的一致。然后基于distilled data进行sensitivity analysis。它定义sensitivity metric为原模型与量化后模型输出的KL距离。最后,基于Pareto frontier方法找到每层最适合的精度。具体地,在目标量化model size的约束下,找到能使所有层的敏感度累加最小的bit-width配置。这里假设层与层之间的bit-width选取是相互独立的,即不考虑层间影响。

第二类是基于自动学习的方法。以上方法本质上是基于heuristic。这样的好处是快,但得到的解未必是实际效果最优的。最优的量化策略往往还是和硬件平台相关的,需要根据特定平台『量体裁衣』。那一个自然的思路就是software-hardware co-design的方法,即对bit-width配置策略的调整添加反馈,通过基于如强化学习的方法自动搜索得到最优的每层bit-width配置。2018年ACL Lab等机构的论文《ReLeQ: A Reinforcement Learning Approach for Deep Quantization of Neural Networks》将强化学习(PPO算法)用于量化中自动找到最优的bit-width。为了考虑层间的影响,它的policy network和value network基于LSTM。在学习过程中,agent从预训练全精度模型开始,以层及网络的静态和动态信息embedding后作为状态,逐层从预定bit-width集合{2,3,4,5,6,7,8}中选取bit-width,然后收到与量化后准确率与计算/内存开销收益相同的回报。由于考虑了多目标,所以文中提到对回报函数做了设计,使其在维持准确率与减少bit-width间做了trade-off,让其更注重准确率的维持。为了得到该准确率的降低信息,需要在量化后进行几轮fine-tuning。2019年MIT的的论文《HAQ: Hardware-Aware Automated Quantization with Mixed Precision》提出HAQ(Hardware-Aware Automated Quantization)方法。它通过强化学习(DDPG算法)自动学习每一层的最优bit-width。为了得到强化学习中训练所需的反馈信号,量化模型被放在硬件上运行以获取延迟和能耗等信息,这样比通过FLOPs或内存访问等直觉上的间接目标要更准确。另外,像延迟、能耗与模型大小的限制可以通过强化学习中动作空间的构造来加以限制。因此,回报中只考虑准确率的降低就行。这点上与上面的ReLeQ方法有所差别。文中实现表明在不同的硬件上bit-width的最优配置会有很大差异,而通过该方法可以自动找到每个硬件平台上的最优配置。

以上方法主要是在离散空间中进行搜索。我们知道,如果能将目标整成搜索空间上的可微函数,那我们就可以使用效率更高的基于梯度的优化方法。2018年Berkeley和Facebook的论文《Mixed Precision Quantization of ConvNets via Differentiable Neural Architecture Search》将NAS(Neural architecture search)引入混合精度量化,提出一种Differentiable NAS(DNAS)框架。它根据给定的模型构建具有相同macro architecture的super net。在super net中,两个代表中间数据的节点中会有多个边。每个边代表不同的算子,比如分别对应不同bit-width的卷积。这些边由随机变量edge mask来控制。利用Gumbel Softmax,可以使目标函数对于该mask参数可微。这样,便可以利用常用的SGD进行优化。2019年Sony的论文《Differentiable Quantization of Deep Neural Network》前面有介绍,其中step-size和dynamic range是自动学习的,而bit-width是通过固定的规则从前面自动学习的参数得到的。

3.7 梯度量化

与weight和activation量化不同,梯度的量化主要用于训练,尤其是分布式训练。在传统的分布式训练中,通信的数据一大块是梯度的更新信息。因此,如果减少梯度,那就可以有效减少通信开销,从而提高训练速度。由于适用范围有限(仅适用于训练场景),这里就简略而过。

相关的研究早些年就开始了,如2014年微软和清华大学的论文《1-Bit Stochastic Gradient Descent and Application to Data-Parallel Distributed Training of Speech DNNs》结合quantization-error feedback方法将梯度压缩到1 bit。前面提到的《DoReFa-Net:Training Low Bitwidth Convolutonal Neural Networks with Low Bitwidth Gradients》也涉及了梯度的量化,它设计了梯度量化公式(只在backward时使用)。考虑到梯度是无界的,且可能比activation大得多。该量化公式先对梯度做仿射变换映射到[0, 1]区间,接着量化后再反变换回来。为了补偿潜在的量化引入的偏差,公式还引入了噪声函数,它的大小与可能的量化误差一致。2016年Google的论文《Distributed Mean Estimation with Limited Communication》提出stochastic rotated quantization,将gradient精度降到4位。2016年苏黎世联邦理工学院等机构的论文《QSGD:Communication-efficient SGD via Gradient Quantization and Encoding》提出了QSGD(Quantized SGD)方法,它允许在通信带宽与训练收敛时间之间做trade-off。也就是说计算节点可以在提高variance的代价下调节梯度的bit-width(实验中使用了2bit、4bit、8bit)减少传输开销。2017年杜克大学等机构的论文《Terngrad: Ternary Gradients to Reduce Communication in Distributed Deep Learning》将梯度的精度降低为三值(2位)。它使用了两个方法减少通信开销:一个是parameter localization。传统的parameter server架构中每个PS会将共享的weight发给每个worker,而parameter localization中每个worker维护本地的weight并通过相同的随机种子使它们初始相同,这样只需要传输量化后的梯度即可;另一个是scaler sharing,即取所有worker的scaler参数的最大值作为共享的scaler。2018年Intel的论文《Scalable Methods for 8-bit Training of Neural Networks》从理论上提出大多训练过程对降低精度鲁棒。论文除了将weight和activation量化为8位,也将gradient量化为8位。2018年清华大学的论文《Training And Inference with Integers in Deep Neural Networks》提出了WAGE方法,它用于训练和推理中weight,activation和gradient的error(故得名WAGE)的量化。它提出一种新的初始化方法和一种逐层的scaling factor常量代替BN。这样,整个框架可以在基于整数计算的芯片上训练与推理。

4. 结语

如文章开头所提到的,神经网络模型的量化能带来许多好处。因此,近年来量化成为学术界与工业界热门的研究方向。相关paper也以很快速度增长。但与此同时,模型量化也带来了巨大的挑战。其中比较大的有两个:其一是由于表示精度下降引起信息损失带来准确率的下降;其二是量化带来的不连续性使神经网络的训练不稳定。上面列举的大多数工作也正是围绕它们展开的。

然而,仅仅是在保证准确率的同时降低网络的bit-width只能保证模型size的减少,同时减少理论上的计算量,但是要真正拿到性能的好处还需要计算相关软件与硬件的配合。先看软件部分,现在主流的深度学习/推理框架都支持常见的8位量化。支持的花样也都差不多。以目前最流行的几个为例:

  • TensorFlow:具体可参见官方介绍Model Optimization。它支持quantization-aware training和post-training quantization两种模式。对于后者,又细分为三种:Dynamic range quantization,Full integer quantization和Float16 quantization。原理部分在2018年Google的文章《Quantizing Deep Convolutional Networks for Efficient Inference: A Whitepaper》中有一些介绍。另外2017年Google的论文《Quantization and Training of Neural Networks for Efficient Integer-Arithmetic-Only Inference》介绍了TensorFlow中使得推理能全部以整型计算的方法。

    • Post-training float16 quantization:比较直观,从FP32压到FP16。模型小一半。一些GPU支持FP16计算,因此性能通常会有可观地提高,而且大部分情况下准确率损失不大,可以说是一种性价比比较高的做法。
    • Post-training dynamic range quantization:Weight部分会以静态方式量化为8位整型。activation以浮点形式保存,如果算子支持量化,那会在推理时对activation量化成8位,然后执行8位weight与activation间的计算。否则,weight会从8位转到浮点类型(只会转一次并保存),然后用浮点运算。性能比post-training integer quantization略差,但好处是不需要额外的calibration dataset。
    • Post-training integer quantization:需要calibration dataset来估计activation和输入的dynamic range,这样除了weight外,activation的量化也可以静态确定。这样可生成完全量化的模型,减少运行时开销,同时便于在只支持整型计算的硬件上执行。
    • Quantization-aware training:在训练过程中模拟量化带来的影响,坏处是需要训练,好处是一般准确率损失比前面的要小。
  • Pytorch:具体可参见官方介绍Introduction to Quantization on PyTorch。对量化的支持有下面三种模式。它们分别对应TensorFlow中的post-training dynamic range quantization,integer quantization和quantization-aware training。

    • Dynamic quantization:Weight转为INT8,对activation的转换是动态的(这也是为啥叫dynamic的原因)。activation从内存读写时是以浮点形式的,但会在计算前进行量化,因此计算是以INT8精度来进行。
    • Post-training static quantization:与dynamic quantization类似,weight转为INT8,计算也是用INT8精度进行。区别在于对activation的量化参数是事先通过一些数据来确定而不是动态来确定。这样便可以省下内存访问和动态量化(避免先转成浮点,再量化成整型)的开销,因此性能较第一种也会高一些。
    • Quantization-aware training:在forward和backward时将weight和activation转为INT8,但计算仍以浮点来进行。通过这种方式,让训练过程考虑量化影响,因此准确率的损失也会较前两种方法少。
  • TensorRT:是NVIDIA的主打推理(非训练)框架,材料《8-bit Inference with TensorRT》 中有介绍对量化的支持。它基于的原则是最小化信息的损失。因为KL距离可以用来衡量当使用给定编码近似时的信息损失,所以使用KL距离作为测度。基于这种思想,TensorRT的方法是在一个calibration dataset(几百张,不用标注)上进行FP32的推理,然后得到合适的量化参数,从而使KL距离最小。这种方法用于weight与activation的线性对称量化。

量化模型的高效推理依赖于计算引擎,它需要对低精度有深入的优化。因为大多数的计算都是矩阵乘加,对于量化模型中的矩阵计算也需要专门的计算优化。如Facebook整了两个对量化模型优化的计算库:QNNPACK和FBGEMM。前者主要用于端上,后者主要用于云上。它们是PyTorch用于支持量化模型计算的两个后端。Google系的有gemmlowp,支持ARM和x86,在TensorFlow Lite中有用来支持量化模型计算。近年来,随着超低精度量化技术的兴起,还涌现出一些专用于二值网络的推理引擎,如2019年京东在论文《daBNN: A Super Fast Inference Framework for Binary Neural Networks on ARM devices》中介绍的daBNN。我们知道,机器学习推理框架还有条路就是基于编译器的方法。2020年华盛顿大学和OctoML等机构的论文《RipTide: Fast End-to-End Binarized Neural Networks》中研究了二值化网络的计算优化。它扩展了TVM支持二值网络中的计算,提出了RipTide系统。以SqueezeNet为例,末优化量化模型与原始浮点模型运行还慢了7x,整上Tiling, Vectorization, Parallelization, Fast Popcount, Bitpack Fusion后完美逆袭,比原始浮点模型快了一个数量级。

再进一步地,正如其它领域一样,往往软件和硬件的深度配合才能达到极致的性能。量化模型要达到最高的性能,打造专用的硬件也是一个方向。一方面 ,在工业界量化的支持已经比较成熟。主流的AI芯片基本都支持8 bit运算,如Apple的Bionic芯片和Tesla的FSD。而一些芯片已开始支持8位以下的bit-width,如Imagination的NNA(Neural network accelerator)支持最低4位。NVIDIA在Turning架构中除了支持常规的FP32、FP16和INT8等精度,还提供了INT4,INT1等次字节级精度。另一方面,学界的相关研究也非常丰富。如2016年Stanford和NVIDIA的《EIE: Efficient Inference Engine on Compressed Deep Neural Network》就是一个早期的经典例子。2016年的YodaNN(《YodaNN: An Ultra-Low Power Convolutional Neural Network Accelerator Based on Binary Weights》),2017年的FINN(《FINN: A Framework for Fast, Scalable Binarized Neural Network Inference》)等专注于使用FPGA和ASIC来计算二值网络。2017年的BISMO(《BISMO: A Scalable Bit-Serial Matrix Multiplication Overlay for Reconfigurable Computing》)和2018年的Bit Fusion(《Bit Fusion: Bit-Level Dynamically Composable Architecture for Accelerating Deep Neural Networks》)考虑了混合精度的硬件加速器。另外,量化(尤其是二值化)网络也更适用于神经拟态芯片。如2016年IBM的TrueNorth相关论文(《Convolutional Networks for Fast, Energy-Efficient Neuromorphic Computing》)中就使用了低精度网络,在其中weight和activation分别是三值和二值。虽然人工智能从不是为了复制人脑,但人脑因其超高的计算效率一直吸引着科学家尝试借鉴其机理。尽管目前人类还不知道人脑的工作机制,但直觉上脉冲神经网络貌似更符合猜想,而二值网络感觉又和它有着千丝万缕的联系。

猜你喜欢

转载自blog.csdn.net/ariesjzj/article/details/106955059