INQ漸進式神經網路量化-論文筆記
3 人贊了文章
沒用的開場白
深度學習已經在計算機視覺、語音識別和NLP等領域取得重大突破,但仍存在很多問題。深度神經網路包含數千萬甚至更多的學習參數,這就給神經網路模型在存儲、計算和功耗開銷等方面帶來諸多考驗,所以深度神經網路的量化壓縮也變得越來越重要。
最近準備好好整理一下神經網路壓縮和量化方面的論文和方法,那就從知乎開始,記錄自己這個生澀小白的論文學習筆記吧。可能有一些理解不對的地方,還請大家多多來批評指正。希望自己可以堅持!加油!
準備準備
- 先獻上論文鏈接和源碼:
論文鏈接:https://arxiv.org/abs/1702.03044
項目源碼:https://github.com/Zhouaojun/Incremental-Network-Quantization
- 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的整數次冪,一是可以用移位操作代替乘法,二是量化後的權值可以通過編碼來存儲(壓縮嵌入式設備上的模型存儲大小)。
創新點
- 以往的量化方法會導致壓縮型網路出現準確率下降過多的問題,而INQ方法通過以下兩個創新點,能有效解決這個問題:
1. 網路生成由三個相互依賴的操作組成,即參數分組(權值分割)、分組量化、再訓練。每一層的權重被分成兩組,一組被量化,另一組再訓練以補償第一組量化帶來的精度損失。
2. 以上三個操作不斷迭代訓練網路,直到所有的權重都被壓縮。
- 該技術有兩個很重要的亮點:
1. 在模型量化過程中,所有參數被限制成二進位表示,量化後都是2的指數次冪或0,這樣的量化使得最後的模型非常適合在硬體上部署和加速。比如在FPGA上,複雜的全精度浮點乘法運算將被直接替換為簡單的移位操作。
2. 為減小模型的精度損失,現有的神經網路量化壓縮方法在處理二值網路或三值網路時,一般會將第一層和最後一層的參數保留為全精度浮點型,而INQ方法不僅對模型的所有參數進行了量化,而且也實現了性能的全面領先。
演算法
前提:得到一個預訓練好的全精度網路模型,模型已收斂。
- 將每一層的參數分為2組(第1組直接進行量化並固定;第2組需要重新訓練以彌補第一組量化後給模型帶來的精度損失)。
- 對第1組的權值進行量化,量化成2的冪次方或者0。
- 將量化後的權值矩陣進行重新訓練,更新第2組的權值來彌補第一組量化後帶來的精度損失。最新重訓練的權重組以迭代方式進行,直到所有的權值都被量化。
- 重複上述步驟,應用到完成重訓練後的全精度浮點參數部分,直到所有的權值都被量化。
通過參數分組、量化和重訓練操作,最終得到漸進式的量化和精度提升。該技術抑制了模型量化造成的性能損失,從而在實際中適用於任意結構的神經網路模型。
具體實現
- Weight partition
文中介紹了兩組分組方式:random strategy和pruning-inspired strategy。
- 隨機策略:隨機把權重分成兩個不相交的部分,即以相等概率分成兩組。
- 基於prune的策略:逐層確定每層的thresholds(一般是given splitting ratio),取weights的絕對值和thresholds比較,最後分成兩個不重疊的組,即一組大值,一組小值。
INQ這篇論文中選擇的是第2種:基於prune的策略,當然選擇這種策略是比較合適的。它是把權重大的分為一組,權重小的分為一組。
我們要量化的是絕對值大的那一組參數,因為絕對值大的權重更重要(這是為什麼呢?因為絕對值大的權重奠定了網路的整體精度的基礎,絕對值較小的權重是在此基礎上進行微調)。
所以,將這些具有較大絕對值的權值劃分到待量化的那組權值矩陣中,具有較小絕對值的那組權值用來進行重訓練。
對於第 層來說,權重分組可以被定義為:
其中, 代表需要被量化的那一組權重, 代表需要被重新訓練的那一組權重。
論文中,定義了一個二值矩陣 來區分兩組權重類別(為更好地實現這個分組演算法),即:
表示
表示
- Quantization encoding
首先假定一個預訓練的全精度(32位浮點數)CNN模型可以表示為
其中, 表示 層的權重集,L表示模型中可學習的層數。
為簡化解釋,這裡僅考慮卷積層和全連接層。對論文中所用到的AlexNet、VGG-16、GoogleNet及ResNets等CNN網路來說, 就是卷積層中的4D張量 ( )或全連層中的2D矩陣。為簡單起見,這裡不考慮表達式中的維數差異。
給定一個預訓練的CNN模型,INQ的主要目標是把所有的32位浮點權重轉化為2的整數次冪或0,而且要保證不損失模型精度。
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
下面開始介紹論文中所採用的量化形式
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
1. 將 量化成低精度的 ,其中 的每個元素都來自:
={ , , , 0}
其中, 和 都是整數,且 。
這兩個值結合到 中來說,其意義就在於:非零元素限制在 或者 之間。也就是說在最後的低精度網路模型中,絕對值小於 的權重就會被修剪掉(即設為0)。
顯然,關鍵問題在於如何確定 和 。在 和 間取2的指數,這樣處理的目的就是為了在FPGA等平台上使用。
2. 論文所提的INQ方法中,位寬 b 是我們根據要求提前設定的值。因此,只有 這一個超參數需要被設置。因為一旦b和 知道了之後, 自然就可以被計算出來。
通過以下公式計算:
,表示向下取整。
s 通過以下公式計算:
,s 是每個kernel值的絕對值的最大值。
一旦 得到之後,結合設置的 b , 就可以通過 被計算出來。比如 , 則 (上述公式中的 b-1 是為了單獨用1位來保存 0 ,除以 2 是因為存在正負數)。這樣 被確定下來了。
3. 確定了之後,就可以進一步通過下面的公式將 量化為低精度的值 :
otherwise
其中, 和 是 中排序後的兩個相鄰的元素。量化規則其實是非常常規的,即被量化的那個數距離 中最近的那個數就是最後的量化值。
如果一個權重 W 被量化為 ,則這個數到 中 的前一個數和後一個數的距離就都比 大,怎麼度量呢? 就是:
而 ,所以上述條件可以寫成 :
。
這個式子乘以 ,得到的區間就是在 和 之間了,這就說明了 是怎麼來的了。
- 重訓練Re-train
INQ重訓練的目的就是最大程度上減少由量化造成的精度損失,即:
其中, 是由前面的分組量化所確定的取值; 是一個mask的二值矩陣,代表每一步權重的分組: 表示已經量化的部分, 表示需要retrain的部分。
在重新進行訓練時,只更新retrain部分(即 的部分),對應的部分還是保持32位全精度浮點數。
使用SGD演算法更新權值可以表示如下:
當 需要量化的話,,否則 ,因此從上面的式子可以知道:權重更新只更新需要重新訓練的權值。
整體演算法
代碼解讀
- 計算 : blob.cpp
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