文章目录

一、离线量化基础概念

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)普通onnx模型来演示一遍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/

在这里插入图片描述

2)实战案例:MobileNet实战案例

(1)流程介绍

①下载微调的数据集tiny-imagenet-200做预训练(这里200指的是类,单个类50张图片)
②微调模型(train_torch.py)生成mobilev2_model.pth
③读取模型,测试fp32的精度(test_torch.py),并转成onnx模型
在这里插入图片描述
④用build_trt.py量化模型,生成engine(需要提供模型onnx和校准数据)
⑤预先准备校准数据(dataset.py),这个文件写了一些imagenet预处理的过程
⑥test_trt.py测试tensorRT量化后,模型推理的精度
在这里插入图片描述

⑦用dipoorlet处理准备校准数据(创个文件夹intput.1,文件格式都是bin格式)
函数在calibrator.py

在这里插入图片描述
⑧开始用dipoorlet量化,生成每个层的dynamic range,也就是trt_clip_val.json文件
–nproc_per_node 8:表示用8卡去训练
在这里插入图片描述
⑨调用build_trt_dipoorlet.py代码,把dynamic range传给network,然后序列化成引擎
在这里插入图片描述

⑩用test_trt.py测试dipoorlet量化后的engine精度
在这里插入图片描述

3)任务说明:MobileNet V2量化推理

4)mobilev2_model

5)作业及思路

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐