------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
本次主要分享,我們在神經網絡模型部署上的其中一次探索,“tensorflow quantization-aware”
參考資源如下:
“Quantizing deep convolutional networks for efficient inference: A whitepaper”
”Quantization and Training of Neural Networks for Efficient Integer-Arithmetic-Only Inference“
”https://github.com/google/gemmlowp“
”https://spatial-lang.org/gemm“
“https://github.com/tensorflow/tensorflow/tree/master/tensorflow/lite”
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1 現狀:
智能移動設備的日益普及以及基於深度學習的模型令人生畏的計算成本要求建立有效而准確的設備上推理方案。我們提出了一種量化方案,該方案允許使用integer-only 算法進行推理,該算法比在通常可用的僅整數硬件上的浮點推理更有效地實現。我們還共同設計了一種訓練程序,以保持量化后的端到端模型准確性。結果,所提出的量化方案improves the tradeoff between accuracy and on-device latency 。即使在以運行時效率聞名的模型系列MobileNets上,這些改進也非常重要,並且在ImageNet分類和流行CPU的COCO檢測中得到了證明。
當前最先進的卷積神經網絡(CNN)不太適合在移動設備上使用。自AlexNet 問世以來,主要根據分類/檢測准確性對現代CNN進行了評估。因此,網絡架構的發展沒有重新評估模型的復雜性和計算效率。另一方面,要在移動平台(例如智能手機,AR / VR設備(HoloLens,Daydream)和無人機)上成功部署CNN,則需要較小的模型尺寸來適應有限的設備內存,以及用戶交互的低延遲。這導致了一個新興的研究領域,該領域專注於以最小的精度損失來減小CNN的模型大小和推理時間。
該領域的方法大致可分為兩類。第一類以MobileNet ,SqueezeNet ,ShuffleNet 和DenseNet 為例,代表了利用計算/內存有效操作設計的新型網絡體系結構。第二類將CNN的權重或激活從32位浮點調整為低位深度表示。這種方法被如下網絡所采用,如三元重量網絡(TWN ),二進制神經網絡(BNN ),XNOR-NET,是我們調查的重點。盡管有很多種方法,但當前的量化方法在兩個方面存在不足,無法准確地平衡延遲。
其次,許多量化方法無法在實際硬件上提供可驗證的效率提升。weight-only的方法是主要關注設備上的存儲,較少關注計算效率。值得注意的例外是二元,三元和位移網絡。這些方法將權重表示為為0或2的冪,這允許通過位移來實現乘法。 然而,盡管移位在傳統的硬件中可能是有效的,但它們對現有的硬件的累加指令幾乎沒有好處,而乘法指令在正確使用(即流水線)后,其成本並不比單獨的累加昂貴。此外,只有在操作數較寬的情況下乘法才是昂貴的,並且一旦量化權重和激活量,避免乘法的需求就隨着位深度而減小。值得注意的是,這些方法很少提供設備上的測量來驗證承諾的耗時改進。更具run-time友好性的一些方法將權重和激活都量化為1位表示,用這些方法,乘法和加法都可以通過有效的bit-shift和bit-count操作來實現,這在自定義GPU內核中得到了展示(BNN)。但是,但是1bit量化會導致性能大幅下降,並且在模型表示上可能過於嚴格。
在本文中,我們通過改善常見移動硬件上MobileNets的延遲與准確性之間的權衡來解決上述問題。我們的具體貢獻是:
• 我們提供了一個量化方案,將權重和激活都量化為8位整數,而僅將幾個參數(bais 向量)量化為32位整數。
• 我們提供一個量化的推理框架,在僅允許整數運算的硬件上如Qualcomm Hexagon ,和我們描述一個有效准確的實現在ARM NEON上。
• 我們提供了與量化推論共同設計的量化訓練框架,以最大程度地減少對真實模型進行量化帶來的准確性損失。
• 我們將我們的框架應用於基於MobileNets的高效分類和檢測系統,並在流行的ARM cpu上提供基准測試結果,展示了在最新的MobileNet架構的latency-vsaccuracy tradeoffs 的顯著提升,在ImageNet分類任務,和coco的對象檢測任務,以及其他任務。
我們的工作從Deep learning with limited numerical precision.中獲得靈感,它利用低精度定點算法來加速CNN的訓練速度,在Deep Learning
and Unsupervised Feature Learning NIPS Workshop 中,它使用8 位定點算法來加快x86 CPU的推理速度。 我們的量化方案專注於提高推理速度與CPU設備的精度之間的權衡。
2 量化推理
2.1量化方案
在此,我們描述了一種通用的”量化方案“(這里描述的量化方案是TensorFlow Lite[5]中采用的方案,我們將參考其代碼的特定部分來說明下面討論。
我們之前在gemmlowp[18]的文檔中描述過這種量化方案。作為本節中開發的一些主題的替代處理,以及作為其自身包含的示例代碼),即bit進行數值表示的對應關系(q ,表示“量化值”),數學實數(r , “實際值”)。我們的量化方案是推理中使用純整數在訓練過程中使用純浮點數,兩種實現都保持了高度的對應性。我們首先給出量化方案的嚴格數學定義,然后分別采用該方案進行整數-算術推理和浮點訓練。
我們的量化方案的基本要求是,它允許僅對量化值使用整數算術運算來高效執行所有算子(我們避免使用需要查找表的實現,因為與SIMD硬件上的純算術相比,它們的執行性能較差)。這等效於要求量化方案是整數q 到實數r 的仿射映射,即形式為:
常數S 和Z 是量化參數。量化方案對每個激活數組和每個權重數組中的所有值使用一組量化參數。單獨的數組使用單獨的量化參數。 對於8位量化,q 被量化為8位整數(對於B 位量化,q 被量化為B 位整數)。一些數組(通常為bais 向量)被量化為32位整數。
常數S (”scale“)是任意正實數。它通常在軟件中表示為浮點數,如實際值r 。2.2描述了避免在推理工作負載中表示此類浮點數量的方法。
常數Z (”zero-point“)與量化值q 屬於同一類型,並且實際上是與真實的”0“值所對應的量化值q。為了滿足實際值的要求 r = 0 可以用一個量化值精確表示。因為有效實施神經網絡運營商通常需要在邊界周圍對陣列進行零填充。
我們的討論到目前為止總結在下面的量化Buffer數據結構(在TensorFlow lite Converter的實際數據結構是頭文件中的QuantizationParams 和Array。我們在下一個小節將會討論,該數據結構仍然包含浮點數量,不會出現在實際的量化的設備上inference代碼中)中,具有這樣的的一個實例Buffer現有用於在神經網絡的每個激活陣列和權重陣列。我們使用C ++語法,因為它允許類型的明確傳達:
2.2 只使用矩陣乘法器的整數算法
現在我們轉向如何僅使用整數算術進行推理的問題,即如何使用方程式將實數計算轉換為量化值計算,以及如何將后者設計為僅包含整數算術,即使S 不是整數。
考慮實數的兩個平方N × N 矩陣r 1 和r 2 的乘積,其乘積以r 3 = r 1 r 2表示。我們表示每一個矩陣的元素偽rα(α= 1、2或3)為rα(i, j),其中1<=i,j<=N ,它們量化的量化參數(SαZα)。我們通過qa[i,j]表示量子化的條目(i, j)。則式(1)變為:
根據矩陣乘法的定義,我們有:
在等式(4),唯一的非整數為M。作為僅取決於量化scale S 1 ,S 2 ,S 3 的常數,可以離線計算。我們憑經驗發現它總是在區間(0 ,1) ,因此可以把它標准化成以下形式:
其中M 0 在區間[0.5,1 )和Ñ 是一個非負整數。現在歸一化乘法器M0 現在很適合表示為定點乘法器(例如,int16或int32,具體取決於硬件功能)。
例如,如果使用int32,表示M 0 的整數是最接近2^31*M0 的int32值。由於M 0 > = 0.5 ,這個值總是在>=2^30 ,因此將始終具有至少30bits的相對精度。
因此,與M0相乘可以實現為定點相乘()。同時,可以通過有效的移位實現2^−n 的乘法運算,盡管這需要具有正確的舍入到行為,稍后介紹。
2.3 對ZERO-POINT的有效處理
為了高效地執行方程(4),而不必執行2*N^3次減法,無需將乘法的操作數擴展為16位整數,我們首先注意到,通過在公式(4)中分配乘法,可以將其重寫為
每一個a2(k)或者一個a1(i)只需要N個加法就可以進行計算,所以一共只需要2n^2個加法,公式(7)的其余代價幾乎全部集中在核心整數矩陣乘法的累加上
它需要2N^3個算術運算;實際上,(7)中的其他所有項都是O(N^2)在O中有一個小常數。
因此,擴張到形式(7),提出計算a2^k和a1~(i)啟用低開銷處理任意零點為N的最小值,減少了相同的核心問題整數矩陣乘法積累(9)
我們必須計算在其他任何zero-points-free量化方案
2.3 實現一個典型的融合層
我們繼續第2.3節的討論,但現在明確定義所有涉及的量的數據類型,並修改量化的矩陣乘法(7),將偏置加法和激活函數計算直接合並到其中。將整個層融合到單個操作中不僅是一種優化。由於我們必須在推理代碼中再現訓練中使用的相同算法,推理代碼中融合運算符的粒度(采用8位量化輸入並生成8位量化輸出)必須與訓練圖中的“偽量化”運算符的設置匹配
對於我們在ARM和x86 CPU架構上的實現,我們使用gemmlowp庫[18],它的
GemmWithOutputPipeline入口點提供了支持我們現在描述的融合操作5(本節的討論是在TensorFlow Lite[5]中實現的,例如一個卷積運算符(參考代碼是自包含的,對gemmlowp[18]的優化代碼調用)。)
我們取q1矩陣為權重,q2矩陣為激活值。權重和激活的類型都是uint8(我們可以等效地選擇int8,並適當修改零點)。累加uint8值的積需要一個32位的累加器,我們為累加器選擇了一個有符號的類型,原因很快就會清楚了。公式(9)的SUM形式如下:
為了使量化的Bais是在int32累加器中加入一個int32偏置,對偏置向量進行量化處理,其量子化數據類型為int32;采用0作為量化零點Zbias;它的量化標度Sbias與累加器的Sbias相同,是權重的標度與輸入激活量的乘積。在第2.3節的符號中
盡管偏置向量被量化為32位值,但它們只占神經網絡參數的一小部分。此外,使用更高的精度偏差向量滿足真正的需要:當每個偏置向量項被添加到許多輸出激活時,偏置向量中的任何量化錯誤都傾向於作為一個整體偏差(一個非零均值的誤差項) 為了保持良好的端到端神經網絡精度,必須避免哪些情況.
對於int32累加器的最終值,還有三件事情要做:按比例縮小到8位輸出激活所使用的最終規模,向下轉換到uint8並應用激活函數來生成最終的8位輸出激活
我們關注的是僅僅是clamps的激活函數,如ReLU、ReLU6。數學函數在附錄A.1中進行了討論,我們目前還沒有將它們融合到這樣的層中。因此,我們的融合激活函數需要做的惟一一件事就是在存儲最終的uint8輸出激活之前,將uint8值進一步固定到某個子區間[0,255]。在實踐中,量子化的訓練過程(第3部分)傾向於學會利用整個輸出uint8 [0, 255]間隔使激活函數不再做任何事情,其作用被包含在clamping 中
3 使用simulated quantization進行訓練
訓練量子化網絡的一種常見方法是在浮點數中進行訓練,然后對產生的權值進行量子化(有時需要進行額外的后量子化訓練以進行微調)。我們發現,這種方法對於具有相當大的代表性的大型模型非常有效,但是對於小型模型卻會導致顯著的精度下降。簡單訓練后量化的常見失效模式包括:
1)不同輸出通道的權值范圍差異較大(大於100×)(第2節規定同一層的所有通道都要量化到
未完--