1. 程式人生 > >深度學習中神經網路模型的量化

深度學習中神經網路模型的量化

深度學習神經網路模型中的量化是指浮點數用定點數來表示,也就是在DSP技術中常說的Q格式。我在以前的文章(Android手機上Audio DSP頻率低 memory小的應對措施 )中簡單講過Q格式,網上也有很多講Q格式的,這裡就不細講了。神經網路模型在訓練時都是浮點運算的,得到的模型引數也是浮點的。通常模型引數較多,在inference時也有非常多的乘累加運算。如果處理器的算力有限,在inference時用浮點運算將導致CPU load很高,極大影響效能。而且通常一個引數用浮點數表示佔四個位元組,而如果用8位元量化的話,一個引數只佔一個位元組,memory得到了極大的節約,在memory緊張的處理器上尤為重要。所以通常都要對神經網路模型進行量化,來降低CPU load和節省memory。由於特徵資料(比如智慧語音中的MFCC資料)在送入模型前基本都做了歸一化處理,值都壓縮到了【-1,1】的範圍內,所以現在主流的都是用8位元來量化。下表是用8位元來量化的各種Q格式的值的取值範圍。

                                                      

模型的量化可分為訓練中量化和訓練後量化,還可分為對稱量化和非對稱量化。我們用的是訓練後對稱量化,即先訓練好用浮點表示的模型引數等,然後再去量化,量化某類值(比如weight)時看其絕對值的最大值,從而可以知道用什麼定標的Q格式最合適。我們目前用的是主流的8位元量化方式。模型的量化主要包括兩方面的內容:各層引數的量化和各層輸出的量化。先看各層輸出的量化。在評估時把測試集中各個檔案每層的輸出儲存下來,然後看每層輸出值的絕對值的最大值,比如絕對值最大值為3.6,可以從上面的8位元量化表看出用Q2.5 量化最為合適(也可以用公式 np.ceil(np.log2(max))算出整數的表示位數,然後確定小數的表示位數,從而確定定標)。再來看各層引數的量化。引數主要包括weight和bias,這兩種引數要分別量化,量化方法同上面的每層輸出的量化方法一樣,這裡不再贅述。需要注意的是如果當前層是卷積層或者全連線層,為了減少運算量,一般部署模型時都會將BatchNormal(BN)層引數融合到卷積層或者全連線層(只有當卷積層或者全連線層後面緊跟BN層時才可以融合引數,否則不可以)。具體怎麼融合如下:假設層的輸入為X,不管是卷積層還是全連線層,運算均可以寫成 WX + b (W為權重weight, b為bias),BN層執行了兩個操作,一個是歸一化,另一個是縮放,兩個階段的操作分別為:

                                                                                            

將上面三個式子合併(卷積層或者全連線層的輸出就是BN層的輸入, 原卷積層或者全連線層的引數為Wold和bold),可以得到:

                                                                        

上式等於Wnew * X + bnew,展開得到:

                                                                          

這樣合併後的運算就成了:

                                                                                     

在卷積層或者全連線層裡用上面得到的新引數(Wnew和bnew)替代舊引數(Wold和bold),inference時BN層就消失啦。

 

卷積層或全連線層中,主要是乘累加運算,通常格式是output = input*weight  + bias。這裡input是當前層的輸入(即是上一層的輸出),weight是當前層的權值,bias是當前層的偏置,output是當前層的輸出。這四個值均已定標,在運算過程中要想得到正確的結果,需要做移位處理。怎麼移位呢?下面舉例說明。

 

假設input定標為Q5.2 ,weight定標為Q1.6 ,bias定標為Q4.3 ,output定標為Q2.5 。假定只有一個input和一個weight,input浮點值是28.4,用Q5.2 表示就是01110010 (28.4 *  = 113.6,四捨五入就是114),weight浮點值是1.6,用Q1.6 表示就是01100110,bias為12.8,用Q4.3 表示就是01100110。Input * weight = 01110010 * 01100110 = 0010 1101 0110 1100 = 11628(十進位制表示)。八位數乘以八位數超出了8位數的表示範圍,要用16位表示。28.4 * 1.6 = 45.44,要讓11628表示45.44,所以11628用Q7.8 表示(11628 / 45.44 約為256 =  )。從上面計算看出,兩個八位數相乘是16位數,16位數的定標小數位數是兩個8位數的定標小數位數相加。這裡Q7.8 中的8是Q5.2 中的2加上Q1.6 中的6。定標小數位數知道了,整數位數就是(15 - 小數位數),這裡小數位數是8,整數位數就是7(7 = 15 - 8)。不同定標的數也不能直接相加,所以要把bias的Q4.3 表示的值轉換成Q7.8 表示的值。Bias原始為12.8,用Q4.3 表示就是12.8 * ,用Q7.8 表示就是12.8 *  。可以看出bias從Q4.3 轉變為Q7.8 ,只要乘以 即可,即左移5位。再來看上面的式子output = input*weight  + bias,等式右邊經過計算後變成了Q7.8 ,而等式左邊是根據非常多的樣本算出來的層的輸出的絕對值的最大值得到的定標Q2.5 ,所以最後要把Q7.8 格式轉換成Q2.5格式 。對於一個浮點數,假設為a,用Q7.8 表示就是a *   , 用Q2.5 表示就是a *  ,可以看出要把Q7.8 格式轉換成Q2.5格式 ,只需右移3位(3 = 8 - 5)即可。

 

所以每一層計算過程中移位的處理如下:假定input定標為 Qa.b,weight定標為Qc.d,bias定標為Qe.f,output定標為Qm.n。這些值均為8位元表示,即a+b=7,c+d=7,e+f=7,m+n=7。input * weight 為16位元Qu.v表示,其中v=b+d,u = 15 - v。計算過程中要把bias從8位表示變成16位表示,若f<v,bias則要左移(v-f)位,若f>v,bias則要右移(f-v)位,若f=v,則不移位。處理後 input*weight  + bias是一個16位表示的數,而output是一個8位表示的數,還要把16位表示的數轉換成8位表示的數。若n<v,16位表示的數則要右移(v-n)位,若n>v,16位表示的數則要左移(n-v)位,若n=v,則不移位。

 

按照上面的方法,各層的模型引數以及輸出都量化好了。量化好後還要對量化進行評估,評估的指標是餘弦相似度和歐幾里得距離等。餘弦相似度是用向量空間中兩個向量夾角的餘弦值作為衡量兩個個體間差異的大小的度量。餘弦值越接近1,就表明夾角越接近0度,也就是兩個向量越相似。公式如下:

                                                              

歐幾里得距離,又稱歐氏距離,是最常見的距離度量,衡量的是多維空間中兩個向量之間的絕對距離。歐氏距離越小,相似度越大;歐氏距離越大,相似度越小。公式如下:

                                      

評估時要一層一層的評估,用餘弦相似度和歐幾里得距離等比較每層的量化前浮點的輸出的向量和量化後的定點的輸出向量(定點的輸出向量算好後要根據定標轉成浮點數才能比較)。餘弦相似度要接近1和歐幾里得距離要接近0,才是一個合格的量化。否則要找出量化中的問題,直到指標達標。

&n