本項目應用PaddleSlim對YOLOv3進行量化訓練,從而對模型進行壓縮,提升其在端上運行的性能。 在量化訓練的過程當中加入了MAP的計算,實時的評估訓練過程當中的效果。node
PaddleSlim是一個模型壓縮工具庫,包含模型剪裁、定點量化、知識蒸餾、超參搜索和模型結構搜索等一系列模型壓縮策略。python
對於業務用戶,PaddleSlim提供完整的模型壓縮解決方案,可用於圖像分類、檢測、分割等各類類型的視覺場景。 同時也在持續探索NLP領域模型的壓縮方案。另外,PaddleSlim提供且在不斷完善各類壓縮策略在經典開源任務的benchmark, 以便業務用戶參考。git
對於模型壓縮算法研究者或開發者,PaddleSlim提供各類壓縮策略的底層輔助接口,方便用戶復現、調研和使用最新論文方法。 PaddleSlim會從底層能力、技術諮詢合做和業務場景等角度支持開發者進行模型壓縮策略相關的創新工做。github
模型剪裁算法
定點量化網絡
知識蒸餾框架
神經網絡結構自動搜索(NAS)分佈式
近年來,定點量化使用更少的比特數(如8-bit、3-bit、2-bit等)表示神經網絡的權重和激活已被驗證是有效的。定點量化的優勢包括低內存帶寬、低功耗、低計算資源佔用以及低模型存儲需求等。 工具
表1: 不一樣類型操做的開銷對比post
由表1可知,低精度定點數操做的硬件面積大小及能耗比高精度浮點數要少幾個數量級。 使用定點量化可帶來4倍的模型壓縮、4倍的內存帶寬提高,以及更高效的cache利用(不少硬件設備,內存訪問是主要能耗)。除此以外,計算速度也會更快(一般具備2x-3x的性能提高)。由表2可知,在不少場景下,定點量化操做對精度並不會形成損失。另外,定點量化對神經網絡於嵌入式設備上的推斷來講是極其重要的。
表2:模型量化先後精度對比
目前,學術界主要將量化分爲兩大類:Post Training Quantization
和Quantization Aware Training
。Post Training Quantization
是指使用KL散度、滑動平均等方法肯定量化參數且不須要從新訓練的定點量化方法。Quantization Aware Training
是在訓練過程當中對量化進行建模以肯定量化參數,它與Post Training Quantization
模式相比能夠提供更高的預測精度。
目前,存在着許多方法能夠將浮點數量化成定點數。例如:
r=min(max(x,a),b)r = min(max(x, a), b) r=min(max(x,a),b)
s=b−an−1s = \frac{b - a}{n - 1} s=n−1b−a
q=⌊r−as⌉q = \left \lfloor \frac{r - a}{s} \right \rceil q=⌊sr−a⌉
式中,xxx是待量化的浮點值,[a,b][a, b][a,b]是量化範圍,aaa是待量化浮點數中的最小值, bbb 是待量化浮點數中的最大值。⌊⌉\left \lfloor \right \rceil⌊⌉ 表示將結果四捨五入到最近的整數。若是量化級別爲kkk,則nnn爲2k2^k2k。例如,若kkk爲8,則nnn爲256。qqq是量化獲得的整數。 PaddleSlim框架中選擇的量化方法爲最大絕對值量化(max-abs
),具體描述以下:
M=max(abs(x))M = max(abs(x)) M=max(abs(x))
q=⌊xM∗(n−1)⌉q = \left \lfloor \frac{x}{M} * (n - 1) \right \rceil q=⌊Mx∗(n−1)⌉
式中,xxx是待被量化的浮點值,MMM是待量化浮點數中的絕對值最大值。⌊⌉\left \lfloor \right \rceil⌊⌉表示將結果四捨五入到最近的整數。對於8bit量化,PaddleSlim採用int8_t
,即n=27=128n=2^7=128n=27=128。qqq是量化獲得的整數。 不管是min-max量化
仍是max-abs量化
,他們均可以表示爲以下形式: q=scale∗r+bq = scale * r + bq=scale∗r+b 其中min-max
和max-abs
被稱爲量化參數或者量化比例或者量化範圍。
1.2.2.1 前向傳播
前向傳播過程採用模擬量化的方式,具體描述以下:
圖1:基於模擬量化訓練的前向過程
由圖1可知,基於模擬量化訓練的前向過程可被描述爲如下四個部分:
GEMM
),輸入XXX和權重WWW的量化操做可被表述爲以下過程:Xq=⌊XXm∗(n−1)⌉X_q = \left \lfloor \frac{X}{X_m} * (n - 1) \right \rceil Xq=⌊XmX∗(n−1)⌉
Wq=⌊WWm∗(n−1)⌉W_q = \left \lfloor \frac{W}{W_m} * (n - 1) \right \rceil Wq=⌊WmW∗(n−1)⌉
執行通用矩陣乘法:
Yq=Xq∗WqY_q = X_q * W_q Yq=Xq∗Wq
對量化乘積結果YqYqYq進行反量化:
Ydq=Yq(n−1)∗(n−1)∗Xm∗Wm=Xq∗Wq(n−1)∗(n−1)∗Xm∗Wm=(Xqn−1∗Xm)∗(Wqn−1∗Wm)Y_{dq} = \frac{Y_q}{(n - 1) * (n - 1)} * X_m * W_m = \frac{X_q * W_q}{(n - 1) * (n - 1)} * X_m * W_m = (\frac{X_q}{n - 1} * X_m) * (\frac{W_q}{n - 1} * W_m) Ydq=(n−1)∗(n−1)Yq∗Xm∗Wm=(n−1)∗(n−1)Xq∗Wq∗Xm∗Wm=(n−1Xq∗Xm)∗(n−1Wq∗Wm)
上述公式代表反量化操做能夠被移動到GEMM
以前,即先對XqXqXq和WqWqWq執行反量化操做再作GEMM
操做。所以,前向傳播的工做流亦可表示爲以下方式:
圖2:基於模擬量化訓練前向過程的等價工做流
訓練過程當中,PaddleSlim使用圖2中所示的等價工做流。在設計中,量化Pass在IrGraph中插入量化op和反量化op。由於在連續的量化、反量化操做以後輸入仍然爲32-bit浮點型數據。所以,PaddleSlim量化訓練框架所採用的量化方式被稱爲模擬量化。
1.2.2.2 反向傳播
由圖3可知,權重更新所需的梯度值能夠由量化後的權重和量化後的激活求得。反向傳播過程當中的全部輸入和輸出均爲32-bit浮點型數據。注意,梯度更新操做須要在原始權重上進行,即計算出的梯度將被加到原始權重上而非量化後或反量化後的權重上。
圖3:基於模擬量化訓練的反向傳播和權重更新過程
所以,量化Pass也會改變相應反向算子的某些輸入。
1.2.2.3 肯定量化比例係數
存在着兩種策略能夠計算求取量化比例係數,即動態策略和靜態策略。動態策略會在每次迭代過程當中計算量化比例係數的值。靜態策略則對不一樣的輸入採用相同的量化比例係數。 對於權重而言,在訓練過程當中採用動態策略。換句話說,在每次迭代過程當中量化比例係數均會被從新計算獲得直至訓練過程結束。 對於激活而言,能夠選擇動態策略也能夠選擇靜態策略。若選擇使用靜態策略,則量化比例係數會在訓練過程當中被評估求得,且在推斷過程當中被使用(不一樣的輸入均保持不變)。靜態策略中的量化比例係數可於訓練過程當中經過以下三種方式進行評估:
在一個窗口中計算激活最大絕對值的平均值。
在一個窗口中計算激活最大絕對值的最大值。
在一個窗口中計算激活最大絕對值的滑動平均值,計算公式以下:
Vt=(1−k)∗V+k∗Vt−1Vt = (1 - k) * V + k * V_{t-1} Vt=(1−k)∗V+k∗Vt−1
式中,VVV 是當前batch的最大絕對值, VtVtVt是滑動平均值。kkk是一個因子,例如其值可取爲0.9。
訓練後量化是基於採樣數據,採用KL散度等方法計算量化比例因子的方法。相比量化訓練,訓練後量化不須要從新訓練,能夠快速獲得量化模型。
訓練後量化的目標是求取量化比例因子,主要有兩種方法:非飽和量化方法 ( No Saturation) 和飽和量化方法 (Saturation)。非飽和量化方法計算FP32類型Tensor中絕對值的最大值abs_max
,將其映射爲127,則量化比例因子等於abs_max/127
。飽和量化方法使用KL散度計算一個合適的閾值T
(0<T<mab_max
),將其映射爲127,則量化比例因子等於T/127
。通常而言,對於待量化op的權重Tensor,採用非飽和量化方法,對於待量化op的激活Tensor(包括輸入和輸出),採用飽和量化方法 。
訓練後量化的實現步驟以下:
DataLoader
;論文原文:https://arxiv.org/pdf/1804.02767v1.pdf
參考連接:https://blog.csdn.net/litt1e/article/details/88907542
code/ ├── model ├── pretrained_model 預訓練模型 ├── YOLOv3.py 以darknet53爲主幹網絡的yolov3(原版yolov3) ├── reader.py 數據讀取腳本 ├── train.py 量化訓練腳本 ├── infer.py 預測腳本 ├── config.py 配置參數腳本 ├── compress.yaml 量化訓練參數配置腳本 ├── train_list.txt 訓練數據列表 ├── val_list.txt 驗證數據列表 ├── label_list label列表
version: 1.0 strategies: quantization_strategy: class: 'QuantizationStrategy' start_epoch: 0 end_epoch: 4 float_model_save_path: './output/yolov3/float' mobile_model_save_path: './output/yolov3/mobile' int8_model_save_path: './output/yolov3/int8' weight_bits: 8 activation_bits: 8 weight_quantize_type: 'abs_max' activation_quantize_type: 'abs_max' save_in_nodes: ['img', 'image_shape'] save_out_nodes: ['multiclass_nms.tmp_0'] compressor: epoch: 5 checkpoint_path: './checkpoints/yolov3/' strategies: - quantization_strategy
本項目採用Pascal VOC數據集,數據集具體介紹能夠參考https://blog.csdn.net/u013832707/article/details/80060327
本項目根據實際須要,將VOC數據集的Annotation文件作了進一步整理,寫入在code/train_list.txt, code/val_list.txt方便reader調用
#解壓數據集,並將voc數據集的訓練和驗證文件拷貝到相應位置
!cd data/data4379/ && unzip -qo pascalvoc.zip
!cd data/data4379/pascalvoc/ && rm label_list
!cp code/train_list.txt data/data4379/pascalvoc/
!cp code/val_list.txt data/data4379/pascalvoc/
!cp code/label_list data/data4379/pascalvoc/
#模型訓練
!cd code && python train.py
#模型預測 !cd code && python infer.py ######檢測結果可視化 %matplotlib inline import os import matplotlib.pyplot as plt import numpy as np import cv2 if os.path.exists('code/result.jpg'): detect_img= cv2.imread('code/result.jpg') plt.imshow(detect_img) plt.show()
W0323 16:50:33.122778 298 device_context.cc:236] Please NOTE: device: 0, CUDA Capability: 70, Driver API Version: 9.2, Runtime API Version: 9.0 W0323 16:50:33.126850 298 device_context.cc:244] device: 0, cuDNN Version: 7.3. predict cost time:44.95 ms 檢測到目標 檢測結果保存爲result.jpg infer one picture cost 44.952392578125 ms
使用AI Studio一鍵上手實踐項目吧:https://aistudio.baidu.com/aistudio/projectdetail/316757