
極市導讀
本文詳細的介紹了關於低比特模型量化,涉及到量化在推理和訓練的內容。>>加入極市CV技術交流群,走在計算機視覺的最前沿
隨着深度學習的發展,神經網絡被廣泛應用於各種領域,模型性能的提高同時也引入了巨大的參數量和計算量。模型量化是一種將浮點計算轉成低比特定點計算的技術,可以有效的降低模型計算強度、參數大小和內存消耗,但往往帶來巨大的精度損失。尤其是在極低比特(<4bit)、二值網絡(1bit)、甚至將梯度進行量化時,帶來的精度挑戰更大。
這篇文章比較詳細,所以下面這個圖是這篇文章的一個整體目錄。當然啦,除了非常多的文字,這篇文章塞了59個公式,涉及到量化在推理和訓練的內容。雖然可能看得很辛苦,但是也希望可以多多支持ZOMI醬哈。打公式不容易,發現錯誤歡迎評論留言指正。

與FP32類型相比,FP16、INT8、INT4的低精度類型所占用空間更小,因此對應的存儲空間和傳輸時間都可以大幅下降。以手機為例,為了提供更人性和智能的服務,現在越來越多的OS和APP集成了深度學習的功能,自然需要包含大量的模型及權重文件。以經典的AlexNet為例,原始權重文件的大小已經超過了200MB,而最近出現的新模型正在往結構更複雜、參數更多的方向發展。顯然,低精度類型的空間受益還是很明顯的。低比特的計算性能也更高,INT8相對比FP32的加速比可達到3倍甚至更高,功耗上也對應有所減少。
模型量化即以較低的推理精度損失將連續取值(或者大量可能的離散取值)的浮點型模型權重或流經模型的張量數據定點近似(通常為int8)為有限多個(或較少的)離散值的過程,它是以更少位數的數據類型用於近似表示32位有限範圍浮點型數據的過程,而模型的輸入輸出依然是浮點型,從而達到減少模型尺寸大小、減少模型內存消耗及加快模型推理速度等目標。

首先量化會損失精度,這相當於給網絡引入了噪聲,但是神經網絡一般對噪聲是不太敏感的,只要控制好量化的程度,對高級任務精度影響可以做到很小。
其次,傳統的卷積操作都是使用FP32浮點,浮點運算時需要很多時間周期來完成,但是如果我們將權重參數和激活在輸入各個層之前量化到INT8,位數少了乘法操作少了,而且此時做的卷積操作都是整型的乘加運算,比浮點快很多,運算結束後再將結果乘上scale_factor變回FP32,這整個過程就比傳統卷積方式快很多。
提前從體系結構的考量角度思考量化帶來的另一個好處是節能和芯片面積,怎麼理解呢?每個數使用了更少的位數,做運算時需要搬運的數據量少了,減少了訪存開銷(節能),同時所需的乘法器數目也減少(減少芯片面積)。

一邊而言,量化方案主要分為兩種:在線量化(On Quantization)和離線量化(Off Quantization),在線量化指的是感知訓練量化(Aware Quantization),離線量化指的是訓練後量化(Post Quantization)。訓練量化根據名字的意思很好理解,其實就是在網絡模型訓練階段採用量化方案進行量化。訓練後量化中的量化方案跟訓練並不相關,主要是在模型離線工具(模型轉換工具的時候)採用量化方案進行量化。
實際上無論是Tensorflow、MindSpore、Pytroch的量化感知訓練是一種偽量化的過程,它是在可識別的某些操作內嵌入偽量化節點(fake quantization op),用以統計訓練時流經該節點數據的最大最小值,便於在使用端測轉換工具(推理轉換工具)的時候,轉換成端側需要的格式時進行量化使用。
目的是減少精度損失,其參與模型訓練的前向推理過程令模型獲得量化損失的差值,但梯度更新需要在浮點下進行,因而其並不參與反向傳播過程。
某些操作無法添加偽量化節點,這時候就需要人為的去統計某些操作的最大最小值,但如果統計不准那麼將會帶來較大的精度損失,因而需要較謹慎檢查哪些操作無法添加偽量化節點。
值得注意的是,偽量化節點的意義在於統計流經數據的最大最小值,並參與前向傳播,讓損失函數的值增大,優化器感知到這個損失值得增加,並進行持續性地反向傳播學習,進一步提高因為偽量化操作而引起的精度下降,從而提升精確度。
值得注意的是,訓練時候的原理與在端測推理的時候,其工作原理並不一致。
2. 訓練後動態量化(Post Dynamic Quantization)
訓練後動態量化是針對已訓練好的模型來說的,針對大部分已訓練,未做任何量化處理的模型來說均可用此方法進行模型量化。
其工作比較簡單,在端測轉換工具的時候,對網絡模型的權重進行統計其每一層卷積的layer或者channel的最大值和最小值,然後通過量化公式對數據進行byte轉換。這樣得到的權重參數比以前小1/4。推理的時候,在內存初始化的時候對網絡模型中的權重進行反量化操作變成float進行正常的推理。
3. 訓練後校正量化(Post Calibration Quantization)
訓練後靜態量化,同時也稱為校正量化或者數據集量化。其原理是對於Mindspore在端測低比特推理的時候(Inference),需要生成一個校準表來量化模型。這個量化校準表的生成需要輸入有代表性的數據集,對於分類任務建議輸入五百張到一千張有代表性的圖片,最好每個類都要包括(即數據無偏)。
量化算法介紹一般而言,無論per channel還是per layer量化方案,對於weight權重的量化使用對稱量化,對於activate激活的量化使用非對稱量化。
其原因是對於權重而言,其數據的分布為對稱的如或,因此採用對稱量化可以進一步有效降低計算量,使得數據分布更加符合其真實的分布;activate激活在網絡中通常使用ReLU和ReLU6等作為網絡模型的激活函數,其數據分布集中在或者,如果採用對稱方案會加劇數據的離散程度,另外一個原理是會造成數據的浪費,如[-128,0]之間並不存儲任何數據,只有[0,127]有數據分布。

下面以int8作為量化的標準,介紹一下兩種量化算法的主要細節。
對稱的量化算法原始浮點精度數據與量化後INT8數據的轉換如下:
其中,scale默認是float32浮點數,為了能夠表示正數和負數,int採用signed int8的數值類型。通過將float32原始高精度數據轉換到signed int8數據的操作如下,其中round為取整函數,量化算法需要確定的數值即為常數scale:
由於在神經網絡的結構以層(Layer)來進行劃分的,因此對權值和數據的量化可以層Layer為單位來進行,對每層Layer的參數和數據分別進行不同scale的量化。
對權值和數據的量化可以歸結為尋找scale的過程,由於int8為有符號數,要保證正負數值表示範圍的對稱性,因此對所有數據首先進行取絕對值的操作,使待量化數據的範圍變換為,再來確定scale,其scale正確的計算公式為:
另外對於offset的計算公式為:
確定了scale之後,itn8數據對應的表示範圍為 ,量化操作即為對待量化數據以 進行飽和式截斷,即超過範圍的數據飽和到邊界值,然後進行第一條公式所示量化計算即可。
2. 非對稱asymmetric
非對稱的量化算法與對稱的量化算法,其主要區別在於數據轉換的方式不同,如下,同樣需要確定scale與offset這兩個常數:
確定後通過原始float32高精度數據計算得到uint8數據的轉換即為如下公式所示:
其中,scale是float32浮點數,uint為unsigned INT8定點數,offset是int32定點數。其表示的數據範圍為[ ]。若待量化數據的取值範圍為 ,則scale的計算公式如下:
offset的計算方式如下:
對於權值和數據的量化,都採用上述公式的方案進行量化, 和 為待量化參數的最小值和最大值, 和 為:
3. 量化初始化
在一般的端測推理的時候,由於網絡模型的輸入並沒有偽量化節點記錄輸入tensor的最大值和最小值,因為無法求得量化參數scale和offset,這個時候推理框架許可要根據輸入數據的標準差deviation和均值mean進行計算,得到對應的量化參數。
其中標準差Standard Deviation的計算公式為下:
其對應的scale為:
Offset的計算為:
值得注意的是,由於在其他端測推理框架(如tflite)需要手工輸入標準差deviation和均值mean,容易導致對數據分析、數據輸入的錯誤和框架的割裂,因此感知量化訓練的時候會對模型的輸入和輸出加上fakeQuant偽量化節點,記錄數據min和max,從而求得Mindspore端測用到input tensor的scale和offset。
1.1.2 感知量化訓練上面講解了基本的量化公式和量化的方法,下面來詳細展開感知量化訓練(Aware Quantization)模型中插入偽量化節點fake quant來模擬量化引入的誤差。端測推理的時候摺疊fake quant節點中的屬性到tensor中,在端測推理的過程中直接使用tensor中帶有的量化屬性參數。
為量化節點(Fake Quant)的意義在於:
1)找到輸入數據的分布,即找到min和max值;
2)模擬量化到低比特操作的時候的精度損失,把該損失作用到網絡模型中,傳遞給損失函數,讓優化器去在訓練過程中對該損失值進行優化。
a. 基本原理
低比特量化模型運行時,需要確定scale與offset兩個量化參數:
其中,是float32浮點數,uint8為unsigned int定點數,offset是int32定點數。其表示的數據範圍為:
若待量化數據的取值範圍為[a,b],則scale和offset的計算方式如下:
對於權值和數據的量化,都採用上述公式的方案進行量化,min和max為待量化參數的最小值和最大值。
前面呢,曾經提到一般而言,權重數據是對稱,為了可以進一步減少數據的計算,較少額外的存儲數據,因此推薦使用對稱的量化算法。但是在對mobieNetV2,mobileNetV3的實際測試開發的過程中,發現數據大部分是有偏的,例如mobileNetV2中:

此時權重對應的數據並不是以0為中心點對稱,featture.child8.conv.child3.weight的權重數據分布範圍是,為了更好地擬合更多的數據,對更多的數據具有更好的泛化性,因此統一使用了非對稱的量化算法。
b. 正向傳播
為了求得網絡模型tensor數據精確的Min和Max值,因此在模型訓練的時候插入偽量化節點來模擬引入的誤差,得到數據的分布。對於每一個算子,量化參數通過下面的方式得到:
Fake quant節點的具體計算公式為:
為了更好地表示上面公式的作用,正向傳播的時候fake quant節點對數據進行了模擬量化規約的過程,如下圖所示:

首先對數據根據min和max值進行截斷,然後把float數據轉換成為int數據,之後再把int數據重新轉換成為float數據,該操作會丟失掉float1與float2轉換之間的精度差。對於量化感知訓練,通過模擬量化操作時候對數據進行規約操作,所以網絡模型中每一個tensor數據可以根據下面公式進行封裝成為op,得到:
c. 反向傳播
按照正向傳播的公式,如果方向傳播的時候對其求導數會導致權重為0,因此反向傳播的時候相當於一個直接估算器:
最終反向傳播的時候fake quant節點對數據進行了截斷式處理,如下圖所示:

d. 更新Min和Max
FakeQuant偽量化節點主要是根據找到的min和max值進行偽量化操作,更新min和max分別為running和moving,跟batch normal算子一樣,這裡不進行過多的講述,具體在Mindspore框架中會自動根據網絡模型的結構進行自動插入不同的形式,具體用戶不感知。
running minimum的計算公式為:
Running maximum的計算公式為:
Moving minimum的計算公式為:
Moving maximum的計算公式為:
2. BN摺疊
初步實施方案中構圖比較複雜的主要集中在如何拆分BN層,本節將會對拆分的原理進行細化,落實確定到每一個算子上面,包括每個算子的具體計算公式,控制原理。
a. BN Fold原理
基本卷積操作為:
經過BN層處理後:
拆分上式得到:
定義:
因此conv+batch normal兩個算子在推理的時候,合起來融合為一個conv算子:
網絡模型中經常使用BN層對數據進行規約,有效降低上下層之間的數據依賴性。然而大部分在推理框架當中都會對BN層和卷積操作進行融合,為了更好地模擬在推理的時候的算子融合操作,這裡對BN層進行folding處理。下面左邊圖是(a)普通訓練時模型,右邊圖是(b) 融合後推理時模型。

下面圖中左邊是BN摺疊的BN folding訓練模型,右邊是BN folding感知量化訓練模型。

b. Correction數據矯正
在計算方差的時候,論文並沒有提及貝塞爾校正,因為貝塞爾校正是通用的統計學方法,用於校正方差。
具體對應於樣本標準差為:
貝塞爾校正的樣本標準差為:
因此對應貝塞爾因子為:
由於每次更新batch參數的delta的時候,都是使用當前batch的統計數據,這會使得權重參數連帶着一起被當前的batch影響,為了避免當前權重數據w的抖動,加入correction的校正因子將權重縮放到長期batch統計數據中。
模型開始訓練的時候會在fold conv卷積的輸出除以correction因子,這樣的操作是為了讓模型直接去學習正常的BN操作(根據當前的batch進行學習),在學習到一定程度之後,凍結當前的BN不再更新全局delta,然後fold conv卷積的操作中直接作用,並同時修改bias,作為correction_2更新到ADD算子中。
Frozen前:
Frozen後:
加上correction能夠有效地抑制在後期階段weight的數據波動。
c. BN FOLD訓練圖
組合模式ConvD+BN+ReLU拆分子圖並加入FakeQuant算子,一共拆分為為以下幾個算子:Conv2D、BatchNormFold、CorrectionMul、MulFold、FakeQuantWithMinMaxPreChannel、ConvMul、CorrectionAdd、AddFold、ReLU、FakeQuantWithMinMax。
1) Conv2D (in: x, weight; out: y):普通卷積,用於計算BatchNormFold的入參:
2) BatchNormFold ( ):FoldBN,用於計算當前 和 ,並使用CMA算法更新 和 ,運行時使用 和 。該算子輸出 並不作用於網絡,因此該算子實際計算公式為更新 :
3) CorrectionMul ( ):對w乘以校正因子。由於每次更新batch參數的 的時候,都是使用當前batch的統計數據,這會使得權重參數連帶着一起被當前的batch影響,為了避免當前權重數據w的抖動,加入correction校正因子將權重縮放到長期batch統計數據中:
4) MulFold ( ):根據batch mean參數對w進行規約,模擬融合操作:
5) FakeQuantWithMinMaxPreChannel (in: w, delay; out: self):控制流delay,訓練模型中插入偽量化節點fake quant來模擬量化引入的誤差,推薦權重按PerChannel模式。
6) Conv2D (in: w, x, out:x):實際作用的卷積:
7) ConvMul ( ):控制流freeze,模型開始訓練的時候會在fold conv卷積的輸出除以correction校正因子,這樣的操作是為了讓模型直接去學習正常的BN操作(根據當前的batch進行學習);在學習到一定程度之後,凍結當前的BN不再更新全局。
8) CorrectionAdd ( ):控制流freeze,在學習到一定程度之後凍結當前BN,校正因子修正bias偏置。
9) AddFold ( ):作用於bias偏置,BN融合後剩餘參數作用於bias偏置:
10) ReLU (in:x, out: x):實際作用的激活函數;
11) FakeQuantWithMinMax(in:x, min, max, delay; out: x):控制流delay,訓練模型中插入偽量化節點fake quant來模擬量化引入的誤差,並用指數移動平均算法更新min和max:
下面左邊為原始設計bn摺疊訓練圖,右邊是實際Mindspore執行經過優化融合的訓練圖。

圖中主要注意的點為BN_Fold_1和BN_Fold_2,其中BN_Fold_1的作用有兩個:拆分融合的BN層對weight的影響,和對權重數據進行校正;BN_Fold_2的作用有兩個:拆分融合的BN層對bias的作用影響,和對bias數據進行校正。
d. BN FOLD推理圖
組合模式ConvD+BN+ReLU拆分子圖並加入FakeQuant算子,一共拆分為以下個算子:Conv2D、BatchNormFold、MulFold、FakeQuantWithMinMaxPreChannel、AddFold。
1) Conv2D (in: x, weight; out: y):普通卷積,用於計算BatchNormFold的入參:
2) BatchNormFold ( ):開根號作用:
3) MulFold ( ):根據BN參數對w進行規約,模擬融合操作:
4) FakeQuantWithMinMaxPreChannel (in: w, delay; out: self):訓練模型中插入偽量化節點fake quant來模擬量化引入的誤差,推薦權重按PerChannel模式。
5) Conv2D (in: w, x, out:x):實際作用的卷積:
6) AddFold ( ):作用於bias偏置,BN融合後剩餘參數作用於bias偏置:
正向推理驗證圖,上面的所有公式都會化為這個圖的實際計算方式。

訓練後靜態量化(Post Calibration Quantization),同時也稱為校正量化或者數據集量化。其原理是對於Mindspore在端測低比特推理的時候(Inference),需要生成一個校準表來量化模型。其核心是取得數據值的量化參數表。
1. 權值量化權值在進行推理加速時均已確定,因此不需要對權值進行校準。如果使用對稱量化方案,max使用權值的絕對值的最大值,對於非對稱量化算法,max和min使用權值的最大值和最小值。
根據算法驗證結果,對於Convolution,每個卷積核按照per channel的方式採用一組獨立的量化係數(scale和offset),量化後推理精度較高。因此,Convolution權值的量化根據卷積核數量分組進行,計算得到的scale和offset的數量與卷積核數量相同。Dense的權值使用一組scale和offset。
2. 數據量化數據量化是對每個要量化的Operation的輸入數據進行統計,每個Operation計算出最優的一組scale和offset。
數據是推理計算的中間結果,其數據的範圍與輸入高度相關,需要使用一組參考輸入作為激勵,得到每個Operation的輸入數據用於確定量化max和min。數據的範圍與輸入相關,為了使確定的min和max在網絡接收不同輸入時有更好的魯棒性,因此提出基於統計分布確定min和max的方案。
該方案的思路為最小化量化後數據的統計分布與原始高精度數據的統計分布差異性,操作流程如下:
在上述操作中,涉及的超參數包括進行直方圖統計時選取的直方圖bin個數、min和max的搜索空間、統計分布差異性的指標。
對於直方圖bin個數,該參數直接反應了直方圖統計特徵的分布數個數,由於數據經過量化後會集中到256個離散的點上,因此bin的個數不宜過大,否則絕大多數的bin都沒有數值。
max的搜索空間可以通過search_start_scale,search_end_scale與search_step來確定。
search_step為搜索空間中每次搜索的值與seach_value的比值步進值。以max_candidate=100,search_start_scale=0.8,search_end_scale=1.2,search_step=0.01為例,對稱量化算法下,其定義的max搜索空間為從100*0.8=80到100*1.2=120的範圍,每次步進100*0.01=1,一共41個d_max搜索值;非對稱量化算法下,搜索0.8*(max–min) ~ 1.2*(max–min),確定最好的一個係數。
繼續舉多一個例子, search_start_scale =0.3,search_step=0.01,search_end_scale==1.7,bin=150。需要在0.3*max~1.7*max這個範圍中找一個最好的max,搜索步長是0.01max,因此需要搜索(1.7-0.3)/0.01 + 1 = 141個max數值。直方統計的bin個數也可以設置,假設當前是150。對於算法方案一,將0-2*max的數據分為150段,統計數據落在每段中的頻率,使用數據的絕對值統計,對於算法方案二,在0.3*(max – min)~1.7*(max - min)這個範圍中找一個最好的ratio,將0-2*(max - min)的數據分為150段,統計數據落在每段中的頻率,使用data – min的值來統計頻率。141個數值都要統計,因此一個量化算子需要存儲141*150個數值。多個batch情況下對frequancy進行累加。
統計分布差異性的指標為計算兩個長度為n直方圖、分布之間的信息差異度,選取的指標包括如下三種:
1) Kullback-Leibler Divergence(KL散度) 計算方式如下:
2) Symmetric Kullback-Leibler Divergence(對稱KL散度):對於 、 兩個分布, 相對 與 相對 的KL Divergence是不同的,Symmetric KL Divergence的計算方式為 相對 與 相對的KL Divergence的均值,計算方式如下:
3) Jensen-Shannon Divergence(JS散度): 首先生成一個新的分布M,為與的均值,JS Divergence為相對M的KL Divergence與相對M的KL Divergence的均值, 計算方式如下:
3. Calibration流程
a. Calibration功能
離線Calibration需要完成以下功能:
b. Calibration過程
Calibration過程可以分為4步:
值得注意的是,min不一定是所有數據batch中的最小值,max也不一定是所有batch中的最大值,與min_percentile和max percentile的值相關。
假設每個batch處理10張圖片,共100個batch,某個op的1張圖片輸入數據是1000個數,max_percentile = 0.99999,數據總量是10*100*1000 = 1000000個數。1000000*0.99999 = 999990。把所有輸入數據從大到小排序,max取第10個數。因此需要緩存10個數,對第一個batch的輸入1000個數進行從大到小排序,取前10大的數進行緩存,第二個batch的輸入1000個數進行從大到小排序,取前10個數,與緩存的10個數共20個數進行排序,取前10大的數,以此類推,最終獲得所有batch數據中前10大的數。
Inference有兩種方式,第一種是數據不做量化進行推理,第二種是數據量化後進行推理。數據量化是指算子的當前batch輸入數據使用當前batch的max和min進行量化,將數據量化為INT8,再由INT8轉回FP32進行inference計算。
第二次inference,進行數據的直方統計。根據第2步已經根據max_percentile找到需要的max的值。
最後,計算分布差異指標,根據指標選擇最好的min和max,然後計算出數據的scale和offset,根據數據和權值的scale,進行bias量化。
c. 搜索空間
影響搜索空間的參數可以分為兩類:一類是增加搜索組合的數量的可以稱之為配置參數,一類是影響單個模型結果的稱之為超參數(不增加結果數量)。
1.1.4 端測量化推理端側量化推理的結構方式主要由3種,分別是下圖的(a) Fp32輸入Fp32輸出、(b) Fp32輸入int8輸出、(c) int8輸入int32輸出。

INT8卷積示意圖,裡面混合里三種不同的模式,因為不同的卷積通過不同的方式進行拼接。

使用INT8進行inference時,由於數據是實時的,因此數據需要在線量化,量化的流程如圖所示。數據量化涉及Quantize,Dequantize和Requantize等3種操作。
1. Quantize量化將float32數據量化為int8。離線轉換工具轉換的過程之前,計算出數據量化需要的scale和offset,如果採用對稱量化算法,則根據公式4進行數據量化,如果採用非對稱量化算法,則根據本文公式6進行數據量化。
2. Dequantize反量化INT8相乘、加之後的結果用INT32格式存儲,如果下一Operation需要float32格式數據作為輸入,則通過Dequantize反量化操作將INT32數據反量化為float32。
Dequantize反量化推導過程如下:
因此反量化需要input和weight的scale。值得注意的是,後面實際的公式約減了 、 和 ,是因為在實際網絡的運行和測試過程結果表明,發現這兩個參數對網絡模型的精度並不影響,其作用相當於bias add,因此故作減約。
3. Requantize重量化INT8乘加之後的結果用INT32格式存儲,如果下一層需要INT8格式數據作為輸入,則通過Requantize重量化操作將INT32數據重量化為INT8。
重量化推導過程如下:
其中y為下一個節點的輸入,即 :
有:
因此重量化需要本Operation輸入input和weight的scale,以及下一Operation的input輸入數據的scale和offset。
4. Conv2d的INT8計算計算公式如下:
其中,P為與w矩陣相同大小的全1矩陣,Q為與x矩陣相同大小的全1矩陣
其中, 是量化後INT8權值, 是量化後INT8數據, 是量化後INT32的bias。
c3項可以在離線時計算好,作為新的bias參數傳入。c1和c2項需要在線計算。Conv2d的INT8計算根據輸入是float32還是int8決定是否需要插入Quantize OP,根據輸出是float32還是int8決定輸出是插入Dequantize OP還是Requantize OP。
如果覺得有用,就請分享到朋友圈吧!
公眾號後台回復「transformer」獲取最新Transformer綜述論文下載~

#CV技術社群邀請函#

備註:姓名-學校/公司-研究方向-城市(如:小極-北大-目標檢測-深圳)
即可申請加入極市目標檢測/圖像分割/工業檢測/人臉/醫學影像/3D/SLAM/自動駕駛/超分辨率/姿態估計/ReID/GAN/圖像增強/OCR/視頻理解等技術交流群
每月大咖直播分享、真實項目需求對接、求職內推、算法競賽、乾貨資訊匯總、與10000+來自港科大、北大、清華、中科院、CMU、騰訊、百度等名校名企視覺開發者互動交流~
