int 8量化
感覺深度學習在移動端的全面開花就在這兩年了,其實感覺已經開始開花了。
先說說量化是怎麼一回事,目前我們在caffe, tensorflow等框架上訓練模型(前向和反向)都是使用float 32的,與int 8相比,所需儲存空間更大,但是精度更好。
量化目前來講,有兩種方式,一種是通過訓練量化finetune原來的模型,另一種是直接對模型和計算進行量化。這篇文章先來講不使用finetune,直接對訓練完畢的模型進行進行量化。
在深度學習中,對float 32進行int 8量化,使其模型尺寸更小、推斷更快、耗電更低。唯一的缺點,模型精度會下降。
先比較一下,float 32 和 int 8有什麼區別
Dynamic Range(兩種數據類型的數值範圍)
FP32 -3.4 x 10^38 ~ +3.4 x 10^38
INT8 -128 ~ +127
其實量化過程很簡單,更高精度的向低精度的範圍進行映射。
當bias=0時,就是正負對稱做的一個對稱的量化
圖片來自於《8-bit inference with tensor RT》,版權歸nvidia所有
在量化過程中,又可以分兩個部分,一是模型參數weights,模型一般可以直接使用No saturation的方式直接進行量化, .
另一部分就是計算過程中的值的量化activations,這部分我們就選擇Saturate的方法,這種方法就有一個閾值選擇的過程。
在《8-bit inference with tensor RT》 文章中,對threshold的選擇使用的是相對熵(kl divergence),在離散情況下的相對熵
在一個驗證數據集上,以一個batch為例,對該batch的每一層計算頻率直方圖(FP32 histogram H with 2048 bins: bin[ 0 ], ..., bin[ 2047 ])
圖片來自於《8-bit inference with tensor RT》版權歸nvidia所有
當然在這片文章中的量化方法還是比較簡單的,對於Resnet、googlenet之類的比較複雜的網路,效果還是不錯的,精度損失的比較小,但是對於mobilenet、shufflenet之類的本身比較精簡的網路精度損失還是比較明顯的,特別是應用在檢測網路架構中的時候。
另外一篇google的文章《Quantizing deep convolutional networks for efficient inference: A whitepaper》。這篇論文是在上述的量化方法上進行優化的,對上面的方法有兩個方面的補充。
首先提出了一個對稱量化和非對稱量化的概念,即在公式(1)中的bias,在nvidia的文章中,bias=0(在他的文章中提到並不需要偏置)就是對稱量化的概念,0量化後還是0; 的情況就是非對稱量化,但是這其中需要注意的是bias的需要是整型,因為在深度學習的模型中,有太多的0-padding存在了,若是bias非整型,那麼在量化過程中會有大量的數值0的精度收到損失。
第二個提出了逐層量化和逐通道量化的概念,從字面非常容易理解兩個量化的區別,我們也看到在nvidia的方法中使用了逐層量化的方法,每一層採用同一個閾值來進行量化。逐通道量化就是對每一層每個通道都有各自的閾值,對精度有一個很好的提升。
對量化是閾值的選取計算,這篇文章採用了更簡單的方法。對於權重,使用實際的最大和最小值來決定量化參數。對於激活輸出,使用跨批(batches)的最大和最小值的滑動平均值來決定量化參數。
最後來看一下效果,文章中只有分類網路,對於檢測網路的精度下降的結果,還在實驗中。
圖片來自於《Quantizing deep convolutional networks for efficient inference: A whitepaper》版權歸google所有
還有訓練中的量化,之後的文章再講。
[1] Szymon Migacz. 8-bit Inference with TensorRT
[2] Raghuraman Krishnamoorthi. Quantizing deep convolutional networks for efficient inference: A whitepaper
[3] BUG1989/caffe-int8-convert-tools
[4] Tencent/ncnn
推薦閱讀: