本文首發於:https://zhuanlan.zhihu.com/p/104052236

原文:

https://openaccess.thecvf.com/content_ICCV_2019/papers/Nagel_Data-Free_Quantization_Through_Weight_Equalization_and_Bias_Correction_ICCV_2019_paper.pdf

代碼(目測是非官方發佈,運行起來bug巨多,慎重,但是寫的確實還不錯):

https://github.com/jakc4103/DFQ

1. 導讀

這篇論文全稱是《Data-Free Quantization Through Weight Equalization and Bias Correction》,來自於高通人工智能研究院,不久前被ICCV2019接收,後面簡稱DFQ。該論文提出了一種不需要額外數據來finetune恢復精度的離線8bit量化方法,它利用了relu函數的尺寸等價縮放的特性來調整不同channel的權重範圍,並且還能糾正量化過程中引入的偏差,使用方法也很簡單,只需要調用一個API就可以,該量化方法在圖像分類、語義分割和目標檢測中都很有效。其實本質上這篇論文就是講如何利用激活函數ReLU的數學性質,均衡相鄰兩層權重各通道的數據範圍,讓per-layer的量化方法能融合per-channel的優勢,又不需要在硬件上承擔額外開銷,最大化離線量化的效果。但是論文的想法還是基於簡單情況做的考慮,真正應用上的侷限性還是存在的,不過總的看完感覺想法還是蠻新穎的,在一些方面具有啓發性,所以還是想陳述一下自己看完後的理解。

2. 一些概念

通常我們用各種現有成熟的深度學習框架,如TensorFlow、Pytorch或mxnet等搭建網絡模型時,參數和中間運行數據都是默認爲float32類型的,然而在移動嵌入式設備上,由於內存大小、功耗等限制,直接部署原始的浮點網絡是不切實際的,所以就需要對原始浮點模型進行壓縮,減少參數所需的內存消耗,通常的方法有剪枝、知識蒸餾、量化、矩陣分解,其中量化方法是使用最爲普遍的,因爲將32bit的參數量化爲8bit,需要消耗的內存直接就縮減到了原始的1/4,而其他方法針對不同任務,不同模型,在滿足性能要求的情況下實際能節省多少資源都是無法保證的。

2.1 8bit量化

一個32bit的浮點tensor量化爲INT8(範圍[0,255],也可以量化到[-128,127])只需要4步:縮放、取整、偏移和溢出保護,如下所示:

8bit量化器(來自Google量化白皮書)

最後de-quantization的操作有兩個作用:計算量化誤差、用於恢復精度的finetune訓練比如一個tensor的浮點範圍是[-1,1],那麼縮放係數就是255/2=127.5( equ. 1 用的步長,和縮放係數互爲倒數),縮放之後的tensor是[-127.5,127.5],取整是[-127,128],偏移是讓浮點的0能夠對應一個int8的整數,防止0填充出現誤差,選取的時候也會盡量使得浮點最小值對應int8的0,所以這裏z=127,偏移之後可以使得tensor是[0,255],溢出保護之後仍然是[0,255]。de-quantization回去的話可以看到量化的tensor恢復回來變成了[-127/127.5, 128/127.5],與原始的[-1,1]存在一些偏差,說明量化的過程是不可逆的,必定會存在量化誤差,這個誤差是四捨五入操作導致的。

2.2 量化方案的四種境界(本文提出的)

  • Level 1: 不需要額外的數據和訓練操作。方法具有普適性,適合所有模型,只需要知道模型的結構和權重參數,直接離線量化就能得到很好的定點模型;

  • Level 2: 需要額外的數據,但不進行訓練。方法具有普適性,適合所有模型,但是需要額外數據用於校正batch normalization的統計參數如moving mean和moving variance,或者用來逐層地計算量化誤差,並且根據該誤差採取相應策略(如重新選擇縮放係數等)來提升性能;

  • Level 3: 需要額外的數據,並且用於finetune訓練。方法具有普適性,適合所有模型。需要調節一些超參來尋找最優;

  • Level 4:  需要額外的數據,並且用於finetune訓練,但方法針對特定模型使用。這種特定模型指的是用全浮點訓練收斂之後的模型進行量化效果極差,並且必須從頭開始加上量化操作進行訓練,這種方法需要消耗極大的時間成本。

回到這篇DFQ論文,我們分析一下他要解決的問題和作出的貢獻

3. 問題

  1. 存在這樣的情況:模型預訓練完之後某些層的權重參數不同通道之間的數據方差很大如下圖所示,利用常見的per-layer量化策略(即整個層的參數作爲一個tensor進行量化),則會使得值較小的通道直接全部被置爲0,導致精度的下降,per-channel的方法可以解決這個問題,但是在硬件實現上因爲要針對每一個通道都有自己獨立的縮放係數和偏移值考慮,會導致很多額外的開銷,得不償失;

MobileNet v2
  1. FP32->INT8量化過程中帶來的noise是有偏誤差,會導致不同模型不同程度的性能下降,目前的方法基本依賴於finetune;

4. 解決方法: Data-Free Quantization

  • 算法流程

DFQ流程
  • Cross-layer equalization

目前最常用的激活函數是ReLU,他滿足如下等式:,並且該等式可以適用於一切分段線性函數,應用到神經網絡中可以描述如下:

給定神經網絡中的兩層:和

那麼有:

推導可得

其中S是一個對角矩陣,對角線上的每個值是用來調整縮放係數的因子。前面講到量化需要對參數Tensor進行縮放,如果不同通道的縮放係數差異很大的話就會導致巨大的量化誤差,所以可以利用ReLU函數的縮放特性來進行上下層之間不同通道縮放係數的調整,如下所示:

示意圖

若Layer 1的weight在輸出通道的range方差很大,那麼可以利用上述的等價變換公式,給range大的層乘以小的係數,range小的層乘以大的係數,使得各個通道的range儘量一致,等於一個給定的範圍(給定方式下面闡述),這樣量化的時候整個tensor量化的誤差就會最小,同時爲了保證數值內部的等價,Layer 1乘完的係數,在Layer 2要除回,具體體現在Layer 1 weight的第i個輸出通道乘了係數s,對應Layer 2 weight的第i個輸入通道就要除以係數s,上圖中的乘除關係和描述的相反,意思是相同的。

論文中證明並講述了每個layer的固定range的取法,具體最優化證明可以看論文的appendix A:Layer 1權重的輸出通道和Layer 2的輸入通道一一對應,令爲第i個通道的權重範圍,即,這裏採用對稱量化的方法比較好說明,假設第i個通道的Layer 1和Layer 2權重的範圍分別是r1和r2,那麼如何取可以使得兩個Layer的第i層量化比較均衡,最好的方法就是令最後兩個的範圍,,另外,而Layer 1和Layer 2權重的整個範圍爲

這裏講的是兩層之間的range均衡,在真正的實驗中是每相鄰兩層均衡,然後不斷迭代着算下去的,可以設置一個量化誤差閾值,如果把整個網絡迭代完一遍之後的權重量化誤差在一個預先設定的範圍之內就可以停止迭代,或者設定一個最大迭代次數,達到最大次數即停止。

  • 上面考慮的是如何使得每層weight的量化誤差儘可能小,但在實際量化過程中,影響比較大的還有activation的量化效果。尤其在本層weight的某通道縮放係數大於1的時候,activation的該通道數據範圍會增大,這有可能會導致activation各通道之間的數據範圍差異變大,從而導致較大的量化誤差。解決辦法是採用ReLU函數的又一等價變換:,這裏的r()是ReLU函數,c是一個正數,可以用裕量來解釋,即原始的Wx+b>c,就滿足上述等式。

再具體說明一下:

就是本層activation直接簡單粗暴地減掉c,使得整個數據範圍變小從而減小量化誤差,然後減掉的部分由下一層的bias完全吸收。這裏我們會疑問當恰好不存在這個裕量時,豈不是用不了該公式了,而實際上paper中也不是用的完全等價公式,它保證99.865%的值是完全等價,剩下的直接減掉,雖然不是完全等價,但是在實驗中發現並不影響結果,這裏有點剪枝的意思。其中c的具體選取方式是基於一個先驗知識:activation:,本文中的

  • Bias correction

本節講述的是如何校正量化(四捨五入的不可逆性)帶來的偏差。之前的研究認爲量化帶來的誤差是無偏的,不影響輸出的均值,但是本文發現權重的量化誤差會導致輸出的有偏誤差,從而改變下一層輸入數據的分佈,在其他量化方法中方法中,可以直接計算activation量化前後的誤差,加入loss中作爲一個正則項,但是本文基於Data-Free的立場,決定繼續採用網絡中的已有信息(其實就是每層的權重和BN的各個參數信息),所以需要從數學形式上進行推導。

可知權重量化的誤差,如果輸出數據的誤差期望,那麼輸出的數據期望就會被改變,解決辦法是每層量化後的輸出減掉這部分的誤差,,且假設誤差是常數,則有。然後我們就有疑惑,這個Data-Free的方法怎麼得到,paper中重新介紹了Batch Normalization參數的作用,我們知道Batch Normalization包含四個參數,分別是經過規範化前後數據的均值和方差,但是這個,其他參數也是對卷積後數據重新校正,如何從這個數據裏面提取出  ,說實話論文一開始的時候沒有說清楚,並且後面一直在推導卷積後的數據x的一些統計信息,經過Batch Normalization之後應該是趨近於高斯分佈,並且均值方差可知,但是經過ReLU這樣的截斷函數之後,它的均值方差就會發生變化,論文一直在推導截斷前後的關係,並且由一個巨複雜的公式,得到了的最終表達,我以爲作者是想試圖用這個來混淆前面那個輸入的均值,一開始很迷惑的,不過仔細一想,這一層的輸出不就是下一層的輸入嗎?作者推到出來的結果不正好可以作爲估計下一層的輸入的均值來用嗎,這麼一想就通了。

5. 總結

具體實驗結果可以看論文的Experiment,一句話描述就是量化後的效果能超過per-channel的方法,且逼近FP32的模型,更厲害的是還能推廣到語義分割和目標檢測等常見視覺任務上面,reviewers看完應該就沒話說了。

實驗結果

總的來說這個論文的工作很完整,從提出問題,總結前人方法和歸類目前已有的方法,通過數學推導來提出自己的解決方法(而非調參),到對比實驗,ablation study,最後推廣到其他任務,最後的附錄也是很好的,從論文的完整度寫作上是非常值得借鑑的。但我感覺這篇論文還存在以下侷限性:

  • 論文僅僅考慮的是網絡層與層之間單層連接方式(單一輸入單一輸出的層),對於add/concat的連接方式,即出現多輸入多輸出的層無法應用。論文中對於MobileNet-v2的實驗也只是在block內部做的均衡,那麼就是說block與block之間是相互獨立的,block內部一般也就三個conv,三個之間來回迭代的效果還是存在質疑;

在這裏插入圖片描述
  • 最後一個工作Bias correction,我的理解是論文通過計算上一層輸出的均值,來作爲本層輸出的均值,那麼第一層怎麼處理?雖然有些網絡一上來就做了規範化,均值可以認爲是0,但還是有些網絡對輸入單純/255,或者再加入一些例如-0.5的平移操作,雖然對於ImageNet等經典數據集,其實事先是有一個公認的均值可以拿來進行計算,但是不是又違背了Data-Free的初衷了呢?

  • 每次權重均衡的迭代方式是本層權重的輸出通道與下一層權重的輸入通道進行一一對應的均衡,然後取最合適的範圍,下一層經過本次均衡後又要基於輸出通道與下下層的輸入通道進行均衡,中間這層相當於經過了兩次優化,經過第一次均衡之後留給下一層的優化空間還足夠嗎?當然來回迭代很多次有可能緩解這個問題,但是否有更好的迭代方式?如每兩層之間的均衡都儘可能先滿足上一層的權重各輸出通道範圍相似,然後最後一層單獨再進行處理,這個只是一種設想。

6. 啓發

最後說說帶來的啓發吧,輕量級網絡如MobileNet,ShuffleNet系列的直接離線量化效果其實不是很好,因爲本身網絡的冗餘度就很低了,不像AlexNet, GoogleNet,ResNet這樣巨無霸網絡,說實話有些量化論文拿這些冗餘網絡來做對比實驗真的是一言難盡。

趣圖

目前針對輕量級網絡直接量化效果差的解決辦法是quantization-aware training,就是在FP32模型訓練收斂之後,再加入量化的操作,繼續進行finetune,這個過程還是比較耗時,且在一些情況下還需要一些調參技巧,如BN操作中的moving_mean和moving_variance要重新校正還是直接凍結等,且在一些深度學習框架上提供模型壓縮與量化工具也是更傾向於一鍵直接離線量化,要加入量化訓練的話還是稍微麻煩一些。所以如果有更好的離線量化方法的話,只需要給定一個FP32模型文件,就能得到一個性能不錯的量化網絡是最好的選擇。這個論文帶來的啓發是直接在數學上考慮量化誤差,並且利用已有的信息將誤差來源大的項進行公式上的融合,比如上下層的權重逐通道範圍均衡,使得每一層的權重各個通道之間的範圍接近。朝着這個方法應該還可以做一些改進什麼的吧。以上就是我對本篇論文的解讀和拙見,非官方復現的代碼因爲代碼bug太多,實在debug不下去了,沒能跑出相應的效果,不過最近又在偷偷更新,而且加入了很多看不懂的操作(明明Data-Free,咋還開始瘋狂load數據了???)。希望有興趣的讀者讀完原論文的可以私下交流一下。

歡迎關注GiantPandaCV, 在這裏你將看到獨家的深度學習分享,堅持原創,每天分享我們學習到的新鮮知識。( • ̀ω•́ )✧

有對文章相關的問題,或者想要加入交流羣,歡迎添加BBuf微信:

二維碼

爲了方便讀者獲取資料以及我們公衆號的作者發佈一些Github工程的更新,我們成立了一個QQ羣,二維碼如下,感興趣可以加入。

公衆號QQ交流羣
相關文章