文章主要有兩個創(chuàng)新點
- 將量化后的weigths進(jìn)行split, 然后優(yōu)化每一位bit, 使得目標(biāo)函數(shù)最小, 得到每一位的bit后再將所有位的bit進(jìn)行stitching
- 在保證計算效率的前提下, 可以對Activation使用per-channel的量化, 論文中叫Error Compensated Activation Quantization(ECAQ)
下面針對這兩條分別說明,
Bit-Split and Stitching
- 常規(guī)的二進(jìn)制, 第一位是符號位, 后面的是絕對值, 每一位只能取0或1. split的作用就是把符號位分配給每個bit, 經(jīng)過split處理, 總位數(shù)會少1, 每一位可取值變?yōu)?1, 0, 1. 可表示的范圍其實沒變都是最小位-111, 最大111.
經(jīng)過這樣處理后, 就可以利用論文中的公式進(jìn)行優(yōu)化, 優(yōu)化這塊不太懂. 大致思想還是迭代, 每次迭代時, 固定其他值, 然后求解其中某一位的值.
其實我不太懂, 為什么這里split后求解得出的量化值和scale精度就會更好
- conv/fc的計算過程可以表示位 (假設(shè)shape為[M, N] shape為[N, C], 則的shape為[M, C]), 經(jīng)過per_tensor量化后變?yōu)?img class="math-inline" src="https://math.jianshu.com/math?formula=Y%20%3D%20%5Calpha%20%5Chat%7BW%7D%5Chat%7BX%7D%5Cbeta" alt="Y = \alpha \hat{W}\hat{X}\beta" mathimg="1">其中和均為標(biāo)量, 經(jīng)過這樣處理后, 計算量較大的變成了 由原來的float計算變?yōu)榱薸nt型的計算.
當(dāng)變?yōu)閜er_channel量化后, 上述過程仍適用. 當(dāng)變?yōu)閜er_channel量化后, 又標(biāo)量變?yōu)橄蛄? 且其維度為M. 但是若對使用per_channel的量化方法, 則的維度為N, 這樣的話, 無法繼續(xù)將原有的浮點計算轉(zhuǎn)為定點計算, 否則數(shù)學(xué)上無法等價.
ECAQ的主要思想如圖, 即對進(jìn)行per_channel量化, 但是將量化的scale乘到中.
這里在代碼實現(xiàn)層面使用了in_scale
和out_scale
, 所以原本的計算過程變?yōu)?br>
這里的會乘到對應(yīng)的W中, 當(dāng)把乘到后續(xù)的W中以后, X的fake quantize將變成
在代碼中這里會設(shè)置out_scale=1, 也就是X經(jīng)過Quantization op后的輸出為int, 而非平時的Quantization那樣, 輸出的是近似與float X的值.
該論文的代碼需要注意下面一些地方:
- 先對W進(jìn)行進(jìn)行ofwa(optimal fixed-point weight approximation) 解出初步最佳值
- 利用layer的input 和 output再進(jìn)行ofwa解出W的最佳量化值和scale, 并保存為文件
- load量化后的W到model內(nèi), 然后使用數(shù)據(jù)對量化activation
- Weights bitwidth=8時時間較長
- 當(dāng)使用ECAQ時, 對feature定點后得到β, 此后beta固定, 且此feature以定點后的數(shù)值存在
- 默認(rèn)情況relu后的quantizer是signed
- First and last layer activation quantize bit-width is always 8
- 不會fold BN
- input image 沒有定點
- 只在conv前定點
- 從feature map中隨機(jī)選取點進(jìn)行量化, 所以結(jié)果每次會有所不同
resnet 系列網(wǎng)絡(luò)的quantization插入位置
mobilenet系列網(wǎng)絡(luò)的quantization插入位置
實驗:
resnet 18和resnet50
基本復(fù)現(xiàn)了論文中的結(jié)果, 但是代碼沒有給出ECAQ的實現(xiàn), 自己實現(xiàn)后, 結(jié)果為
A3W8:
float 69.758/89.078
Bit split & stitch: * Acc@1 64.754 Acc@5 85.926
Bit split & stitch + ECAQ: * Acc@1 66.262 Acc@5 86.750
略有提升, 但是不多.
ECAQ在實現(xiàn)時, 對每一個conv做完ECAQ后需是使用乘以后的W作為conv的weights, 并且,與之對應(yīng)的activation的Quantization的
mobilenet v2
Bit width | accuracy | accuracy after quantize W but not quantize activation
---- | ----- |
A8W8: | * Acc@1 71.644 Acc@5 90.134 | * Acc@1 71.842 Acc@5 90.296
A8W4: | * Acc@1 67.898 Acc@5 88.028 | * Acc@1 63.652 Acc@5 85.112
A4W4: | * Acc@1 36.672 Acc@5 61.942 | * Acc@1 64.240 Acc@5 85.496
A4W4+ECAQ后:
- Acc@1 46.160 Acc@5 71.004 (只對第一層使用ECAQ)
這里很奇怪, 如果對所有層使用ECAQ, 最終結(jié)果不理想,
但如果只對第一層使用ECAQ, 絕對精度雖然還不行, 但是相對于原始的量化, 提升很多
只對第一層量化: * Acc@1 46.160 Acc@5 71.004
思考
- 由于量化條件比較寬松( , per_channel, float scale, unsigned), 所以在8bit時精度幾乎沒有掉. 這篇論文主要在說自己在低比特時效果更好, 但是實驗?zāi)P投紝儆诒容^好量化的, 在mobilenet v2上的效果似乎不是特別好.
- 而且他們在量化時沒有fold bn也挺奇怪.
- 從實驗來看, per_channel和per_tensor的量化方式, 對于activation來說貌似影響不大, 即使將per_tensor替換為per_channel精度提升似乎并不高