一文搞懂模型量化

前言:我也是剛入行模型轉換的新人,目前從事模型轉換相關工作,參考大佬們的博客,結合自己的理解寫瞭這篇文章,如果有什麼寫錯的歡迎指出

原文鏈接:

What:什麼是模型量化

簡單來說,模型量化(Model Quantization)就是通過某種方法將浮點模型轉為定點模型。比如說原來的模型裡面的權重(weight)都是float32,通過模型量化,將模型變成權重(weight)都是int8的定點模型。

Why:為什麼需要模型量化

隨著深度學習(Deep Learning)的發現,其在計算機視覺(Computer Vision, CV)和自然語言處理(Natural Language Processing,NLP)等領域都取得瞭巨大的成功。通過深度學習,我們可以得到用於處理各種任務的高性能模型,這些模型大多都很復雜、一般隻適合在GPU上進行推理,並不適合在板端進行推理,然而在實際應用時,很多場景都需要將模型部署到板端。

為瞭解決模型難以部署到板端的問題,我們就需要通過模型量化來降低模型的復雜性,這個過程不可避免的會發生精度損失。

量化前的浮點模型和量化後的定點模型的特點:

量化前的浮點模型 量化後的定點模型
參數量大(float32) 壓縮參數(int8)
計算量大 提升速度
內存占用多 內存占用少
精度高 精度損失

How:怎麼進行模型量化

模型量化就是建立一種浮點數據和定點數據間的映射關系,使得以較小的精度損失代價獲得瞭較大的收益,要弄懂模型量化的原理就是要弄懂這種數據映射關系。

線性量化與非線性量化

線性量化

采用相同的量化間隔對輸入作量化

根據Z (zero_point) 是否為0,線性量化可以分為對稱量化和非對稱量化

非對稱量化

浮點0對應的值不是定點0

浮點和定點之間的映射公式:

其中,Q表示量化後的定點數,R表示量化前的浮點數,Z就是zero_point,即浮點數映射到定點之後,浮點0所對應的定點值。S就是scale,即縮放尺度。Round()函數就是四舍五入。clamp()函數的作用是把一個值限制在一個上限和下限之間。Tmax表示浮點數的最大閾值,Tmin表示浮點數的最小閾值。Qmax表示定數的最大值,Qmin表示定點數的最小值。

通過換算可以得到閾值和線性映射參數 S 和 Z 的數學關系,在確定瞭閾值後,也就確定瞭線性映射的參數。

數據類型 取值范圍
float32 -2^31 ~ 2^31-1
int8 -2^7 ~ 2^7-1 (-128 ~ 127)
uint8 0 ~ 2^8-1 (0~255)

從上述的映射關系中,如果知道瞭閾值,那麼其對應的線性映射參數也就知道瞭,整個量化過程也就明確瞭。

那麼該如何確定閾值呢?

一般來說,對於權重的量化,由於權重的數據分佈是靜態的,一般直接找出 MIN 和 MAX 線性映射即可;而對於推理激活值來說,其數據分佈是動態的,為瞭得到激活值的數據分佈,往往需要一個所謂校準集的東西來進行抽樣分佈,有瞭抽樣分佈後再通過一些量化算法進行量化閾值的選取(飽和量化)。

舉例:

模型訓練後權重或激活值往往在一個有限的范圍內分佈,如權重值范圍為[-2.0, 6.0],即Tmax = 6.0,Tmin = -2.0(非飽和量化)。然後我們用int8進行模型量化,則定點量化值范圍為[-128, 127],即Qmax = 127,Qmin = -127,那麼S和Z的求值過程如下:

可以得到如下對應關系:

浮點數 定點數
6.0 -128
0 -64
-2.0 127

得到量化參數S和Z後,我們就可以求任意一個浮點數對應的定點數,比如說有一個權重等於0.28,即R=0.28

對稱量化(一種特殊的非對稱量化)

浮點0對應的值就是定點0。對稱量化對於正負數不均勻分佈的情況不夠友好,比如如果浮點數全部是正數,量化後的數據范圍是[0, 127], [-128, 0]的范圍就浪費瞭,減弱瞭int8數據的表示范圍

非線性量化

對輸入進行量化時,大的輸入采用大的量化間隔,小的輸入采用小的量化間隔。

飽和量化與非飽和量化

一般而言,待量化 Op 的權重采用非飽和量化方法,待量化 Op 的激活(輸入和輸出)采用飽和量化方法

非飽和量化

非飽和量化是最本質也是最暴力的方法,即通過統計網絡模型中每一個層中權重或激活值的絕對最大值,將其映射到127,來計算出縮放因子scale,然後使用線性映射的方式將原始的浮點數據轉換到INT8的數據域中,如下圖(圖是從知乎帖子中拿來的,圖中-127應該替換為-128)

非飽和量化

飽和量化

因為模型數據(一般是激活數據)分佈可能是不均勻的,直接使用非飽和量化會使得量化後的值都擠在一個很小的范圍從而浪費瞭INT8范圍內的其他空間,也就是說沒有充分利用INT8(-128 ~ 127)的值域。因此我們在量化時,不是直接將數據的最大值映射到127,而是使用 KL 散度計算一個合適的閾值,將其映射為127。這樣使得映射後的-128 ~ 127范圍內分佈相對均勻,也相當於去掉瞭一些不重要的因素,保留瞭主要成分。飽和量化如下圖所示(圖是從知乎帖子中哪來的,圖中-127應該替換為-128)。

PTQ 與 QAT

後訓練量化(Post-Training Quantization, PTQ)

後訓練量化(PTQ)可以在沒有原始的訓練過程的情況下,就能將預訓練的FP32模型直接轉換為定點模型絡。PTQ最大的特點就是不需要數據或者隻需要很少的校準數據集。且PTQ幾乎不需要調整超參數,使得我們可以很方便的進行模型量化

量化感知訓練(Quantization Aware Training, QAT)

模型量化過程其實就是在做一件事,就是找閾值或者scale。

在PTQ中,閾值或者scale一般是通過統計的方法,然後人工通過一些分佈相似性得到的,然而,這肯定是有誤差的。而且,由於量化是每層獨立進行的,所以每層的量化是不依賴於前一層量化的結果的,這就導致瞭在實際的inference過程中會出現誤差累積的情況,進一步影響量化後的性能。所以,我們需要一種可學習的scale。QAT就是在做這樣一件事情。

簡單概括就是,我們在網絡訓練過程去模擬量化,我們通過設定一個可學習的scale,這個scale一般可以與權重或者激活值相綁定,然後我們利用一個量化過程 q = round(r/s)*127,將需要量化的值量化到0-127之間,再接著一個反量化過程q * s,就實現瞭一個誤差的傳遞,接著我們利用反量化後的結果繼續前傳,最後得到loss,我們求量化後權重的梯度,並用它來更新量化前的權重,使得這種誤差被網絡抹平,讓網絡越來越像量化後的權重靠近,最後我們得到瞭量化後的縮放因子s。而這一系列操作都可以寫成網絡中的一個op,實現網絡的正常訓練。

參考鏈接:

模型量化瞭解一下? – 知乎 (zhihu.com)

f="https://blog.csdn.net/WZZ18191171661/article/details/103332338">模型量化詳解技術挖掘者的博客-CSDN博客模型量化

Tensorflow模型量化(Quantization)原理及其實現方法 – 知乎 (zhihu.com)

模型量化-對稱量化和非對稱量化Briwisdom的博客-CSDN博客非對稱量化

【模型推理】談談幾種量化策略:MinMax、KLD、ADMM、EQ – 知乎 (zhihu.com)

INT8量化 – 知乎 (zhihu.com)

離線量化-靜態離線量化 — Paddle-Lite 文檔

再讀《神經網絡量化白皮書》- 0x03 訓練後量化(PTQ) – 知乎 (zhihu.com)

赞(0)