本项目应用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