神經網路模型量化方法簡介
【轉載請註明出處】chenrudan.github.io
隨著神經網路演算法的發展,網路效能雖然越來越強大,但是也耗費了太多的計算資源和記憶體,為了得到更有效率的網路以及能部署在移動端,近幾年神經網路的壓縮演算法成了一個研究熱點,主要的網路壓縮途徑有五種,量化、剪枝、低秩分解、教師-學生網路、輕量化網路設計,量化就是將以往用32bit或者64bit表達的浮點數用1bit、2bit佔用較少記憶體空間的形式進行儲存。剪枝的目的是為了去掉一些不重要的神經元、連線、通道等,低秩分解主要是通過各種分解方法用精簡的張量來表達複雜張量,教師-學生網路間接通過提升小網路效能來壓縮學生網路的規模,一般可以與其他壓縮方法同時使用,輕量化網路設計主要是類似MobileNet這種設計的非常精簡但效能又好的網路。幾種方法都各有特點,都是值得研究和討論的,本文主要針對量化演算法近幾年的發展做一個梳理和歸納,我覺得量化演算法有幾個特點,理論簡單,公式少,效能穩定且trick多。
下圖1-4我整理了本文涉及到的文章在各個開源資料集上的效能表現,由於各個文章中對比指標不是完全一致,例如MNIST、Cifar10所用到的基礎網路不一定一樣,對效能感興趣的可以去對照原文看看。
![]() ![]() |
![]() |
![]() |
![]() |
模型量化主要包括兩個部分,一是針對權重Weight量化,一是針對啟用值Activation量化,在一些文章中已經表明了將權重和啟用值量化到8bit時就可以等價32bit的效能。在神經網路中的基本操作就是權重和啟用值的卷積、乘加操作,$W*A$如果將其中一項量化到{-1,1},那麼就將乘加操作簡化為了加減操作,如果兩項都量化到{-1,1},乘加操作就簡化為了按位操作,對於硬體計算是非常友好的。
BinnaryConnect
BinnaryConnect[2]是我看到的第一篇歸納出完整量化流程的文章,它提出DNN的前向和反向訓練中用1bit的二值權重替代浮點權重,能夠讓硬體計算將乘法操作簡化成簡單的累加操作,且能大量的減少儲存空間,在MNIST、CIFAR-10、SVHN上接近SOA的效能。
我們知道正是由於神經網路引數量大,無法直接得到損失函式的最優引數,才採用了梯度下降的方式來逼近最優解,Sgd通過平均權重帶來的梯度來得到一些小的帶噪聲的步長,嘗試更新權重去搜索引數空間,因此這些梯度十分重要,要具有足夠的解析度,sgd至少需要6~8bits的精度,大腦突觸的估計精度也是6~12bits。。如果採用量化權重,就會導致無法對權重直接求導,這種權重可以被看成是帶噪聲的權重。文章認為帶噪聲的權重往往能夠帶來正則化,使得泛化能力更好,類似dropout、dropconnect這種就是對啟用值或者權重加入了噪聲,它們表明只有權重的期望值需要是高精度的,新增噪聲往往是有益處的,所以對權重進行量化理論角度是可行的,且在部分文章中發現對梯度隨機取捨能夠提供無偏離散化。
在本文中提出了BinaryConnect,在DNN的前向和反向訓練中用二值權重替代浮點權重,此處的二值權重B取值為{-1,1},文章中提出了兩種量化方法,判別式和隨機式,其中$\sigma (w)=clip(\frac{x+1}{2},0,1)$,公式1通過符號函式直接取浮點權重的符號,公式2根據當前浮點權重求出一個概率,按照這個概率隨機分配正負1。
$$
w_b= \begin{cases} +1, & \text {if $w \geq$ 0}; \ -1, & \text{otherwise} \end{cases} \tag{1}
$$
$$
w_b= \begin{cases} +1, & \text {with probability $p=\sigma (w)$}; \ -1, & \text{with probability 1-p} \end{cases} \tag{2}
$$
完整演算法流程如下圖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-10、SVHN上達到了SOA的效能。
權重和啟用值都量化成了{-1,1},量化方式也是按照公式1和2,隨機式在硬體實現上具有一定的難度,為了加快訓練速度,文章中用的是判別式。由於符號函式的梯度都是0,離散神經元的梯度可以通過straight-through estimator[25]來解決,即浮點數的梯度等於量化數的梯度$g_r = g_q1_{|r|\leq 1}$,但是如果浮點權重數值過大,一般要捨棄掉這個梯度。
在訓練過程中,需要儲存二值權重和浮點權重,在前向後向計算中用二值權重,計算出來的梯度儲存成浮點,且更新到浮點權重上。前向傳播時,先對$W_k$做二值化,然後與當前的二值輸入$a_{k-1}^b$,相乘得到$s_k$,再經過BatchNorm,得到輸出即下一層的輸入$a_k^b$。反向傳播時,對二值啟用值的的梯度等於對浮點啟用值的梯度,計算對上一層輸入的梯度時用的是二值權重,計算對二值權重的梯度時用的是上一層的二值啟用值。在更新梯度時,梯度更新在浮點權重上,並將新一輪的$W_k^{t+1}$限制在-1~1之間。
文章中提出了第一個卷積層引數普遍較少,所以第一個卷積層輸入量化到8bit,後面很多論文也採用同樣的策略。與1bit權重相乘方式如公式3,$x^n$代表的是用8bit表示方法第n位的取值。
$$
s = \sum_{n=1}^{8}2^{n-1}(x^n\cdot w^b) \tag{3}
$$
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=\alpha B$,$\alpha$是一個浮點實數,所以在BWN中權重取值就是$-\alpha, +\alpha$,所以量化變成了一個優化問題,這個優化問題是公式4,找到最優的$\alpha$使得量化權重與浮點權重之間差距最小。
$$
J(B,\alpha )=||W-\alpha B||^2 \\
\alpha^{*},B^{*}=\underset{\alpha,B}{argmin}J(B,\alpha ) \tag{4}
$$
將公式4對$\alpha$求導再設為0,得到alpha的解析解$ \alpha^{*} =\frac{W^TB^{*}}{n} $,其中包含了二值權重B,如果假設B通過符號函式來求解,那麼可以推匯出$ \alpha^{*} =\frac{1}{n} ||W||_{l_1}$。
XNOR-Net中對啟用值也量化$X = \beta H$,其中H也是{-1,1},$\beta$是它的尺度係數,卷積包括重複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^(3 3)=512種配置,而三值權重3^(3 3)=19683種配置,所以說三值權重比二值權重的表達能力要高很多。三值權重取值上多了一個0,實際計算中,由於0值處不需要進行相乘累加,對硬體也是十分友好。
量化公式如公式5,也使用到了尺度因子來擬合浮點權重,最小化量化權重TWN和浮點權重FPWN之間的L2距離。
$$
\alpha^{*},W^{t*}=\underset{\alpha, W^t}{argmin}J(\alpha, W^t)=||W-\alpha W^t||^2 \text { s.t. } \alpha\geq 0, W_i^t\in {-1,0,1} \tag{5}
$$
優化問題就變成了如何求出$\alpha$和$W^t$,同樣對$\alpha$求梯度且令梯度為0,可以得到$\alpha$的解析解,求出來的$W^t$和$\alpha$是相互關聯的,所以無法直接得出,文章就提出了一種量化方法,首先需要一個閾值$\Delta$,這個閾值用來區分浮點權值對映到正負1、0上,如公式6。然後求出的$\alpha_{\Delta}^{*}=\frac{1}{|I_{\Delta}|}\sum_{i\in\Delta}|W_i|$。
$$
W_i^t=
+1, \:\:\:if\:\: W_i > \Delta \\
0, \:\:\:if\:\: |W_i| \leq \Delta \\
-1, \:\:\:if\:\: W_i < -\Delta \tag{6}
$$
求閾值則無法直接去求解,因此假設權重服從幾個分佈來分析這個閾值的求解途徑,例如假設權重服從均勻分佈[-a,a],閾值$\Delta=1/3*a$,例如服從高斯分佈,閾值$\Delta=0.6\sigma$,所以作者歸納出了一個經驗公式用於求解$\Delta^{*}=\frac{0.7}{n}\sum_{i=1}^n|W_i|$,然後求出對應$\alpha$。訓練網路的方式與之前的文章一致。
TWN的主要貢獻通過2bit來近似浮點權重,相比於二值權重效能有較明顯的提升,但由於取值也限於正負1和0,對硬體計算沒有額外的負擔。
BWNH
[5]認為量化的過程可以看成一個hash對映,目標就變成了交替優化方法來學習雜湊碼。
在之前文章中的量化優化問題都是找到最優的量化數值來擬合浮點數值,本文中考慮的是最小化內積的量化誤差。本文中是將權重量化到1bit,內積指的是權重和啟用值之間相乘,也稱為輸入X和權重W的相似性矩陣$S=X^TW$,將浮點權重對映到量化權重的雜湊函式為$B=g(W)$,雜湊函式$X=h(X)$,h是恆等對映函式。
$$
minL(B)=||X^TW-X^TB||_F^2\:\:\:s.t. B\in\{+1,-1\}^{S\times N}\tag{7}
$$
$g(W)=BA$,A是對角矩陣,每個元素是一個scaling factor,所以目標函式也可以寫成$minL(A,B)=\sum_i^N||S_i-\alpha_i\cdot X^TB_i||_F^2$,計算每個$\alpha$、輸入、二值權重之間的乘積來擬合浮點權重與輸入乘積,要求的是雜湊對映g,將浮點權重對映到正負1、0這樣的hash code上。
此處對A和B求梯度設為0,可以推匯出帶有輸入資料關於$\alpha$和B的求解公式8,在更新A時將B固定不動,更新B時固定A不動,且更新每一個B時還要固定剩下的B,即通過這種交替優化的方式來進行更新。且由於二值權重的量化error是網路層與層從頭到尾一直在累加的,因而考慮分層量化,例如先對前l個層做二值化,讓整個網路逐漸的適應二值權重,再去量化第二個部分。
$$
\alpha_i = \frac{S_i^TX^TB_i}{||X^TB_i||_F^2} \\
b=sign(q_j-B_i^{‘T}Z^{‘}v) \tag{8}
$$
在具體演算法流程中,逐層的對每一層的權值做二值化,每一層量化時初始化時B取浮點權重的符號,而A取權重平均絕對值,接著就按照公式8進行交替的優化A和B。最後再對整個網路進行finetuing。
BWNH只對權重進行了量化,演算法主要貢獻在於從雜湊角度來解決量化問題,並且提出了逐層的交替更新,相對於之前的二值權重量化方法效能有著較為明顯的提升。
FFN
FFN[16]中只將浮點權重量化到2bit,通過定點化分解方式來求解量化後權重,由於三值權重只有正負1和0,即可以消除最耗費資源的multiply-accumulate operations(MAC)操作,FFN可以得到浮點網路效能相當的網路,且乘法運算僅為浮點網路的千分之一。
通過semidiscrete decomposition(SDD)半離散分解將浮點權重W分解成定點化方式$W=XDY^T$,中D是一個非負對角矩陣,X和Y每個元素取值為{-1,0,1},所以一個正常的卷積n*c*h*w會被分解成三個步驟,卷積有n個輸出channel,拆成三個後,第一個可看成有k個輸出channel的卷積,即k*c*h*w,第二個步驟相當於每個特徵圖都乘以一個尺度因子,最後一個也可以看成卷積層大小是n*1*1*k。

為了更好的恢復浮點權重,演算法中保留了X和Y對應的浮點數值$\hat{X}$和$\hat{Y}$,且浮點數值被限制在-1.5~1.5,根據取值落在哪個區間量化到哪個數值,而在梯度更新時,更新的物件是$\hat{X}$和$\hat{Y}$。
FFN只針對權重做了量化,提出了將浮點權重矩陣用矩陣分解的方式分解成三個簡單矩陣,其中兩個矩陣元素取值為正負1和0,從而間接完成量化的功能。
INQ
INQ[17]提出增量網路量化方法,通過權重分組、按組量化、重新訓練三個操作將浮點網路量化到低bit網路,在resnet18上量化權重後,4bit、3bit、2bit能夠達到甚至超過浮點權重。
文章從網路剪枝演算法中得到靈感,逐步的從已經訓練好的網路中移除掉不那麼重要的權重,最終效能也不會有明顯下降,所以說權重是存在不同的重要性的,但是之前的方法沒有考慮到這點,而是同時將高精度浮點數轉化為低精度數值,因此改變網路權重的重要性對於減少量化網路的損失很重要。
本文中低bit權重需要一個符號位,至少從2bit開始,b是位元數,取值範圍是$P_l={\pm 2^{n_1},…,\pm 2^{n_2},0}$,由兩個整數n1n2定義$n_2 = n_1+1-\frac{2^{b-1}}{2}$,通過經驗公式可以計算出n1n2。量化公式9中的$\alpha$和$\beta$就是$P_l$中相鄰的兩項。
$$
\hat{W_l}(i,j)=\beta sgn(W_l(i,j)) \:\:\:\: \text{if}(\alpha+\beta)/2\leq abs(W_l(i,j))< 3\beta/2 \\
0, otherwise \tag{9}
$$
網路訓練過程中,將權重分割到兩個不相交的組中,第一個組$A_l^{(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={W_1,…,W_m}$,其中m等於輸出channel數量,第i個filter權重是$W_i$。也是將這一層的權重劃分成兩個不相交的集合$G_q$和$G_r$,將$G_q$中權重量化到低bit,而$G_r$權重還是浮點,$G_q$有$N_q=r*m$個filter,而$G_q$有$N_q=(1-r)*m$個。其中r就是隨機量化SQ比例,r在逐漸增加,最終增加到1。
針對每一個filter$W_i$都有自己的一個量化概率$p_i$,表明第i個filter被量化的概率,量化概率的取值由量化誤差決定。當量化誤差小時,量化當前的這個channel就會造成較少不同的資訊損失,那麼就能給這個channel賦予較大的量化概率。首先定義浮點權重和量化權重的L1距離$e_i=\frac{||W_i-Q_i||_1}{||W_i||_1}$,將它作為量化誤差,並定義一箇中間變數$f_i=\frac{1}{e_i+\epsilon }$,從而量化概率可以有不同的求解方法,例如$p_i=1/m$或者$p_i=\frac{1}{1+exp(-f_i)}$。

在圖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=\frac{nb}{nlog2(k)+kb}$。通過k-means聚類來確定這些用於共享的權重,將n個權值分配到k個類中,最小化權重和類中心絕對值之差(WCSS)得到類中心$C={c_1,…,c_k}$。嘗試了三種初始化共享權重中心C的方法,隨機、基於密度、線性初始化,隨機方法就從權重中隨機選擇k個值,基於密度會選擇一些在尖峰周圍的點,線性初始化在權重數值線性進行間隔選擇,發現線性初始化效果最好。反向傳播也跟其他量化方式是一致的。
huffman編碼是一種無損資料壓縮方法,壓縮非均勻分佈的值可節省20%~30%的網路儲存。最終經過這三個操作,網路在效能沒有降低的情況下被壓縮了35x~49x。
這篇文章操作較多比較複雜,但是效能是穩定可靠的,每個壓縮操作都沒有導致效能下降。
TTQ
TTQ[8]量化浮點權重到三值權重,在開源資料集上相比浮點效能下降很少。
在之前的量化演算法中,是通過一個尺度因子和三值權重相乘來擬合浮點權重,像在TWN中給出了經驗公式來計算尺度因子$\alpha$,本文提出了通過梯度下降對$\alpha$進行更新。
首先將浮點權重除以最大值後正則化到正負1之間,所有的層有一個相同的引數t,用來計算閾值$\Delta_l = t \times max(|\tilde{w}|)$進行量化。
$$
w_l^t=W_l^p:\tilde{w}_l>\Delta_l \\
0:|\tilde{w}_l|<\Delta_l \\
-W_l^n:\tilde{w}_l<-\Delta_l \tag{10}
$$
這裡針對正負數有不同的量化levels,即有兩個尺度因子$W_l^p$和$W_l^n$。因此對它們計算梯度可以得到梯度下降更新公式,$\frac{\partial L}{\partial W_l^p} = \sum _{i\in I_l^p}\frac{\partial L}{\partial w_l^t(i)},\frac{\partial L}{\partial W_l^n} = \sum _{i\in I_l^n}\frac{\partial L}{\partial w_l^t(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中權重量化方式為$r_o = f_w^k(r_i)=2quantize_k(\frac{tanh(r_i)}{2max(|tanh(r_i)|)}+\frac{1}{2})-1$,其中k是指定的bit數,$f_w^k(r_i)$取值被限制在了-1~1之間。
啟用值的量化先是由一個啟用函式將範圍限制在0~1之內,再量化到k bit,$ f_a^k(r)=quantize_k(r)$。
在針對梯度進行量化時,隨機量化是一個比較有效的手段,且梯度是不像啟用值可以被限制在某個範圍內,有的位置上梯度取值可能會比較大,啟用值由於可以經過一個啟用函式,所以能夠限制數值大小。梯度量化公式為$ f_\gamma ^k(dr)= 2max_0(|d_r|)[ quantize_k[\frac{d_r}{2max_0(|d_r|)}+\frac{1}{2}+N(k)]-\frac{1}{2}]$,本文的隨機就體現在加入了一個額外的噪聲函式$N(k)$,效果非常明顯。
所以DoReFa-Net並不是指定量化到多少bit,而是可以量化到任意的bit,由於整個網路的輸入資料層channel較少,對於整體網路複雜度影響較小,因此第一個卷積層的權重不進行量化,第一個卷積層的輸出啟用值會被量化,如果輸出類別較少時,最後一個卷積層的權重也不進行量化,最後一層的反向梯度需要量化。
這篇文章主要就是提出對梯度也進行量化,並且支援量化到任意bit。
ABC-Net
二值權重和啟用值能夠很大程度的減少記憶體空間,且能採用按位計算,對硬體很友好,但是現有的方法會導致效能下降,本文主要提出了ABC-net(Accurate-Binary Convolutional)線性組合多個二值權重基來擬合浮點權重,利用多個二值啟用值基組合來減少資訊損失。
將浮點權重用M組二值權重和尺度因子進行線性組合,$W\approx \alpha_1 B_1+\alpha_2 B_2+…+\alpha_M B_M$,將B表示成浮點權重與均值和方差的組合形式$B_i = F_{u_i}(W):=sign(W-mean(W)+u_istd(W))$,其中有一個尺度變數$u_i$,既可以由經驗公式$u_i=-1+(i-1)\frac{2}{M-1}$直接算出,也可以通過網路訓練的方式得到。這樣去估計B的原因是,浮點權重傾向於是一個對稱、非稀疏分佈,比較類似高斯分佈,所以用均值和方差來估計。確定B之後,通過線性迴歸來求解alpha。在增加了尺度因子後,求解反向梯度時,會增加一個$\alpha$係數,$\frac{\partial c}{\partial W} = \sum_{m=1}^{M}\alpha_m\frac{\partial c}{\partial B_m}$。在實現中,將浮點權重按照channel區分開,用同樣的方式來估計尺度因子和二值權重,理論上能夠更加細緻的擬合浮點權重。
當權重是二值的,卷積操作就沒有了乘法,只剩下加減,如果想要更高效的利用按位操作,最好是將啟用值也變為二值。因此類似對權重的處理,文章首先將啟用值通過一個clip函式$h_v(x)=clip(x+v,0,1)$,將範圍限制在0~1之間,量化啟用值取值是{-1,1},通過一個指示函式$A=H_v(R):=2\mathbb{I}_{h_v(R)\geq 0.5}-1$進行量化,量化啟用值與量化權重的不同點在於,inference的階段權重是不變的,啟用值則變化了,但是通過利用神經網路啟用值的統計特效能夠避免這個問題,為了保證啟用值的分佈相對穩定,使用了batchnorm,它能夠讓輸出保持0均值1方差的分佈。用N組二值啟用值和尺度因子組合成浮點啟用值$R\approx \beta_1A_1+\beta_2A_2+…+\beta_NA_N$,啟用值量化中多了一個可以訓練的閾值$v$。卷積操作就轉化M*N個按位操作,$Conv(W,R)\approx \sum_{m=1}^{M}\sum_{n=1}^{N}\alpha_m\beta_nConv(B_m,A_n)$。
ABC-Net也是一個不限制bit數的量化演算法,效能也接近浮點網路。
HWGQ
HWGQ[11]主要針對啟用值量化,利用了啟用值的統計特性和batchnorm操作,在前向計算時能有效的近似浮點值的效能。
針對啟用值的量化需要處理不可微的操作,主要切入點在於ReLU函式,神經網路每個單元都計算了一個啟用函式,即權重與輸入相乘後經過一個非線性變換,這個操作的多少決定了整個網路的複雜度。
本文中估計1bit量化權重,也是基於二值權重和尺度因子相乘去擬合浮點權重,輸入I與量化權重卷積來近似I和浮點權重卷積結果,是二值權重取浮點權重的符號$B^*=sign(W)$,尺度因子是浮點權重平均絕對值$\alpha^*=\frac{1}{cwh}||W||_1$,1bit權重能夠減少儲存空間,但是無法完全計算複雜度的問題,如果將I也變成二值的,則能夠最大程度上解決計算複雜度的問題。
在對啟用值進行量化時,如果直接按照符號函式來定義量化levels,那麼對量化啟用值進行求導時,導數處處為0,所以有人提出,對符號函式求導如果輸入絕對值小於1則梯度為1,其他位置取0。結合relu函式,本文對啟用值量化的目標是擬合relu函式的輸出。quantizer是一個分段常數函式,量化levels就是量化到的值,量化step就是兩個量化level之間的差,針對每個浮點數值,它只需要儲存一個索引值i,對應到第i個量化level,非均勻量化情況下表達浮點權重需要多餘$log_2m$的bit數,如果是均勻量化則$log_2m$個bit就夠了。啟用值的統計結構傾向於對稱非稀疏分佈類似高斯分佈,再結合relu,就是變成了一個半波高斯量化子half-wave Gaussian quantizer。這裡的量化就是變成了求針對高斯分佈的量化levels和step,但是在不同層的神經元所得到的類高斯分佈,它們的均值方差不一定是相同的,為了得到相同的資料分佈,通過batchnorm來得到0均值1方差的分佈,然後就能在神經元之間得到均勻的量化引數。以上是在解釋構造這樣的HWGQ,它是階梯常數函式,梯度處處為0,目標就變成了選哪個函式作為HWGQ在量化後才能最好的擬合relu函式的效果。
首先考慮最基本的relu函式,它對輸入的梯度等於輸出梯度,與正向的HWGQ所需要的梯度是不匹配的,特別是當輸入數值大於最大的量化level時,產生的誤差導致的反向梯度就會特別大。基於這個情況,考慮用clipped後的relu,保證最大值不超過最大的量化level,但是由於clipped的操作,丟失掉了$q_m$之後的輸入資訊會直接導致效能的下降,因此提出一種折中的函式公式11即長尾relu,它既能保證超過$q_m$的梯度不會過大,也不會完全丟失掉大於$q_m$的資訊。
$$
\tilde{Q_l}(x)=q_m+log(x-\tau ),x>q_m \\
x,x\in (0,q_m] \\
0,x\leq 0 \tag{11}
$$
HWGQ主要從理論上分析如何去選擇一個啟用函式,從而保證啟用值量化後低bit網路效能接近浮點網路。
Network Sketching
本文提出了Network Sketching[19]用來尋找量化二值權重的網路,整個過程可以看成是由粗到細的模型近似。
按照輸出channel來劃分不同的filter,假設有m組基來擬合一個channel的權重,$W=\sum_{m=0}^{m-1}\alpha_jB_j$,其中$B\in \{+1,-1\}^{c\times w\times h\times m}$,而$\alpha \in \mathbb{R}^m$。主要想法是基於不斷擬合量化權重和浮點權重之間的殘差,即計算浮點權重減去已經累加得到的量化權重$\sum_{k=0}^{j-1}\alpha_kB_k$之間的殘差成為新的需要擬合的浮點權重,去獲得下一步的B和$\alpha$,即公式12。
$$
\hat{W_j}=W-\sum_{k=0}^{j-1}\alpha_kB_k \tag{12}
$$
具體在求B和$\alpha$,B是取浮點權重的符號,$\alpha$由二值權重和浮點權重內積求出來$\alpha_j=\frac{ < B_j,\hat{W_j} > }{t}$,其中$t=c\times w \times h$。在第一個Direct Approximation演算法中就是重複m次,求出m組B和$\alpha$。重構error以1/t的指數進行衰減,如果t取值小,重構error就會越小,t很大時,重構error的減少幅度就會很慢,就算增加m的數量,最終的近似效果可能也不夠好。所以B和$\alpha$不一定是最優的,為了進一步優化得到更好的近似效果,在第二個Approximation with Refinement演算法中給出更新公式,$a_j=(B_j^TB_j)^{-1}B_j^T\cdot vec(W)$,且文中進一步證明了更新公式能夠近似浮點權重,減少量化error。
本文的sketch就體現在第j個量化權重是在估計當前浮點權重的殘差,量化error越來越精細,就像在逐步的從粗到細描繪出具體的輪廓。
PQ+TS+Guided
本文[20]為了提升量化網路訓練效能,提出了三個方法,一是兩步優化策略,先量化權重再量化啟用值,其次在訓練過程中逐步減少量化位寬,第三聯合訓練浮點網路和低精度網路。
量化採用的是Q函式均勻量化,$z_q=Q(z_r)=\frac{1}{2^k-1}round((2^k-1)z_r)$,在量化權重時,先對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},二值化或者三值化權重時通常的方法是採用分段常數函式,並存在$\eta$這樣的量化閾值超引數,二值化時取為0,三值時由經驗公式$\eta=0.05\times max(|W_l|)$得出。後來的估計方式中引入了scaling factor,提高了近似浮點數的能力,此時的codebook就變成了${-\alpha,\alpha}$,前面提到過的TTQ就是提出可以對$\alpha$進行訓練,且設定正負兩個尺度因子${-\alpha_l^n, \alpha_l^p}$,但是如果採用正負不同的尺度因子,那麼在計算權重和啟用值乘積時需要先去判斷當前二值權重或者三值權重的符號,增加了額外的判斷分支,所以本文認為對稱的codebook計算效率會更高,codebook最好是在0周圍對稱,那儲存空間可減半。
很多細粒度量化方法能夠提升近似權重分佈的能力,本文實現了按畫素進行縮放,假設一層權重是$K\times K \times N \times I$,pixel-wise就是在I*N維度上將權重進行分組,此時$\alpha$個數為$K^2$,此時就是將權重分為了$K^2$組,row-wise將一個kernel中行或者列組成一組,最粗粒度的是layer-wise,一層只有一個$\alpha$。
在SYQ演算法流程中,每一層首先通過$Q_l=sign(W_l) \bigodot M_l$量化權重成二值或者三值,其中$M_l$是通過$\eta$計算得到,然後通過$G(x)=\frac{1}{2^f}floor((2^f)x+\frac{1}{2})$線性量化啟用值,前向計算完成之後,通過$\frac{\partial E}{\partial W_{l_{i,j}}} = \alpha_{l}^i\frac{\partial E}{\partial Q_{l_{i,j}}} $來更新權重,通過$\frac{\partial E}{\partial x} = \frac{\partial E}{\partial G} $更新啟用值,通過$\frac{\partial E}{\partial \alpha_{l}^i} = \sum_{j\in S_l^i} \frac{\partial E}{\partial W_{l_{i,j}}}$更新scaling factor。
SYQ相對於TTQ沒有特別明顯的改進,增加了$\alpha$的數量使得最終效能想比於TTQ有提升。
TSQ
之前方法中都是同時量化權重和啟用值,TSQ[12]提出了先量化啟用值再量化權重,針對啟用值,提出了稀疏量化方法,文章認為網路壓縮和加速中稀疏能起到很大作用,之前的文章中都很少研究這個方向,且稀疏性在特殊硬體上會更有效,而權重量化可以看成低bit非線性最小二乘迴歸問題,通過迭代方式求解。
得到低位元權重是transformations,得到低位元啟用值是encodings。在encodings問題中,Relu函式本身就產生了50%的稀疏性,在attention機制的基本假設中,數值較大的啟用值比數值較少的啟用值更重要。所以將數值較小的正值變成0,這樣量化演算法能夠更能關注到較大的數值,量化的會更精細。n-bit均勻量化子quantizer將浮點啟用值對映到$2^n$個離散值,主要就是在於決定量化間隔$\Delta$和量化範圍$t_i$。之前的HWGQ方法中是通過batchnorm層,輸出分佈就非常趨近於0均值1方差的高斯分佈,因此每個層的$\Delta$和$t_i$是相同的。本文提出稀疏量化,不是將經過relu後的所有正值都進行量化,而是將不重要的數值先設定為0再量化,這個想法之前在網路剪枝中也有類似研究,也就是大值比小值更重要。所以給出了一個稀疏閾值$\epsilon$,得到新的求解啟用值量化函式的公式13。
$$
Q_{\epsilon}^*(x)=\underset{Q_{\epsilon}}{argmax}E_{x\sim N(0,1),x>\epsilon }[(Q_{\epsilon}(x)-x)^2] \tag{13}
$$
對權重進行量化,假設上一層的輸出是X,這一層的輸出是Y,將權重量化的問題變成一個非線性最小平方迴歸問題,將浮點尺度因子$\alpha$看成一個對角矩陣,與輸入X相乘之後再經過啟用值量化最終去擬合浮點輸出$\underset{\alpha,\hat{w}}{minimize} || y - Q_{\epsilon }(\alpha X^T\hat{w}) ||$。然後引入了一個輔助變數z,將兩個量化過程區分開$\underset{\alpha,\hat{w},z}{minimize} || y - Q_{\epsilon }(z) | | +\lambda || z - \alpha X^T\hat{w} ||$,權重量化去擬合輔助變數z,啟用值量化去擬合浮點輸出。
在求解$\alpha$和w時,將優化問題展開之後,對$\alpha$進行求導且設定導數為0,可以直接得出$\alpha$的求解公式,然後將$\alpha$帶入展開公式同樣求出w的求解公式。由於w的維數較高,即m個畫素點每個都需要進行計算,而每個可能取值又是2^n個bit,所以如果用窮舉法來找到最優的w是不可行的,還是在求解一個w時,固定剩下的w不變。在求z時,此時$\alpha$和w是確定的,且此處將啟用值量化函式條件放寬,在0~M範圍內的數值就不進行量化,所以針對不同分佈得到了z的求解方式。
對權重量化時,層與層之間可以同時進行,沒有耦合關係,但是獨立進行量化時,量化誤差會在層與層之間累加,所以還是考慮通過按層量化。
TSQ通過稀疏量化啟用值和引入一箇中間變數z來產生新的量化方法,在alexnet上將權重啟用值都量化到2bit時效能與浮點也是一致的。
LQ-Net
LQ-Net[13]目的是希望學習量化任意bit權重和啟用值的quantizers,現有的量化方法都是一種人工設計的quantizers,例如均勻量化、對數量化,或者在網路訓練之時已經計算好的quantizers(HGWQ),如果針對不同的網路能自適應的學到不同quantizers,效能應該會有所提升,所以本文就想聯合訓練一個量化的DNN網路和對應的quantizers。
$q_l$是量化levels,量化intervals指的是$t_l$到$t_{l+1}$,浮點值在$t_l$到$t_{l+1}$範圍內的會被量化到$q_l$,均勻量化就是指每個$t_l$到$t_{l+1}$的範圍都是相同的,對數量化是$t_l$到$t_{l+1}$的範圍成指數關係,量化到n-bit,就有32/n或者64/n倍的壓縮比例。但是由於每個卷積層的資料分佈的不同,均勻量化不一定是最優的,預先設定好的量化方式也不一定是最優的,所以考慮既訓練整個量化網路,也訓練量化函式。如果量化函式是可以訓練的,那麼它不僅能夠減少量化誤差,也能適應整體的訓練目標提升最終效能。
假設網路被量化到K-bit,一個整數q可以通過一個k維的basis係數向量v和k個bit的二值編碼向量$e_l$點積表達,如公式14所示,此處的係數向量取值為整數。
$$
q=<\begin{bmatrix}
1\\
2\\
…\\
2^{K-1}\\
\end{bmatrix},
\begin{bmatrix}
b_1\\
b_2\\
…\\
b_K\\
\end{bmatrix}> \tag{14}
$$
由於二值編碼向量$e_l$裡面每個元素取值都是0和1,當k確定之後$e_l$所有取值可能都可以確定,例如K=2,$e_l$所有可能為{(-1,-1),(-1,1),(1,-1),(1,1)}。v是一個可學習的浮點basis係數向量,v值確定之後和每一組可能的二值編碼向量相乘$q_l=v^Te_l$,得到了一系列的量化levels,量化intervals就是兩個level之間的均值。
對權重和啟用值都進行相同的量化操作,卷積就變成了$Q_{ours}(w,v^w)^TQ_{ours}(a,v^a)=\sum_{i=1}^{K_w}\sum_{j=1}^{K_a}v_i^wv_j^a(b_i^w\odot b_j^a)$,其中有兩組要學習的引數,分別是$v_w$和$v_a$,同一層的啟用值量化共用一個$v_a$向量,一層權重對應每個輸出channel用一個$v_w$向量。
在量化和更新過程中,在訓練開始之前通過一個經驗公式求出初始的v,然後先固定v更新B,此時v是已知的,可以直接計算出所有levels,對比浮點數x落在哪個區間就量化到對應的B。然後固定B更新v,通過最小化量化誤差$\underset{v,B}{argmax}||B^Tv-x||_2^2$對v求閉式解$v^*=(BB^T)^{-1}Bx$來更新當前的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
[7] DEEP COMPRESSION: COMPRESSING DEEP NEURAL NETWORKS WITH PRUNING, TRAINED QUANTIZATION AND HUFFMAN CODING
[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] CVPR_2018_paper.pdf" target="_blank" rel="nofollow,noindex">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