INQ漸進式神經網路量化-論文筆記

INQ漸進式神經網路量化-論文筆記

3 人贊了文章

沒用的開場白

深度學習已經在計算機視覺、語音識別和NLP等領域取得重大突破,但仍存在很多問題。深度神經網路包含數千萬甚至更多的學習參數,這就給神經網路模型在存儲、計算和功耗開銷等方面帶來諸多考驗,所以深度神經網路的量化壓縮也變得越來越重要。

最近準備好好整理一下神經網路壓縮和量化方面的論文和方法,那就從知乎開始,記錄自己這個生澀小白的論文學習筆記吧。可能有一些理解不對的地方,還請大家多多來批評指正。希望自己可以堅持!加油!

準備準備

  • 先獻上論文鏈接和源碼:

論文鏈接:arxiv.org/abs/1702.0304

項目源碼:github.com/Zhouaojun/In

  • INQ簡介(前言(⊙﹏⊙)啰嗦話)

Incremental Network Quantization: Towards Lossless CNNs with Low-precision Weights(INQ神經網路無損低比特量化技術),是發表在ICLR2017上的一篇會議論文。

這是英特爾中國研究院針對現有問題而提出的一種新型的量化技術,極其有效地解決了現有方法泛化能力不足,模型精度損失明顯,以及重訓練時間長等問題,為深度神經網路在定製化硬體上的部署、加速等開闢了新的途徑。

以下是分割線:↓↓↓↓↓↓↓↓↓↓↓↓


思想

INQ提出了漸進式神經網路量化的思想(核心:參數分組、量化、重訓練)。

1. 只要給定任意結構的全精度浮點神經網路模型,如:AlexNet、VGGNet、GoogleNet和ResNets等,INQ都能夠有效地將其轉換成無損的低比特二進位模型。

2. 輸入是已經訓練好的任意全精度(即32位浮點數)CNN網路,輸出是量化後的低精度權值,即權值為2的整數次冪或0的網路。

注意:

1. 這裡的低精度指的是:相鄰兩個權值間的個數少( 2^{-2}、2^{-3} ),都是2的整數次冪,中間並沒有其他數值的權值。就如同刻度尺的精度一樣。

2. 權值量化後為2的整數次冪,一是可以用移位操作代替乘法,二是量化後的權值可以通過編碼來存儲(壓縮嵌入式設備上的模型存儲大小)。

創新點

  • 以往的量化方法會導致壓縮型網路出現準確率下降過多的問題,而INQ方法通過以下兩個創新點,能有效解決這個問題:

1. 網路生成由三個相互依賴的操作組成,即參數分組(權值分割)、分組量化、再訓練。每一層的權重被分成兩組,一組被量化,另一組再訓練以補償第一組量化帶來的精度損失。

2. 以上三個操作不斷迭代訓練網路,直到所有的權重都被壓縮。

  • 該技術有兩個很重要的亮點:

1. 在模型量化過程中,所有參數被限制成二進位表示,量化後都是2的指數次冪或0,這樣的量化使得最後的模型非常適合在硬體上部署和加速。比如在FPGA上,複雜的全精度浮點乘法運算將被直接替換為簡單的移位操作。

2. 為減小模型的精度損失,現有的神經網路量化壓縮方法在處理二值網路或三值網路時,一般會將第一層和最後一層的參數保留為全精度浮點型,而INQ方法不僅對模型的所有參數進行了量化,而且也實現了性能的全面領先。

演算法

前提:得到一個預訓練好的全精度網路模型,模型已收斂。

  1. 將每一層的參數分為2組(第1組直接進行量化並固定;第2組需要重新訓練以彌補第一組量化後給模型帶來的精度損失)。
  2. 對第1組的權值進行量化,量化成2的冪次方或者0。
  3. 將量化後的權值矩陣進行重新訓練,更新第2組的權值來彌補第一組量化後帶來的精度損失。最新重訓練的權重組以迭代方式進行,直到所有的權值都被量化。
  4. 重複上述步驟,應用到完成重訓練後的全精度浮點參數部分,直到所有的權值都被量化。

(a) Pre-trained full-precision model (b) Model update with three proposed operations: weightpartition, group-wise quantization (green connections) and re-training (blue connections) (c) Finallow-precision model with all the weights constrained to be either powers of two or zero

通過參數分組、量化和重訓練操作,最終得到漸進式的量化和精度提升。該技術抑制了模型量化造成的性能損失,從而在實際中適用於任意結構的神經網路模型。

圖1 第一個圖中參數分為黑白兩組,黑色需要量化,白色需要重新訓練,經過量化和重新訓練之後的結果如第三個圖所示,綠色的為量化後的結果,灰色的需要進行分組、量化和重新訓練的操作。

具體實現

  • Weight partition

文中介紹了兩組分組方式:random strategy和pruning-inspired strategy。

  1. 隨機策略:隨機把權重分成兩個不相交的部分,即以相等概率分成兩組。
  2. 基於prune的策略:逐層確定每層的thresholds(一般是given splitting ratio),取weights的絕對值和thresholds比較,最後分成兩個不重疊的組,即一組大值,一組小值。

INQ這篇論文中選擇的是第2種:基於prune的策略,當然選擇這種策略是比較合適的。它是把權重大的分為一組,權重小的分為一組。

我們要量化的是絕對值大的那一組參數,因為絕對值大的權重更重要(這是為什麼呢?因為絕對值大的權重奠定了網路的整體精度的基礎,絕對值較小的權重是在此基礎上進行微調)。

所以,將這些具有較大絕對值的權值劃分到待量化的那組權值矩陣中,具有較小絕對值的那組權值用來進行重訓練。

對於第 l^{th} 層來說,權重分組可以被定義為:

A_{l}^{(1)}cup A_{l}^{(2)}= left{ W_{l}(i,j) 
ight}

A_{l}^{(1)}cap A_{l}^{(2)}= phi

其中, A_{l}^{(1)} 代表需要被量化的那一組權重, A_{l}^{(2)} 代表需要被重新訓練的那一組權重。

論文中,定義了一個二值矩陣 T_{l} 來區分兩組權重類別(為更好地實現這個分組演算法),即:

T_{l}(i,j)=0 表示 W_{l}(i,j)in A_{l}^{(1)}

T_{l}(i,j)=1 表示 W_{l}(i,j)in A_{l}^{(2)}

  • Quantization encoding

首先假定一個預訓練的全精度(32位浮點數)CNN模型可以表示為

{W_{l}: 1leq lleq L}

其中, W_{l} 表示 l^{th} 層的權重集,L表示模型中可學習的層數。

為簡化解釋,這裡僅考慮卷積層和全連接層。對論文中所用到的AlexNet、VGG-16、GoogleNet及ResNets等CNN網路來說,W_{l} 就是卷積層中的4D張量 (N*C*H*W )或全連層中的2D矩陣。為簡單起見,這裡不考慮表達式中的維數差異。

給定一個預訓練的CNN模型,INQ的主要目標是把所有的32位浮點權重轉化為2的整數次冪或0,而且要保證不損失模型精度。

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

下面開始介紹論文中所採用的量化形式

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

1. 將W_{l} 量化成低精度的 	ilde{W_{l}} ,其中 	ilde{W_{l}} 的每個元素都來自:

P_{l} ={ pm2^{n_{1}}, cdot cdot cdot, pm2^{n_{2}}, 0}

其中,n_{1}n_{2} 都是整數,且 n_{2}leq n_{1}

這兩個值結合到 P_{l} 中來說,其意義就在於:非零元素限制在 [-2^{n_{1}}, -2^{n_{2}}] 或者 [2^{n_{2}}, 2^{n_{1}}] 之間。也就是說在最後的低精度網路模型中,絕對值小於 2^{n_{2}} 的權重就會被修剪掉(即設為0)。

顯然,關鍵問題在於如何確定 n_{1}n_{2} 。在 n_{1}n_{2} 間取2的指數,這樣處理的目的就是為了在FPGA等平台上使用。

2. 論文所提的INQ方法中,位寬 b 是我們根據要求提前設定的值。因此,只有 n_{1} 這一個超參數需要被設置。因為一旦b和 n_{1} 知道了之後, n_{2} 自然就可以被計算出來。

n_{1} 通過以下公式計算:

n_{1}=floor(log_{2}(4s/3))floor(cdot)表示向下取整。

s 通過以下公式計算:

s=max(abs(W_{l})) ,s 是每個kernel值的絕對值的最大值。

一旦 n_{1}得到之後,結合設置的 b , n_{2} 就可以通過 n_{2}=n_{1}+1-frac{2^{b-1}}{2} 被計算出來。比如 b=3、 n_{1}=-1, 則n_{2}=-2 (上述公式中的 b-1 是為了單獨用1位來保存 0 ,除以 2 是因為存在正負數)。這樣 P_{l} 被確定下來了。

3. P_{l}確定了之後,就可以進一步通過下面的公式將 W_{l} 量化為低精度的值 	ilde{W_{l}}

	ilde{W_{l}(i,j)}=eta sgn(W_{l}(i,j)), if (alpha+eta)/2leq abs(W_{l}(i,j))<3eta/2

	ilde{W_{l}(i,j)}=0, otherwise

其中,alphaetaP_{l} 中排序後的兩個相鄰的元素。量化規則其實是非常常規的,即被量化的那個數距離 P_{l} 中最近的那個數就是最後的量化值。

如果一個權重 W 被量化為 eta ,則這個數到 P_{l}eta 的前一個數和後一個數的距離就都比 eta 大,怎麼度量呢? 就是:

(alpha+eta)/2leq abs(W_{l}(i,j))<3eta/2

alpha+eta=3eta/2 ,所以上述條件可以寫成 :

3eta/4leq abs(W_{l}(i,j))<3eta/2

這個式子乘以 4/3 ,得到的區間就是在 eta2eta 之間了,這就說明了 4/3 是怎麼來的了。

  • 重訓練Re-train

INQ重訓練的目的就是最大程度上減少由量化造成的精度損失,即:

min_{W_{l}}=L(W_{l})+lambda R(W_{l})

s.t. W_{l}(i,j)in P_{l} , ifT_{l}(i,j)=0, 1leq lleq L

其中, P_{l} 是由前面的分組量化所確定的取值; T_{l} 是一個mask的二值矩陣,代表每一步權重的分組: T_{l} =0 表示已經量化的部分, T_{l} =1 表示需要retrain的部分。

在重新進行訓練時,只更新retrain部分(即 T_{l} =1 的部分),對應的部分還是保持32位全精度浮點數。

使用SGD演算法更新權值可以表示如下:

W_{l}(i,j)leftarrow W_{l}(i,j)-gamma frac{dE}{dW_{l}(i,j)}T_{l}(i,j)

W_{l}(i,j) 需要量化的話,T_{l}(i,j)=0,否則 T_{l}(i,j)=1 ,因此從上面的式子可以知道:權重更新只更新需要重新訓練的權值。

整體演算法

表1 INQ演算法流程

代碼解讀

  • 計算 n_{1} : blob.cpp

n_{1}=floor(log_{2}(4s/3))

Dtype* data_copy=(Dtype*) malloc(count_*sizeof(Dtype)); caffe_copy(count_,data_vec,data_copy); caffe_abs(count_,data_copy,data_copy); //data_copy order from small to large std::sort(data_copy,data_copy+count_); //caculate the n1 Dtype max_data=data_copy[count_-1]; int n1=(int)floor(log2(max_data*4.0/3.0));

  • 權重分組量化:blob.cpp

//quantizate the top 30% of each layer, change the "partition" until partition=0 int partition=int(count_*0.7)-1; for (int i = 0; i < (count_); ++i) { if(std::abs(data_vec[i]) >= data_copy[partition]) //選取權重較大的30%進行量化 { data_vec[i] = weightCluster_zero(data_vec[i],n1); //weightCluster_zero為量化過程 mask_vec[i]=0; //權重量化的部分,mask設置為0,表示已進行量化,不進行權重更新 } }

  • 權重量化:power2.cpp

double weightCluster_zero( Dtype weight, int M) { double min=100; double ind=0; double flag=1.0; if(min>std::abs(weight)) { min=std::abs(weight); flag=0.0; } //此處代碼中的7其實對應的是paper中的5位 //b=5,n2=n1+1-power(2,b-1)/2,即n2=n1-7 for(int i=(M-7);i<=M;i++) //search最接近的量化值 { if(min>std::abs(weight-pow(2,i))) //表示權重為正 { min=std::abs(weight-pow(2,i)); ind=i; flag=1.0; //符號位標記 } if(min>std::abs(weight+pow(2,i))) //表示權重為負 { min=std::abs(weight+pow(2,i)); ind=i; flag=-1.0; //符號位標記 } } return flag*pow(2,ind); //返回量化後的結果 }

  • to be continue...

Experiments

論文中使用幾乎所有已知的深度CNN架構對ImageNet大規模分類任務進行了大量實驗,以驗證INQ方法的有效性:

(1)對於具有5位量化的AlexNet、VGG-16、GoogleNet和ResNets,INQ與其各自的基準原始全精度浮點模型相比,實現了更高的精度。

(2)以ResNet-18為例,在4比特和3比特條件下,INQ技術能夠做到無損量化。儘管在三值量化時,量化後的模型精度有少許損失,但損失程度遠低於目前業界已知的結果。

(3)將INQ技術與之前發表在NIPS 2016的DNS技術相結合,實現了深度的神經網路二進位量化壓縮。以AlexNet為例,首次實現了接近無損的、百倍級、二進位的神經網路模型。網路修剪和INQ的結合優於深度壓縮方法(Han et al。,2016)。

網路裁剪和INQ結合也有很好的效果,使用INQ有望使深度學習神經網路在移動或者嵌入式設備中得到應用。

未來的工作

未來可以進一步將INQ技術從只量化模型參數推廣到不但量化模型參數,還量化網路每一層的輸入和輸出。

推薦閱讀:

Path-Based Attention Neural Model for Fine-Grained Entity Typing
看別人買了LV 你也想買LV?鏡像神經元心智DNA 社會行為之神經基礎統一架構 改變了文明哲學語言和心理情感
RNN Part 3-Back Propagation Through Time and Vanishing Gradients(BPTT演算法和梯度消失)
機器學習論文筆記(二)Practical Block-wise Neural Network Architecture Generation
深度學習面試100題(第1-5題):經典常考點CNN

TAG:神經網路 | 量化 | 壓縮 |