文章目录
- 一、离线量化基础概念
 - 1)离线量化定义
 - 2)离线量化优缺点
 - 3)如何生产一个硬件能跑的量化模型?
 - 4)离线量化的类型
 - 5)如何计算scale,zero_point?
 - 6)离线量化概念
 - 7)PTQ与QAT区别
 - 8)离线量化流程
 - 9)校准数据的选择
 - 10)量化模式选择
 - 11)校准方式的选择
 - 12)量化算法的选择(展示离线量化的pipeline)
 - 13)写入量化参数
 
- 二、离线量化难点
 - 三、离线量化算法介绍
 - 1)问题点
 - 2)Weight equalization(WE):使每个channel分布更接近,从而更适用于per-tensor量化
 - 3)Bias Correction(BC):从卷积或全连接层的bias剪掉权重的误差,准确率更接近per-channel量化
 - 4)AdaRound
 - 5)Brecq:解决AdaRound逐层重建忽略层间依赖关系的问题
 - 6)QDrop:随机失活激活量化
 - 7)离线量化算法--总结
 
- 四、离线量化工具介绍
 - 1)业界常见量化框架与工具
 - 2)Dipoorlet离线量化工具介绍
 - 3)Dipoorlet离线量化工具使用
 
- 五、离线量化工具整体设计结构
 - 1)回顾:如何生产一个硬件能跑的量化模型?
 - 2)Dipoorlet:支持多后端部署的离线量化框架
 - 3)Dipoorlet的代码架构和量化pipleline流程
 
- 六、离线量化工具代码解读
 - 1)自定义数据结构ONNXGraph(utils.py)
 - 2)可选参数(__main__.py)
 - 3)量化流程之加载模型
 - 4)量化流程之校准
 - 5)量化流程之权重微调(未完待续)
 - 6)权重流程之量化分析(profiling.py)
 - 7)导出量化部署配置
 
- 七、实践:Dipoorlet量化MobileNet
 - 1)具体演示一遍Dipoorlet实战流程
 
一、离线量化基础概念
1)离线量化定义

2)离线量化优缺点

3)如何生产一个硬件能跑的量化模型?

4)离线量化的类型
①对称量化:速度更快
 ②非对称量化:精度更好
 
5)如何计算scale,zero_point?
①权重weights是一个常量张量
 ②activation激活值的实际动态范围必须经过数据集采样获取,一般把这个过程称为数据校准calibration
 
6)离线量化概念

7)PTQ与QAT区别

8)离线量化流程

9)校准数据的选择

10)量化模式选择

11)校准方式的选择
- 不同的方式
①min_max:可能一些极端值会进来
②KL Divergence(TensorRT所使用的方法):
③Histogram(统计直方图):选定直方图的百分位点作为阶段之,根据百分比来调整截断值大小
④MSE:使用均方误差作为模型量化前后输出的损失的衡量指标。此方法较为耗时,但是效果常常优于其他方法 

 
 
12)量化算法的选择(展示离线量化的pipeline)

 ①经过预训练的模型经过CLE调整,使得模型更方便量化
 ②给模型建立更容易量化的节点,对称性权重和非对称性激活值
 ③用MSE做权重的range设置
 ④使用数据就用AdaRound的方法,不使用数据就用Bias Correction的方法
 ⑤真正数据对激活值的范围做校准
13)写入量化参数

二、离线量化难点
- 难点
①校准数据有限
②异常数据分布
③优化空间有限
④优化粒度选择

 
三、离线量化算法介绍

1)问题点
①问题点一:
 
 
②问题点二:
 
2)Weight equalization(WE):使每个channel分布更接近,从而更适用于per-tensor量化
特点:跨层动态范围均衡
 
3)Bias Correction(BC):从卷积或全连接层的bias剪掉权重的误差,准确率更接近per-channel量化
方法:用量化统计数据集前后变化的偏移
 
 
 
4)AdaRound
- 备注
在前面data-free-quantization中,对权重和bias只是采用比较简单的线性偏移;而AdaRound剔除的方法让weight做更灵活的变换




 
5)Brecq:解决AdaRound逐层重建忽略层间依赖关系的问题

 
 
 
6)QDrop:随机失活激活量化

 
 
7)离线量化算法–总结

- 硬件和推理库离线量化工具的能力

 
四、离线量化工具介绍
1)业界常见量化框架与工具

2)Dipoorlet离线量化工具介绍

 
3)Dipoorlet离线量化工具使用


 
 
 
 
五、离线量化工具整体设计结构
1)回顾:如何生产一个硬件能跑的量化模型?

2)Dipoorlet:支持多后端部署的离线量化框架
①部署支持能力
 ②精度提升能力
 ③框架代码结构

- 参数
 
1)-M :模型路径
2)-I:校准数据路径
3)-N:表示校准数据一共有多少个
4)-A:校准方式
 

3)Dipoorlet的代码架构和量化pipleline流程

- Dipoolet量化流程

 
六、离线量化工具代码解读
1)自定义数据结构ONNXGraph(utils.py)
- 代码功能

 
2)可选参数(main.py)
①指定模型路径,数据路径,输出路径,-N 校准数据数量
 
 ②指定权重调整算法
 
 ③激活校准算法和目标部署后端
 
④量化误差分析和opset版本
 
3)量化流程之加载模型
start = time.time()
if args.optim_transformer:model = onnx.load(args.optimzed_model_dir)
else:model = onnx.load(args.model)if model.opset_import[0].version < 13:model = onnx.version_converter.convert_version(model, 13)model, check = simplify(model)assert check, "Simplified ONNX model could not be validated"
onnx_graph = ONNXGraph(model, args.output_dir, args.deploy, args.model_type)
 
①加载onnx模型,并构建ONNXGragph
 ②转换opeset版本
 ③确保是否适用onnxsim简化图结构
 
④使用onnx.checker检查模型的合法性
4)量化流程之校准
# Assgin rank index to calibration GPU wise.
# Split the dataset averagly.
setattr(args, 'rank', dist.get_rank())
setattr(args, 'local_rank', dist.get_rank() % torch.cuda.device_count())
setattr(args, 'world_size', dist.get_world_size())
if dist.get_rank() == 0:logger.info("Do tensor calibration...")
act_clip_val, weight_clip_val = tensor_calibration(onnx_graph, args)
tensor_range = copy.deepcopy(act_clip_val)
save_clip_val(act_clip_val, weight_clip_val, args,act_fname='act_clip_val.json.rank{}'.format(args.rank),weight_fname='weight_clip_val.json.rank{}'.format(args.rank))
dist.barrier()
if dist.get_rank() == 0:reduce_clip_val(dist.get_world_size(), args)
dist.barrier()
act_clip_val, weight_clip_val = load_clip_val(args)
 
①调用tensor_calibration方法,产出激活和权重的量化参数,分别存于act_clip_val和weight_clip_val中
 ②激活校准的发给发根据前文讲述的-A参数
 
③权重校验的方法默认为minmax
- tensor_calibration方法实现

 
获得激活数据使用装饰器模式,会先执行注册的函数
 
 
 
- 总结
做完这些校准算法后,就得到这些层的minmax数据,就可以去做量化 
5)量化流程之权重微调(未完待续)
计算偏移值
 
6)权重流程之量化分析(profiling.py)
-  
功能
输出逐层量化误差以及激活/权重分布范围,看出问题的地方在哪里 -  
文件及函数接口

 
7)导出量化部署配置
- 具体文件及接口

根据不同的部署类型,用deploy_dispatcher去发布不同的事件,下面截图是发布了trt的事件

 
七、实践:Dipoorlet量化MobileNet
1)具体演示一遍Dipoorlet实战流程
- 流程解析
①安装Dipoorlet
②初始化数据和工作目录
③撰写命令生成量化 
①安装Dipoorlet
 
要注意onnxruntime和cuda版本要对的上,举例如下
 
 具体对应细节,去cuda官网看
 
 这里给出建议:
cuda:11.8
pytorch 2.0.0
 

 
尝试运行命令
python -m dipoorlet
 

②初始化数据和工作目录
 (1)创建临时目录dipoolet_work_dip_tmp
 (2)在该目录放onnx文件
 (3)创建input目录
 (4)在input目录生成随机数
 
③撰写命令生成量化数据(包含权重和激活信息)
python -m torch.distributed.launch  --use_env -m dipoorlet -M model.onnx -I ./ -A minmax -D trt -N 2 -O ./log_dir/
 

