【转载请注明出处】chenrudan.github.io
随着神经网络算法的发展,网络性能虽然愈来愈强大,可是也耗费了太多的计算资源和内存,为了获得更有效率的网络以及能部署在移动端,近几年神经网络的压缩算法成了一个研究热点,主要的网络压缩途径有五种,量化、剪枝、低秩分解、教师-学生网络、轻量化网络设计,量化就是将以往用32bit或者64bit表达的浮点数用1bit、2bit占用较少内存空间的形式进行存储。剪枝的目的是为了去掉一些不重要的神经元、链接、通道等,低秩分解主要是经过各类分解方法用精简的张量来表达复杂张量,教师-学生网络间接经过提高小网络性能来压缩学生网络的规模,通常能够与其余压缩方法同时使用,轻量化网络设计主要是相似MobileNet这种设计的很是精简但性能又好的网络。几种方法都各有特色,都是值得研究和讨论的,本文主要针对量化算法近几年的发展作一个梳理和概括,我以为量化算法有几个特色,理论简单,公式少,性能稳定且trick多。
下图1-4我整理了本文涉及到的文章在各个开源数据集上的性能表现,因为各个文章中对比指标不是彻底一致,例如MNIST、Cifar10所用到的基础网络不必定同样,对性能感兴趣的能够去对照原文看看。
![]() ![]() |
![]() |
![]() |
![]() |
![]() ![]() |
![]() |
![]() |
![]() |
模型量化主要包括两个部分,一是针对权重Weight量化,一是针对激活值Activation量化,在一些文章中已经代表了将权重和激活值量化到8bit时就能够等价32bit的性能。在神经网络中的基本操做就是权重和激活值的卷积、乘加操做,W∗AW∗A若是将其中一项量化到{-1,1},那么就将乘加操做简化为了加减操做,若是两项都量化到{-1,1},乘加操做就简化为了按位操做,对于硬件计算是很是友好的。
BinnaryConnect
BinnaryConnect[2]是我看到的第一篇概括出完整量化流程的文章,它提出DNN的前向和反向训练中用1bit的二值权重替代浮点权重,可以让硬件计算将乘法操做简化成简单的累加操做,且能大量的减小存储空间,在MNIST、CIFAR-十、SVHN上接近SOA的性能。
咱们知道正是因为神经网络参数量大,没法直接获得损失函数的最优参数,才采用了梯度降低的方式来逼近最优解,Sgd经过平均权重带来的梯度来获得一些小的带噪声的步长,尝试更新权重去搜索参数空间,所以这些梯度十分重要,要具备足够的分辨率,sgd至少须要68bits的精度,大脑突触的估计精度也是612bits。。若是采用量化权重,就会致使没法对权重直接求导,这种权重能够被当作是带噪声的权重。文章认为带噪声的权重每每可以带来正则化,使得泛化能力更好,相似dropout、dropconnect这种就是对激活值或者权重加入了噪声,它们代表只有权重的指望值须要是高精度的,添加噪声每每是有益处的,因此对权重进行量化理论角度是可行的,且在部分文章中发现对梯度随机取舍可以提供无偏离散化。
在本文中提出了BinaryConnect,在DNN的前向和反向训练中用二值权重替代浮点权重,此处的二值权重B取值为{-1,1},文章中提出了两种量化方法,判别式和随机式,其中σ(w)=clip(x+12,0,1)σ(w)=clip(x+12,0,1),公式1经过符号函数直接取浮点权重的符号,公式2根据当前浮点权重求出一个几率,按照这个几率随机分配正负1。
完整算法流程以下图5,C是损失函数,binarize(w)是按照上述公式二值化权重值,clip(w)是截断权重值,L是层数。前向传播时,只对权重作二值化,而后逐层求出二值权重获得的激活值,反向传播时,也是在二值权重上将对每层输入的导数传播回来,此时的导数是浮点的,更新参数时,一样求得的梯度也是浮点的。因为一般求得的梯度数值不是很大可是又很是重要,因此此处参数更新时仍是用浮点梯度。因为权重量化时只取符号,浮点权重大于正负1,对结果没有影响,为了限制浮点权重不会增加过于夸张以及提升正则性,使用了clip函数将浮点权重限制在正负1之间。


量化网络如何inference,一是直接用二值权重。二是用浮点权重,权重二值化只用在训练阶段。三是从浮点权重和随机二值化能够采样出不少二值网络,将它们的预测输出平均一下做为输出。论文用第三种方法,训练过程当中用随机二值权重,测试时用浮点权重能够提高性能,证实了论文前面认为的带噪声的权重具备必定的正则性。
这篇文章主要贡献在于将浮点权重量化到1bit,提出了完整的量化权重流程,且从带噪声的权重角度来解释量化权重。
BNN
BNN[3]与BinnaryConnect是同一个做者,也是这个算法的扩展,在前面只将权重量化到了1bit,本文则进一步将激活值也变成1bit,即减小了内存消耗,也将许多乘加操做简化成了按位操做XNOR-Count,二值化CNN可以减小60%的硬件时间复杂度,训练BNN在MNIST、CIFAR-十、SVHN上达到了SOA的性能。
权重和激活值都量化成了{-1,1},量化方式也是按照公式1和2,随机式在硬件实现上具备必定的难度,为了加快训练速度,文章中用的是判别式。因为符号函数的梯度都是0,离散神经元的梯度能够经过straight-through estimator[25]来解决,即浮点数的梯度等于量化数的梯度gr=gq1|r|≤1gr=gq1|r|≤1,可是若是浮点权重数值过大,通常要舍弃掉这个梯度。
在训练过程当中,须要保存二值权重和浮点权重,在前向后向计算中用二值权重,计算出来的梯度保存成浮点,且更新到浮点权重上。前向传播时,先对WkWk作二值化,而后与当前的二值输入abk−1ak−1b,相乘获得sksk,再通过BatchNorm,获得输出即下一层的输入abkakb。反向传播时,对二值激活值的的梯度等于对浮点激活值的梯度,计算对上一层输入的梯度时用的是二值权重,计算对二值权重的梯度时用的是上一层的二值激活值。在更新梯度时,梯度更新在浮点权重上,并将新一轮的Wt+1kWkt+1限制在-1~1之间。
文章中提出了第一个卷积层参数广泛较少,因此第一个卷积层输入量化到8bit,后面不少论文也采用一样的策略。与1bit权重相乘方式如公式3,xnxn表明的是用8bit表示方法第n位的取值。
BNN算法主要贡献在于同时对权重和激活值量化到1bit,不只从实验角度证实量化算法的可行,还分析针对低bit如何进行更有效的计算,整理出了同时量化权重和激活值到1bit的算法流程,且针对内部的硬件计算,给出了具体实现,例如Shift-based Batch Normalization、XNOR-Count,最终训练能减小60%的时间,32倍的存储空间。
XNOR-Net
这篇文章[15]提出了两个网络Binary-Weight-Networks(BWN)和XNOR-Net,BWN只将权重量化为二值,XNOR权重和激活值都是二值,速度快了58x,内存节省32x。当AlexNet压缩成BWN时,性能与浮点网络一致。
在对浮点值进行量化时,加入了一个scaling factor,例如权重量化中W=αBW=αB,αα是一个浮点实数,因此在BWN中权重取值就是−α,+α−α,+α,因此量化变成了一个优化问题,这个优化问题是公式4,找到最优的αα使得量化权重与浮点权重之间差距最小。
将公式4对αα求导再设为0,获得alpha的解析解α∗=WTB∗nα∗=WTB∗n,其中包含了二值权重B,若是假设B经过符号函数来求解,那么能够推导出α∗=1n||W||l1α∗=1n||W||l1。
XNOR-Net中对激活值也量化X=βHX=βH,其中H也是{-1,1},ββ是它的尺度系数,卷积包括重复shift操做和点乘,shift指的是filter在输入图上进行移动,当输入输出都变为二值时,将权重和激活值的尺度系数提取出来以后,卷积能够变成xnor-bitcounting操做。
Cnn训练分为三个部分,前向传播、后向传播、参数更新,在前向后向的计算中使用量化权重,更新时若是直接更新量化权重,那么梯度可能不够大到改变量化权重的取值,因此仍是让浮点权重进行更新。
XNOR-Net文章主要贡献在于提出了一个更好的拟合浮点数的方法,即给二值数增长一个尺度因子,而不是简单的取符号,在alexnet上将权重量化到1bit时可以达到跟浮点权重同样的性能。
TWN
前几篇文章都是将浮点数直接量化到了1bit,TWN[4]则提出将权重量化成2bit,虽然2bit能表达四个数,可是只取了三个数{-1,0,1},在mnist和cifar10数据集上三值权重性能比二值权重好不少,经过2bit表达,能够达到16x到32x的模型压缩比例。
通常卷积kernel的尺寸是3x3,针对二值权重,表达能力是2^(33)=512种配置,而三值权重3^(33)=19683种配置,因此说三值权重比二值权重的表达能力要高不少。三值权重取值上多了一个0,实际计算中,因为0值处不须要进行相乘累加,对硬件也是十分友好。
量化公式如公式5,也使用到了尺度因子来拟合浮点权重,最小化量化权重TWN和浮点权重FPWN之间的L2距离。
优化问题就变成了如何求出αα和WtWt,一样对αα求梯度且令梯度为0,能够获得αα的解析解,求出来的WtWt和αα是相互关联的,因此没法直接得出,文章就提出了一种量化方法,首先须要一个阈值ΔΔ,这个阈值用来区分浮点权值映射到正负一、0上,如公式6。而后求出的α∗Δ=1|IΔ|∑i∈Δ|Wi|αΔ∗=1|IΔ|∑i∈Δ|Wi|。
求阈值则没法直接去求解,所以假设权重服从几个分布来分析这个阈值的求解途径,例如假设权重服从均匀分布[-a,a],阈值Δ=1/3∗aΔ=1/3∗a,例如服从高斯分布,阈值Δ=0.6σΔ=0.6σ,因此做者概括出了一个经验公式用于求解Δ∗=0.7n∑ni=1|Wi|Δ∗=0.7n∑i=1n|Wi|,而后求出对应αα。训练网络的方式与以前的文章一致。
TWN的主要贡献经过2bit来近似浮点权重,相比于二值权重性能有较明显的提高,但因为取值也限于正负1和0,对硬件计算没有额外的负担。
BWNH
[5]认为量化的过程能够当作一个hash映射,目标就变成了交替优化方法来学习哈希码。
在以前文章中的量化优化问题都是找到最优的量化数值来拟合浮点数值,本文中考虑的是最小化内积的量化偏差。本文中是将权重量化到1bit,内积指的是权重和激活值之间相乘,也称为输入X和权重W的类似性矩阵S=XTWS=XTW,将浮点权重映射到量化权重的哈希函数为B=g(W)B=g(W),哈希函数X=h(X)X=h(X),h是恒等映射函数。
g(W)=BAg(W)=BA,A是对角矩阵,每一个元素是一个scaling factor,因此目标函数也能够写成minL(A,B)=∑Ni||Si−αi⋅XTBi||2FminL(A,B)=∑iN||Si−αi⋅XTBi||F2,计算每一个αα、输入、二值权重之间的乘积来拟合浮点权重与输入乘积,要求的是哈希映射g,将浮点权重映射到正负一、0这样的hash code上。
此处对A和B求梯度设为0,能够推导出带有输入数据关于αα和B的求解公式8,在更新A时将B固定不动,更新B时固定A不动,且更新每个B时还要固定剩下的B,即经过这种交替优化的方式来进行更新。且因为二值权重的量化error是网络层与层从头至尾一直在累加的,于是考虑分层量化,例如先对前l个层作二值化,让整个网络逐渐的适应二值权重,再去量化第二个部分。
在具体算法流程中,逐层的对每一层的权值作二值化,每一层量化时初始化时B取浮点权重的符号,而A取权重平均绝对值,接着就按照公式8进行交替的优化A和B。最后再对整个网络进行finetuing。
BWNH只对权重进行了量化,算法主要贡献在于从哈希角度来解决量化问题,而且提出了逐层的交替更新,相对于以前的二值权重量化方法性能有着较为明显的提高。
FFN
FFN[16]中只将浮点权重量化到2bit,经过定点化分解方式来求解量化后权重,因为三值权重只有正负1和0,便可以消除最耗费资源的multiply-accumulate operations(MAC)操做,FFN能够获得浮点网络性能至关的网络,且乘法运算仅为浮点网络的千分之一。
经过semidiscrete decomposition(SDD)半离散分解将浮点权重W分解成定点化方式W=XDYTW=XDYT,中D是一个非负对角矩阵,X和Y每一个元素取值为{-1,0,1},因此一个正常的卷积n*c*h*w会被分解成三个步骤,卷积有n个输出channel,拆成三个后,第一个可当作有k个输出channel的卷积,即k*c*h*w,第二个步骤至关于每一个特征图都乘以一个尺度因子,最后一个也能够当作卷积层大小是n*1*1*k。


为了更好的恢复浮点权重,算法中保留了X和Y对应的浮点数值X^X^和Y^Y^,且浮点数值被限制在-1.5~1.5,根据取值落在哪一个区间量化到哪一个数值,而在梯度更新时,更新的对象是X^X^和Y^Y^。
FFN只针对权重作了量化,提出了将浮点权重矩阵用矩阵分解的方式分解成三个简单矩阵,其中两个矩阵元素取值为正负1和0,从而间接完成量化的功能。
INQ
INQ[17]提出增量网络量化方法,经过权重分组、按组量化、从新训练三个操做将浮点网络量化到低bit网络,在resnet18上量化权重后,4bit、3bit、2bit可以达到甚至超过浮点权重。
文章从网络剪枝算法中获得灵感,逐步的从已经训练好的网络中移除掉不那么重要的权重,最终性能也不会有明显降低,因此说权重是存在不一样的重要性的,可是以前的方法没有考虑到这点,而是同时将高精度浮点数转化为低精度数值,所以改变网络权重的重要性对于减小量化网络的损失很重要。
本文中低bit权重须要一个符号位,至少从2bit开始,b是比特数,取值范围是Pl=±2n1,…,±2n2,0Pl=±2n1,…,±2n2,0,由两个整数n1n2定义n2=n1+1−2b−12n2=n1+1−2b−12,经过经验公式能够计算出n1n2。量化公式9中的αα和ββ就是PlPl中相邻的两项。
网络训练过程当中,将权重分割到两个不相交的组中,第一个组A(1)lAl(1)中的权重基于公式4进行组内量化,另外一个组$A_l^{(2)}中权重保持浮点精度,自适应的弥补量化模型形成的loss,且在反向re-training更新权重时,经过一个mask来判断属于哪一个组,属于第一个组的量化权重就不更新,只更新第二个组的浮点权重。而后针对第二个组的浮点权重作重复的三步操做,直到全部权重被量化完成。


INQ算法对权重进行了量化,经过逐步增量式的将权重量化,经过保留一部分浮点权重来恢复模型的性能,精度损失获得了必定的遏止。
SQ-B(T)WN
SQ-B(T)WN[6]也是一种增量式量化算法,它从不一样权重会致使不一样量化偏差角度,在近似实数权重时,可能只是针对部分filter量化error大,部分filter量化error小,文章提出了随机选择部分filter量化STOCHASTIC QUANTIZATION,逐渐增长量化比例最终完成所有权重量化。
一层的权重按照输出channel做为一组数据W=W1,…,WmW=W1,…,Wm,其中m等于输出channel数量,第i个filter权重是WiWi。也是将这一层的权重划分红两个不相交的集合GqGq和GrGr,将GqGq中权重量化到低bit,而GrGr权重仍是浮点,GqGq有Nq=r∗mNq=r∗m个filter,而GqGq有Nq=(1−r)∗mNq=(1−r)∗m个。其中r就是随机量化SQ比例,r在逐渐增长,最终增长到1。
针对每个filterWiWi都有本身的一个量化几率pipi,代表第i个filter被量化的几率,量化几率的取值由量化偏差决定。当量化偏差小时,量化当前的这个channel就会形成较少不一样的信息损失,那么就能给这个channel赋予较大的量化几率。首先定义浮点权重和量化权重的L1距离ei=||Wi−Qi||1||Wi||1ei=||Wi−Qi||1||Wi||1,将它做为量化偏差,并定义一个中间变量fi=1ei+ϵfi=1ei+ϵ,从而量化几率能够有不一样的求解方法,例如pi=1/mpi=1/m或者pi=11+exp(−fi)pi=11+exp(−fi)。


在图8中,先计算出4个channel的量化error,假设当前r=50%,根据每一个channel计算出来的量化几率挑选2个channel量化。
SQ-B(T)WN算法经过逐步量化权重,比直接所有量化产生的更加合适梯度方向,可是从算法结果上来讲,看起来并非特别好。
Deep Compression
Deep Compression算法[7]结合了剪枝、量化、哈夫曼编码三种操做,在性能没有下降的状况下压缩了35x~49x,目标是减小存储空间减小inference的耗时,从而能部署在移动设备上。
第一步是剪枝,在训练过程当中来学习各个链接的性能表现,而后裁剪掉权重较小不够重要的链接,经过设定一个阈值,小于这个阈值移除掉,再从新训练留下的稀疏链接。剪枝后的稀疏结构用compressed sparse row和compressed sparse row方式存储,须要保存2a+n+1数据,a是非零值元素个数,n是行数或者列数。这一步中能够在Alexnet和VGG-16上压缩9x~13x。
第二步是量化,经过让多个链接共享相同权重来达到量化目的,在有限的bit数中只能表达有限的数值,因此当某些神经元取同样的数值时,就说它们在共享这个权重。假设权重大小是4*4,权重被量化到4个bin,在相同bin中的权重取值相同,所以只须要保存bin的索引,更新的时候相同bin中的梯度加起来再更新。假若有k个bin,那么须要log2k位来对索引进行编码,假如网络有n个链接,每一个链接由b个位表达,从而能够获得压缩比例r=nbnlog2(k)+kbr=nbnlog2(k)+kb。经过k-means聚类来肯定这些用于共享的权重,将n个权值分配到k个类中,最小化权重和类中心绝对值之差(WCSS)获得类中心C=c1,…,ckC=c1,…,ck。尝试了三种初始化共享权重中心C的方法,随机、基于密度、线性初始化,随机方法就从权重中随机选择k个值,基于密度会选择一些在尖峰周围的点,线性初始化在权重数值线性进行间隔选择,发现线性初始化效果最好。反向传播也跟其余量化方式是一致的。
huffman编码是一种无损数据压缩方法,压缩非均匀分布的值可节省20%30%的网络存储。最终通过这三个操做,网络在性能没有下降的状况下被压缩了35x49x。
这篇文章操做较多比较复杂,可是性能是稳定可靠的,每一个压缩操做都没有致使性能降低。
TTQ
TTQ[8]量化浮点权重到三值权重,在开源数据集上相比浮点性能降低不多。
在以前的量化算法中,是经过一个尺度因子和三值权重相乘来拟合浮点权重,像在TWN中给出了经验公式来计算尺度因子αα,本文提出了经过梯度降低对αα进行更新。
首先将浮点权重除以最大值后正则化到正负1之间,全部的层有一个相同的参数t,用来计算阈值Δl=t×max(|w~|)Δl=t×max(|w~|)进行量化。
这里针对正负数有不一样的量化levels,即有两个尺度因子WplWlp和WnlWln。所以对它们计算梯度能够获得梯度降低更新公式,∂L∂Wpl=∑i∈Ipl∂L∂wtl(i),∂L∂Wnl=∑i∈Inl∂L∂wtl(i)∂L∂Wlp=∑i∈Ilp∂L∂wlt(i),∂L∂Wln=∑i∈Iln∂L∂wlt(i)。在观察尺度因子的变化状况时,针对第一个量化全局层,正负尺度因子的绝对值会变得愈来愈小,稀疏性下降了,针对最后一个卷积层和全链接层正负尺度因子的绝对值会变得愈来愈大,稀疏性提高了。
对尺度因子进行训练的好处在于,正负尺度因子的不对称使得模型能力更强,且针对全部层有一个常数稀疏r,调整超参数r能够调整量化阈值,可以得到不一样稀疏度的三值网络。
TTQ中将正负量化levels分开考虑,且做为可训练的参数进行更新,而不是用经验公式进行计算,性能比TWN也要好一些。
DoReFa-Net
在DoReFa-Net[9]中权重、激活值和参数梯度都设置成了低bit,优势是不仅在inference时可以加速,且训练时因为梯度也被量化了,训练时也能加速。因此可以很好的在硬件平台上直接进行训练。
当权重和激活值都量化后,就可以用bitcount操做来计算,即x和y相与的结果后能够直接数出位置为1的个数,而以前的文章中尚未量化过梯度到8bit如下。在BNN网络中,浮点梯度在-1到1范围内时等于量化梯度,超出范围就等于0,在xnor-net中,浮点梯度直接等于量化梯度,因为加上了一个尺度因子,因此权重可以表示的范围就更广了,在DoReFa-Net中权重量化方式为ro=fkw(ri)=2quantizek(tanh(ri)2max(|tanh(ri)|)+12)−1ro=fwk(ri)=2quantizek(tanh(ri)2max(|tanh(ri)|)+12)−1,其中k是指定的bit数,fkw(ri)fwk(ri)取值被限制在了-1~1之间。
激活值的量化先是由一个激活函数将范围限制在0~1以内,再量化到k bit,fka(r)=quantizek(r)fak(r)=quantizek(r)。
在针对梯度进行量化时,随机量化是一个比较有效的手段,且梯度是不像激活值能够被限制在某个范围内,有的位置上梯度取值可能会比较大,激活值因为能够通过一个激活函数,因此可以限制数值大小。梯度量化公式为fkγ(dr)=2max0(|dr|)[quantizek[dr2max0(|dr|)+12+N(k)]−12]fγk(dr)=2max0(|dr|)[quantizek[dr2max0(|dr|)+12+N(k)]−12],本文的随机就体如今加入了一个额外的噪声函数N(k)N(k),效果很是明显。
因此DoReFa-Net并非指定量化到多少bit,而是能够量化到任意的bit,因为整个网络的输入数据层channel较少,对于总体网络复杂度影响较小,所以第一个卷积层的权重不进行量化,第一个卷积层的输出激活值会被量化,若是输出类别较少时,最后一个卷积层的权重也不进行量化,最后一层的反向梯度须要量化。
这篇文章主要就是提出对梯度也进行量化,而且支持量化到任意bit。
ABC-Net
二值权重和激活值可以很大程度的减小内存空间,且能采用按位计算,对硬件很友好,可是现有的方法会致使性能降低,本文主要提出了ABC-net(Accurate-Binary Convolutional)线性组合多个二值权重基来拟合浮点权重,利用多个二值激活值基组合来减小信息损失。
将浮点权重用M组二值权重和尺度因子进行线性组合,W≈α1B1+α2B2+…+αMBMW≈α1B1+α2B2+…+αMBM,将B表示成浮点权重与均值和方差的组合形式Bi=Fui(W):=sign(W−mean(W)+uistd(W))Bi=Fui(W):=sign(W−mean(W)+uistd(W)),其中有一个尺度变量uiui,既能够由经验公式ui=−1+(i−1)2M−1ui=−1+(i−1)2M−1直接算出,也能够经过网络训练的方式获得。这样去估计B的缘由是,浮点权重倾向因而一个对称、非稀疏分布,比较相似高斯分布,因此用均值和方差来估计。肯定B以后,经过线性回归来求解alpha。在增长了尺度因子后,求解反向梯度时,会增长一个αα系数,∂c∂W=∑Mm=1αm∂c∂Bm∂c∂W=∑m=1Mαm∂c∂Bm。在实现中,将浮点权重按照channel区分开,用一样的方式来估计尺度因子和二值权重,理论上可以更加细致的拟合浮点权重。
当权重是二值的,卷积操做就没有了乘法,只剩下加减,若是想要更高效的利用按位操做,最好是将激活值也变为二值。所以相似对权重的处理,文章首先将激活值经过一个clip函数hv(x)=clip(x+v,0,1)hv(x)=clip(x+v,0,1),将范围限制在0~1之间,量化激活值取值是{-1,1},经过一个指示函数A=Hv(R):=2Ihv(R)≥0.5−1A=Hv(R):=2Ihv(R)≥0.5−1进行量化,量化激活值与量化权重的不一样点在于,inference的阶段权重是不变的,激活值则变化了,可是经过利用神经网络激活值的统计特性可以避免这个问题,为了保证激活值的分布相对稳定,使用了batchnorm,它可以让输出保持0均值1方差的分布。用N组二值激活值和尺度因子组合成浮点激活值R≈β1A1+β2A2+…+βNANR≈β1A1+β2A2+…+βNAN,激活值量化中多了一个能够训练的阈值vv。卷积操做就转化M*N个按位操做,Conv(W,R)≈∑Mm=1∑Nn=1αmβnConv(Bm,An)Conv(W,R)≈∑m=1M∑n=1NαmβnConv(Bm,An)。
ABC-Net也是一个不限制bit数的量化算法,性能也接近浮点网络。
HWGQ
HWGQ[11]主要针对激活值量化,利用了激活值的统计特性和batchnorm操做,在前向计算时能有效的近似浮点值的性能。
针对激活值的量化须要处理不可微的操做,主要切入点在于ReLU函数,神经网络每一个单元都计算了一个激活函数,即权重与输入相乘后通过一个非线性变换,这个操做的多少决定了整个网络的复杂度。
本文中估计1bit量化权重,也是基于二值权重和尺度因子相乘去拟合浮点权重,输入I与量化权重卷积来近似I和浮点权重卷积结果,是二值权重取浮点权重的符号B∗=sign(W)B∗=sign(W),尺度因子是浮点权重平均绝对值α∗=1cwh||W||1α∗=1cwh||W||1,1bit权重可以减小存储空间,可是没法彻底计算复杂度的问题,若是将I也变成二值的,则可以最大程度上解决计算复杂度的问题。
在对激活值进行量化时,若是直接按照符号函数来定义量化levels,那么对量化激活值进行求导时,导数到处为0,因此有人提出,对符号函数求导若是输入绝对值小于1则梯度为1,其余位置取0。结合relu函数,本文对激活值量化的目标是拟合relu函数的输出。quantizer是一个分段常数函数,量化levels就是量化到的值,量化step就是两个量化level之间的差,针对每一个浮点数值,它只须要保存一个索引值i,对应到第i个量化level,非均匀量化状况下表达浮点权重须要多余log2mlog2m的bit数,若是是均匀量化则log2mlog2m个bit就够了。激活值的统计结构倾向于对称非稀疏分布相似高斯分布,再结合relu,就是变成了一个半波高斯量化子half-wave Gaussian quantizer。这里的量化就是变成了求针对高斯分布的量化levels和step,可是在不一样层的神经元所获得的类高斯分布,它们的均值方差不必定是相同的,为了获得相同的数据分布,经过batchnorm来获得0均值1方差的分布,而后就能在神经元之间获得均匀的量化参数。以上是在解释构造这样的HWGQ,它是阶梯常数函数,梯度到处为0,目标就变成了选哪一个函数做为HWGQ在量化后才能最好的拟合relu函数的效果。
首先考虑最基本的relu函数,它对输入的梯度等于输出梯度,与正向的HWGQ所须要的梯度是不匹配的,特别是当输入数值大于最大的量化level时,产生的偏差致使的反向梯度就会特别大。基于这个状况,考虑用clipped后的relu,保证最大值不超过最大的量化level,可是因为clipped的操做,丢失掉了qmqm以后的输入信息会直接致使性能的降低,所以提出一种折中的函数公式11即长尾relu,它既能保证超过qmqm的梯度不会过大,也不会彻底丢失掉大于qmqm的信息。
HWGQ主要从理论上分析如何去选择一个激活函数,从而保证激活值量化后低bit网络性能接近浮点网络。
Network Sketching
本文提出了Network Sketching[19]用来寻找量化二值权重的网络,整个过程能够当作是由粗到细的模型近似。
按照输出channel来划分不一样的filter,假设有m组基来拟合一个channel的权重,W=∑m−1m=0αjBjW=∑m=0m−1αjBj,其中B∈{+1,−1}c×w×h×mB∈{+1,−1}c×w×h×m,而α∈Rmα∈Rm。主要想法是基于不断拟合量化权重和浮点权重之间的残差,即计算浮点权重减去已经累加获得的量化权重∑j−1k=0αkBk∑k=0j−1αkBk之间的残差成为新的须要拟合的浮点权重,去得到下一步的B和αα,即公式12。
具体在求B和αα,B是取浮点权重的符号,αα由二值权重和浮点权重内积求出来αj=<Bj,Wj^>tαj=<Bj,Wj^>t,其中t=c×w×ht=c×w×h。在第一个Direct Approximation算法中就是重复m次,求出m组B和αα。重构error以1/t的指数进行衰减,若是t取值小,重构error就会越小,t很大时,重构error的减小幅度就会很慢,就算增长m的数量,最终的近似效果可能也不够好。因此B和αα不必定是最优的,为了进一步优化获得更好的近似效果,在第二个Approximation with Refinement算法中给出更新公式,aj=(BTjBj)−1BTj⋅vec(W)aj=(BjTBj)−1BjT⋅vec(W),且文中进一步证实了更新公式可以近似浮点权重,减小量化error。
本文的sketch就体如今第j个量化权重是在估计当前浮点权重的残差,量化error愈来愈精细,就像在逐步的从粗到细描绘出具体的轮廓。
PQ+TS+Guided
本文[20]为了提高量化网络训练性能,提出了三个方法,一是两步优化策略,先量化权重再量化激活值,其次在训练过程当中逐步减小量化位宽,第三联合训练浮点网络和低精度网络。
量化采用的是Q函数均匀量化,zq=Q(zr)=12k−1round((2k−1)zr)zq=Q(zr)=12k−1round((2k−1)zr),在量化权重时,先对w作归一化,其中tanh能够减小大值的影响,再用Q函数去量化,求解形式与DoReFa-Net是同样的。针对激活值,先将激活值经过clip函数限制在0~1的范围内,而后用Q量化。反向传播更新梯度也是基于STE算法。
为了增长量化的准确性,本文首先提出了两步优化two-stage optimization(TS),先量化权重再量化激活值,若是从K-bit的网络量化获得k-bit的网络,首先训练在K-bit激活值下的k-bit权重,在k-bit权重训练好后训练k-bit的激活值。而因为训练过程当中近似的梯度不必定是准确的,因此会致使陷入局部最优值的状况,因此本文提出了分阶段量化progressive quantization(PQ)的想法,逐步减小量化位宽的方法,例如32bit->16bit->4bit->2bit,量化n次就得完整训练n次。第三个提高方法是基于教师-学生网络(Guided),联合训练浮点网络和低精度网络,互相适应,由于直接用固定的预训练好的浮点模型来指导量化网络不必定最好,且在特征图层面上进行迁移,为了保持浮点网络和低精度网络一致,在相互适应时,将浮点网络也作一样的量化,而后再相互迁移。


这个方法主要是提出一些有效的trick来辅助训练量化网络,且表现很是不错。
SYQ
SYQ[21]提出了对称量化可以提高网络准确率。
在SYQ中,Codebook C是量化levels的一些可能取值,例如{-1,1},或者{-1,0,1},二值化或者三值化权重时一般的方法是采用分段常数函数,并存在ηη这样的量化阈值超参数,二值化时取为0,三值时由经验公式η=0.05×max(|Wl|)η=0.05×max(|Wl|)得出。后来的估计方式中引入了scaling factor,提升了近似浮点数的能力,此时的codebook就变成了−α,α−α,α,前面提到过的TTQ就是提出能够对αα进行训练,且设置正负两个尺度因子−αnl,αpl−αln,αlp,可是若是采用正负不一样的尺度因子,那么在计算权重和激活值乘积时须要先去判断当前二值权重或者三值权重的符号,增长了额外的判断分支,因此本文认为对称的codebook计算效率会更高,codebook最好是在0周围对称,那存储空间可减半。
不少细粒度量化方法可以提高近似权重分布的能力,本文实现了按像素进行缩放,假设一层权重是K×K×N×IK×K×N×I,pixel-wise就是在I*N维度上将权重进行分组,此时αα个数为K2K2,此时就是将权重分为了K2K2组,row-wise将一个kernel中行或者列组成一组,最粗粒度的是layer-wise,一层只有一个αα。
在SYQ算法流程中,每一层首先经过Ql=sign(Wl)⨀MlQl=sign(Wl)⨀Ml量化权重成二值或者三值,其中MlMl是经过ηη计算获得,而后经过G(x)=12ffloor((2f)x+12)G(x)=12ffloor((2f)x+12)线性量化激活值,前向计算完成以后,经过∂E∂Wli,j=αil∂E∂Qli,j∂E∂Wli,j=αli∂E∂Qli,j来更新权重,经过∂E∂x=∂E∂G∂E∂x=∂E∂G更新激活值,经过∂E∂αil=∑j∈Sil∂E∂Wli,j∂E∂αli=∑j∈Sli∂E∂Wli,j更新scaling factor。
SYQ相对于TTQ没有特别明显的改进,增长了αα的数量使得最终性能想比于TTQ有提高。
TSQ
以前方法中都是同时量化权重和激活值,TSQ[12]提出了先量化激活值再量化权重,针对激活值,提出了稀疏量化方法,文章认为网络压缩和加速中稀疏能起到很大做用,以前的文章中都不多研究这个方向,且稀疏性在特殊硬件上会更有效,而权重量化能够当作低bit非线性最小二乘回归问题,经过迭代方式求解。
获得低比特权重是transformations,获得低比特激活值是encodings。在encodings问题中,Relu函数自己就产生了50%的稀疏性,在attention机制的基本假设中,数值较大的激活值比数值较少的激活值更重要。因此将数值较小的正值变成0,这样量化算法可以更能关注到较大的数值,量化的会更精细。n-bit均匀量化子quantizer将浮点激活值映射到2n2n个离散值,主要就是在于决定量化间隔ΔΔ和量化范围titi。以前的HWGQ方法中是经过batchnorm层,输出分布就很是趋近于0均值1方差的高斯分布,所以每一个层的ΔΔ和titi是相同的。本文提出稀疏量化,不是将通过relu后的全部正值都进行量化,而是将不重要的数值先设置为0再量化,这个想法以前在网络剪枝中也有相似研究,也就是大值比小值更重要。因此给出了一个稀疏阈值ϵϵ,获得新的求解激活值量化函数的公式13。
对权重进行量化,假设上一层的输出是X,这一层的输出是Y,将权重量化的问题变成一个非线性最小平方回归问题,将浮点尺度因子αα当作一个对角矩阵,与输入X相乘以后再通过激活值量化最终去拟合浮点输出minimizeα,w^||y−Qϵ(αXTw^)||minimizeα,w^||y−Qϵ(αXTw^)||。而后引入了一个辅助变量z,将两个量化过程区分开minimizeα,w^,z||y−Qϵ(z)||+λ||z−αXTw^||minimizeα,w^,z||y−Qϵ(z)||+λ||z−αXTw^||,权重量化去拟合辅助变量z,激活值量化去拟合浮点输出。
在求解αα和w时,将优化问题展开以后,对αα进行求导且设置导数为0,能够直接得出αα的求解公式,而后将αα带入展开公式一样求出w的求解公式。因为w的维数较高,即m个像素点每一个都须要进行计算,而每一个可能取值又是2^n个bit,因此若是用穷举法来找到最优的w是不可行的,仍是在求解一个w时,固定剩下的w不变。在求z时,此时αα和w是肯定的,且此处将激活值量化函数条件放宽,在0~M范围内的数值就不进行量化,因此针对不一样分布获得了z的求解方式。
对权重量化时,层与层之间能够同时进行,没有耦合关系,可是独立进行量化时,量化偏差会在层与层之间累加,因此仍是考虑经过按层量化。
TSQ经过稀疏量化激活值和引入一个中间变量z来产生新的量化方法,在alexnet上将权重激活值都量化到2bit时性能与浮点也是一致的。
LQ-Net
LQ-Net[13]目的是但愿学习量化任意bit权重和激活值的quantizers,现有的量化方法都是一种人工设计的quantizers,例如均匀量化、对数量化,或者在网络训练之时已经计算好的quantizers(HGWQ),若是针对不一样的网络能自适应的学到不一样quantizers,性能应该会有所提高,因此本文就想联合训练一个量化的DNN网络和对应的quantizers。
qlql是量化levels,量化intervals指的是tltl到tl+1tl+1,浮点值在tltl到tl+1tl+1范围内的会被量化到qlql,均匀量化就是指每一个tltl到tl+1tl+1的范围都是相同的,对数量化是tltl到tl+1tl+1的范围成指数关系,量化到n-bit,就有32/n或者64/n倍的压缩比例。可是因为每一个卷积层的数据分布的不一样,均匀量化不必定是最优的,预先设置好的量化方式也不必定是最优的,因此考虑既训练整个量化网络,也训练量化函数。若是量化函数是能够训练的,那么它不只可以减小量化偏差,也能适应总体的训练目标提高最终性能。
假设网络被量化到K-bit,一个整数q能够经过一个k维的basis系数向量v和k个bit的二值编码向量elel点积表达,如公式14所示,此处的系数向量取值为整数。
因为二值编码向量elel里面每一个元素取值都是0和1,当k肯定以后elel全部取值可能均可以肯定,例如K=2,elel全部可能为{(-1,-1),(-1,1),(1,-1),(1,1)}。v是一个可学习的浮点basis系数向量,v值肯定以后和每一组可能的二值编码向量相乘ql=vTelql=vTel,获得了一系列的量化levels,量化intervals就是两个level之间的均值。
对权重和激活值都进行相同的量化操做,卷积就变成了Qours(w,vw)TQours(a,va)=∑Kwi=1∑Kaj=1vwivaj(bwi⊙baj)Qours(w,vw)TQours(a,va)=∑i=1Kw∑j=1Kaviwvja(biw⊙bja),其中有两组要学习的参数,分别是vwvw和vava,同一层的激活值量化共用一个vava向量,一层权重对应每一个输出channel用一个vwvw向量。
在量化和更新过程当中,在训练开始以前经过一个经验公式求出初始的v,而后先固定v更新B,此时v是已知的,能够直接计算出全部levels,对比浮点数x落在哪一个区间就量化到对应的B。而后固定B更新v,经过最小化量化偏差argmaxv,B||BTv−x||22argmaxv,B||BTv−x||22对v求闭式解v∗=(BBT)−1Bxv∗=(BBT)−1Bx来更新当前的v。
LQ-Net算法经过学习获得量化levels,而不是人为设计的quantizers,能够量化到任意的bit,在几个开源数据集上都有很是不错的性能表现。
小结
写到后面,感受意识有点模糊了,到如今我已经工做了一年多了,今年开始在作模型量化方面的工做,由于须要保护公司的利益,不可能在文章中聊工做的事情,因此只能分享了几篇我的以为作这个方向须要了解的一些文章,若是有不足的地方,但愿你们批评指正,谢谢了。
[1] Maxout Networks
[2] BinaryConnect: Training Deep Neural Networks with binary weights during propagations
[5] From Hashing to CNNs: Training Binary Weight Networks via Hashing
[6] Learning Accurate Low-Bit Deep Neural Networks with Stochastic Quantization
[8] TRAINED TERNARY QUANTIZATION
[9] DOREFA-NET: TRAINING LOW BITWIDTH CONVOLUTIONAL NEURAL NETWORKS WITH LOW BITWIDTH GRADIENTS
[10] TRAINING AND INFERENCE WITH INTEGERS IN DEEP NEURAL NETWORKS
[11] Deep Learning with Low Precision by Half-wave Gaussian Quantization
[12] Two-Step Quantization for Low-bit Neural Networks
[13] LQ-Nets: Learned Quantization for Highly Accurate and Compact Deep Neural Networks
[14] ImageNet Classification with Deep Convolutional Neural Networks
[15] XNOR-Net: ImageNet Classification Using Binary Convolutional Neural Networks
[16] Fixed-point Factorized Networks
[17] INCREMENTAL NETWORK QUANTIZATION: TOWARDS LOSSLESS CNNS WITH LOW-PRECISION WEIGHTS
[18] DOREFA-NET: TRAINING LOW BITWIDTH CONVOLUTIONAL NEURAL NETWORKS WITH LOW BITWIDTH GRADIENTS
[19] Network Sketching: Exploiting Binary Structure in Deep CNNs
[20] Towards Effective Low-bitwidth Convolutional Neural Networks
[21] SYQ: Learning Symmetric Quantization For Efficient Deep Neural Networks
[22] Very deep convolutional networks for large-scale image recognition
[23] Towards Accurate Binary Convolutional Neural Network
[24] Deep residual learning for image recognition
[25] Estimating or Propagating Gradients Through Stochastic Neurons for Conditional Computation