基於PaddleSlim對目標檢測模型YOLOv3進行量化訓練

項目簡介

本項目應用PaddleSlim對YOLOv3進行量化訓練,從而對模型進行壓縮,提升其在端上運行的性能。 在量化訓練的過程當中加入了MAP的計算,實時的評估訓練過程當中的效果。node

 

PaddleSlim簡介

PaddleSlim是一個模型壓縮工具庫,包含模型剪裁、定點量化、知識蒸餾、超參搜索和模型結構搜索等一系列模型壓縮策略。python

對於業務用戶,PaddleSlim提供完整的模型壓縮解決方案,可用於圖像分類、檢測、分割等各類類型的視覺場景。 同時也在持續探索NLP領域模型的壓縮方案。另外,PaddleSlim提供且在不斷完善各類壓縮策略在經典開源任務的benchmark, 以便業務用戶參考。git

對於模型壓縮算法研究者或開發者,PaddleSlim提供各類壓縮策略的底層輔助接口,方便用戶復現、調研和使用最新論文方法。 PaddleSlim會從底層能力、技術諮詢合做和業務場景等角度支持開發者進行模型壓縮策略相關的創新工做。github

功能

  • 模型剪裁算法

    • 卷積通道均勻剪裁
    • 基於敏感度的卷積通道剪裁
    • 基於進化算法的自動剪裁
  • 定點量化網絡

    • 在線量化訓練(training aware)
    • 離線量化(post training)
  • 知識蒸餾框架

    • 支持單進程知識蒸餾
    • 支持多進程分佈式知識蒸餾
  • 神經網絡結構自動搜索(NAS)分佈式

    • 支持基於進化算法的輕量神經網絡結構自動搜索
    • 支持One-Shot網絡結構自動搜索
    • 支持 FLOPS / 硬件延時約束
    • 支持多平臺模型延時評估
    • 支持用戶自定義搜索算法和搜索空間

本項目主要展現PaddleSlim在目標檢測模型YOLOv3上的量化訓練。

基於PaddleSlim量化訓練原理:

1.1 背景

近年來,定點量化使用更少的比特數(如8-bit、3-bit、2-bit等)表示神經網絡的權重和激活已被驗證是有效的。定點量化的優勢包括低內存帶寬、低功耗、低計算資源佔用以及低模型存儲需求等。 工具

表1: 不一樣類型操做的開銷對比post

由表1可知,低精度定點數操做的硬件面積大小及能耗比高精度浮點數要少幾個數量級。 使用定點量化可帶來4倍的模型壓縮、4倍的內存帶寬提高,以及更高效的cache利用(不少硬件設備,內存訪問是主要能耗)。除此以外,計算速度也會更快(一般具備2x-3x的性能提高)。由表2可知,在不少場景下,定點量化操做對精度並不會形成損失。另外,定點量化對神經網絡於嵌入式設備上的推斷來講是極其重要的。

表2:模型量化先後精度對比

目前,學術界主要將量化分爲兩大類:Post Training QuantizationQuantization Aware TrainingPost Training Quantization是指使用KL散度、滑動平均等方法肯定量化參數且不須要從新訓練的定點量化方法。Quantization Aware Training是在訓練過程當中對量化進行建模以肯定量化參數,它與Post Training Quantization模式相比能夠提供更高的預測精度。

1.2 量化原理

1.2.1 量化方式

目前,存在着許多方法能夠將浮點數量化成定點數。例如:

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=n1ba

q=⌊r−as⌉q = \left \lfloor \frac{r - a}{s} \right \rceil q=sra

式中,xxx是待量化的浮點值,[a,b][a, b][a,b]是量化範圍,aaa是待量化浮點數中的最小值, bbb 是待量化浮點數中的最大值。⌊⌉\left \lfloor \right \rceil 表示將結果四捨五入到最近的整數。若是量化級別爲kkk,則nnn2k2^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(n1)

式中,xxx是待被量化的浮點值,MMM是待量化浮點數中的絕對值最大值。⌊⌉\left \lfloor \right \rceil表示將結果四捨五入到最近的整數。對於8bit量化,PaddleSlim採用int8_t,即n=27=128n=2^7=128n=27=128qqq是量化獲得的整數。 不管是min-max量化仍是max-abs量化,他們均可以表示爲以下形式: q=scale∗r+bq = scale * r + bq=scaler+b 其中min-maxmax-abs被稱爲量化參數或者量化比例或者量化範圍。

1.2.2 量化訓練

1.2.2.1 前向傳播

前向傳播過程採用模擬量化的方式,具體描述以下:

圖1:基於模擬量化訓練的前向過程

由圖1可知,基於模擬量化訓練的前向過程可被描述爲如下四個部分:

  1. 輸入和權重均被量化成8-bit整數。
  2. 在8-bit整數上執行矩陣乘法或者卷積操做。
  3. 反量化矩陣乘法或者卷積操做的輸出結果爲32-bit浮點型數據。
  4. 在32-bit浮點型數據上執行偏置加法操做。此處,偏置並未被量化。 對於通用矩陣乘法(GEMM),輸入XXX和權重WWW的量化操做可被表述爲以下過程:

Xq=⌊XXm∗(n−1)⌉X_q = \left \lfloor \frac{X}{X_m} * (n - 1) \right \rceil Xq=XmX(n1)

Wq=⌊WWm∗(n−1)⌉W_q = \left \lfloor \frac{W}{W_m} * (n - 1) \right \rceil Wq=WmW(n1)

執行通用矩陣乘法:

Yq=Xq∗WqY_q = X_q * W_q Yq=XqWq

對量化乘積結果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=(n1)(n1)YqXmWm=(n1)(n1)XqWqXmWm=(n1XqXm)(n1WqWm)

上述公式代表反量化操做能夠被移動到GEMM以前,即先對XqXqXqWqWqWq執行反量化操做再作GEMM操做。所以,前向傳播的工做流亦可表示爲以下方式:

圖2:基於模擬量化訓練前向過程的等價工做流

訓練過程當中,PaddleSlim使用圖2中所示的等價工做流。在設計中,量化Pass在IrGraph中插入量化op和反量化op。由於在連續的量化、反量化操做以後輸入仍然爲32-bit浮點型數據。所以,PaddleSlim量化訓練框架所採用的量化方式被稱爲模擬量化。

1.2.2.2 反向傳播

由圖3可知,權重更新所需的梯度值能夠由量化後的權重和量化後的激活求得。反向傳播過程當中的全部輸入和輸出均爲32-bit浮點型數據。注意,梯度更新操做須要在原始權重上進行,即計算出的梯度將被加到原始權重上而非量化後或反量化後的權重上。

圖3:基於模擬量化訓練的反向傳播和權重更新過程

所以,量化Pass也會改變相應反向算子的某些輸入。

1.2.2.3 肯定量化比例係數

存在着兩種策略能夠計算求取量化比例係數,即動態策略和靜態策略。動態策略會在每次迭代過程當中計算量化比例係數的值。靜態策略則對不一樣的輸入採用相同的量化比例係數。 對於權重而言,在訓練過程當中採用動態策略。換句話說,在每次迭代過程當中量化比例係數均會被從新計算獲得直至訓練過程結束。 對於激活而言,能夠選擇動態策略也能夠選擇靜態策略。若選擇使用靜態策略,則量化比例係數會在訓練過程當中被評估求得,且在推斷過程當中被使用(不一樣的輸入均保持不變)。靜態策略中的量化比例係數可於訓練過程當中經過以下三種方式進行評估:

  1. 在一個窗口中計算激活最大絕對值的平均值。

  2. 在一個窗口中計算激活最大絕對值的最大值。

  3. 在一個窗口中計算激活最大絕對值的滑動平均值,計算公式以下:

Vt=(1−k)∗V+k∗Vt−1Vt = (1 - k) * V + k * V_{t-1} Vt=(1k)V+kVt1

式中,VVV 是當前batch的最大絕對值, VtVtVt是滑動平均值。kkk是一個因子,例如其值可取爲0.9。

1.2.4 訓練後量化

訓練後量化是基於採樣數據,採用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(包括輸入和輸出),採用飽和量化方法 。

訓練後量化的實現步驟以下:

  • 加載預訓練的FP32模型,配置DataLoader
  • 讀取樣本數據,執行模型的前向推理,保存待量化op激活Tensor的數值;
  • 基於激活Tensor的採樣數據,使用飽和量化方法計算它的量化比例因子;
  • 模型權重Tensor數據一直保持不變,使用非飽和方法計算它每一個通道的絕對值最大值,做爲每一個通道的量化比例因子;
  • 將FP32模型轉成INT8模型,進行保存。

參考連接

YOLOv3

論文原文:https://arxiv.org/pdf/1804.02767v1.pdf

參考連接:https://blog.csdn.net/litt1e/article/details/88907542

PaddleSlim

連接:https://github.com/PaddlePaddle/PaddleSlim

 

代碼結構

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列表
 

量化訓練參數配置腳本說明:compress.yaml

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

可配置的參數:

  • class: 量化策略的類名稱,目前僅支持QuantizationStrategy
  • start_epoch: 在start_epoch開始以前,量化訓練策略會往train_program和eval_program插入量化operators和反量化operators. 從start_epoch開始,進入量化訓練階段。
  • end_epoch: 在end_epoch結束以後,會保存用戶指定格式的模型。注意:end_epoch以後並不會中止量化訓練,而是繼續訓練到compressor.epoch爲止。
  • float_model_save_path: 保存float數據格式模型的路徑。模型weight的實際大小在int8可表示範圍內,可是是以float格式存儲的。若是設置爲None, 則不存儲float格式的模型。默認爲None.
  • int8_model_save_path: 保存int8數據格式模型的路徑。若是設置爲None, 則不存儲int8格式的模型。默認爲None.
  • mobile_model_save_path: 保存兼容paddle-mobile框架的模型的路徑。若是設置爲None, 則不存儲mobile格式的模型。默認爲None.
  • weight_bits: 量化weight的bit數,bias不會被量化。
  • activation_bits: 量化activation的bit數。
  • weight_quantize_type: 對於weight的量化方式,目前支持'abs_max', 'channel_wise_abs_max'.
  • activation_quantize_type: 對activation的量化方法,目前可選abs_max或range_abs_max。abs_max意爲在訓練的每一個step和inference階段動態的計算量化範圍。range_abs_max意爲在訓練階段計算出一個靜態的範圍,並將其用於inference階段。
  • save_in_nodes: variable名稱列表。在保存量化後模型的時候,須要根據save_in_nodes對eval programg 網絡進行前向遍歷剪枝。默認爲eval_feed_list內指定的variable的名稱列表。
  • save_out_nodes: varibale名稱列表。在保存量化後模型的時候,須要根據save_out_nodes對eval programg 網絡進行回溯剪枝。默認爲eval_fetch_list內指定的variable的名稱列表。
 

數據集

本項目採用Pascal VOC數據集,數據集具體介紹能夠參考https://blog.csdn.net/u013832707/article/details/80060327

本項目根據實際須要,將VOC數據集的Annotation文件作了進一步整理,寫入在code/train_list.txt, code/val_list.txt方便reader調用

In[1]
#解壓數據集,並將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/
In[2]
#模型訓練
!cd code && python train.py
In[3]
#模型預測
!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 

相關文章
相關標籤/搜索