5.3. INT8 模型生成

​BM168X支持INT8量化模型的部署。在通用流程中,需要先借助于算能提供的量化工具对fp32模型进行量化。 ​TPU-NNTC工具链下的Qantization-Tools是算能科技自主开发的网络模型量化工具,它解析各种已训练好的32bit浮点网络模型,生成8bit的定点网络模型。该8bit定点网络模型,可用于算能科技SOPHON系列AI运算平台。在SOPHON运算平台上,网络各层输入、输出、系数都用8bit来表示,从而在保证网络精度的基础上,大幅减少功耗,内存,传输延迟,大幅提高运算速度。

Quantization-Tools由三部分组成:Parse-Tools、Calibration-Tools以及U-FrameWork,如下图所示:

../_images/Calibration-Tools.png
  • Parse-Tools:

    解析各深度学习框架下已训练好的网络模型,生成统一格式的网络模型文件—umodel, 支持的深度学习框架包括: Caffe、TensorFlow、MxNet、PyTorch、Darknet、ONNX以及PaddlePaddle。

  • Calibration-Tools:

    分析float32格式的umodel文件,默认基于熵损失最小算法(可选MAX等其他算法),将网络系数定点化成8bit,最后 将网络模型保存成int8格式的umodel文件。

  • U-FrameWork:

    自定义的深度学习推理框架,集合了各开源深度学习框架的运算功能,提供的功能包括:

    1. 作为基础运算平台,为定点化提供基础运算。

    2. 作为验证平台,可以验证fp32,int8格式的网络模型的精度。

    3. 作为接口,通过bmnetu,可以将int8umodel编译成能在SOPHON运算平台上运行的bmodel。

使用Quantization-Tools量化网络流程如下图:

../_images/quan_flow.png

生成int8量化模型,通常需要以下步骤:

  1. 准备lmdb数据集;

  2. 生成fp32 Umodel;

  3. 生成int8 Umodel;

  4. int8 Umodel精度测试(可选);

  5. 生成int8 Bmodel。

5.3.1. 准备lmdb数据集

我们需要将原始量化数据集转换成lmdb格式,供后续校准量化工具Quantization-tools 使用。

注解

Quantization-tools对数据格式的要求:

  • Quantization-tools 对输入数据的格式要求是 [N,C,H,W] :即先按照 W 存放数据,再按照 H 存放数据,依次类推

  • Quantization-tools 对输入数据的 C 维度的存放顺序与原始框架保持一致:例如 caffe 框架要求的 C 维度存放顺序是 BGR;tensorflow 要求的 C 维度存放顺序是 RGB

将数据转换成 lmdb 数据集有两种方法:

  1. 使用 auto_cali一键量化工具 工具,将图片目录转化为lmdb供分步量化使用;

  2. 运用U-FrameWork接口,在网络推理过程抓取网络推理输入或编写脚本存成lmdb,方法请参考 create_lmdb。与LMDB相关的功能已经独立成为ufwio包,该安装包不再依赖SophonSDK,可以在任何Python3.5及以上环境下运行。

在U-FrameWork中,网络的输入数据使用LMDB形式保存,以其作为data layer的数据来源。推荐在制作LMDB过程中即进行如减均值、除方差等前处理操作,lmdb中保存前处理后的数据。而对于前处理不能精确表达的复杂处理, 或者在级联网络中需要把中间结果作为下一级网络的输入进行训练的情况,用户可以自己开发预处理脚本,直接生成lmdb。

SophonSDK中提供了一套ufwio包,提供了一系列API帮助用户构建LMDB,该包已与SophonSDK解耦,可以在任何Pyhton3.5及以上环境中安装运行,具体请参考《 TPU-NNTC开发参考手册 》准备LMDB数据集。

TPU-NNTC开发参考手册 》中提供了创建lmdb的示例程序即 示例2:create_lmdb_demo,此示例程序可以直接作为工具使用,也可以在其基础上加入自定义的预处理。

5.3.2. 生成FP32 Umodel

为了将第三方框架训练后的网络模型量化,需要先将它们转化为量化平台私有格式fp32 Umodel。

注解

本阶段会生成一个*.fp32umodel文件以及一个*.prototxt文件。

prototxt文件的文件名一般是net_name_bmnetX_test_fp32.prototxt,其中X代表原始框架名的首字母,比如TensorFlow的网络转为Umodel后prototxt文件名会是net_name_bmnett_test_fp32.prototxt,PyTorch转换的网络会是net_name_bmnetp_test_fp32.prototxt等。

此阶段生成的 fp32umodel 文件是量化的输入,using-lmdb 中修改预处理就是针对此阶段生成的 prototxt 文件的修改。

注意

注意: 基于精度方面考虑输入Calibration-tools的fp32 umodel需要保持BatchNorm层以及Scale层独立。当您利用第三方工具对网络图做一些等价转换优化时,请确保BatchNorm以及Scale层不被提前融合到Convolution。

注意

此阶段的参数设置需要注意:

  • 如果指定了“-D (-dataset )”参数,那么需要保证“-D”参数下的路径正确,同时指定的数据集兼容该网络,否则会有运行错误。

  • 若指定了“-D”参数,则按照章节 using-lmdb 方法修改 prototxt。
    • 使用 data layer 作为输入

    • 正确设置数据预处理

    • 正确设置 lmdb 的路径

  • 在不能提供合法的数据源时,不应该使用“-D”参数(该参数是可选项,不指定会使用随机数据测试网络转化的正确性,可以在转化后的网络中再手动修改数据来源)

  • 转化模型的时候可以指定参数“–cmp”,使用该参数会比较模型转化的中间格式与原始框架下的模型计算结果是否一致,增加了模型转化的正确性验证。

此阶段生成fp32 umodel使用的工具为一系列名为ufw.tools.*_to_umodel的python脚本,存放于ufw包中,*号代表不同框架的缩写,可以通过以下命令查看使用帮助:

 1# Caffe模型转化fp32umodel工具
 2python3 -m ufw.tools.cf_to_umodel --help
 3# Darknet模型转化fp32umodel工具
 4python3 -m ufw.tools.dn_to_umodel --help
 5# MxNet模型转化fp32umodel工具
 6python3 -m ufw.tools.mx_to_umodel --help
 7# ONNX模型转化fp32umodel工具
 8python3 -m ufw.tools.on_to_umodel --help
 9# PyTorch模型转化fp32umodel工具
10python3 -m ufw.tools.pt_to_umodel --help
11# TensorFlow模型转化fp32umodel工具
12python3 -m ufw.tools.tf_to_umodel --help
13# PaddlePaddle模型转化fp32umdoel工具
14python3 -m ufw.tools.pp_to_umodel --help

详细参数说明针对不同框架稍有区别。用户可以参考《 TPU-NNTC开发参考手册 》提供的示例程序,在其基础上修改少量参数完成自己的模型转换。 更多详细内容,请参考《 TPU-NNTC开发参考手册 》。

5.3.3. 生成INT8 Umodel

此流程从fp32 Umodel转换为int8 Umodel,即为量化过程。 网络量化过程包含下面两个步骤:

  1. 优化网络:对输入浮点网络图进行优化

  2. 量化网络:对浮点网络进行量化得到 int8 网络图及系数文件

量化需要用到 3.3.1 准备lmdb数据集 中产生的 lmdb 数据集。由于正确使用数据集尤为重要,所以先说明如何使用数据集。

post-training 量化方法,旨通过将训练后的模型进行一定次数的推理,来统计每层的输入输出数据范围,从而确定量化参数。为了使统计尽可能准确, 推理时候必须保证输入的数据为实际训练/验证时候的有效数据,前处理也保证和训练时候的一致

Uframework 中提供了简单的前处理接口可以对生成的 lmdb 数据进行前处理以对齐训练过程中的预处理。具体来说,可通过修改生成 fp32 umodel 时候生成的 *_test_fp32.prototxt 文件来配置前处理算法,生成的lmdb数据在输入网络前会按照此处的配置进行计算后再进行真正的网络推理。完整的前处理可以视为制作lmdb时进行的前处理和prototxt中定义的前处理算法的组合。

5.3.3.1. 数据预处理

完整定义前处理一般需要做以下三方面的修改:

  • 使用Data layer 作为网络的输入

  • 使 Data layer 的参数 data_param 指向生成的 lmdb 数据集的位置

  • 修改 Data layer 的 transform_param 参数以对应网络对图片的预处理

data_layer的典型结构如下例所示:

 1layer {
 2name: "data"
 3type: "Data"
 4top: "data"
 5top: "label"
 6include {
 7    phase: TEST
 8}
 9transform_param {
10    transform_op {
11        op: RESIZE
12        resize_h: 331
13        resize_w: 331
14    }
15    transform_op {
16        op: STAND
17        mean_value: 128
18        mean_value: 128
19        mean_value: 128
20        scale: 0.0078125
21    }
22}
23data_param {
24    source: "/my_lmdb"
25    batch_size: 0
26    backend: LMDB
27}
28}

例如:

../_images/fp32umodel_to_int8umodel.png

在量化网络前,需要修改网络的 *_test_fp32.prototxt 文件,在 datalayer(或者 AnnotatedData layer)添加其数据预处理的参数,以保证送给网络的数据与网络在原始框架中训练时的预处理一致。

Calibration-tools 量化工具支持两种数据预处理表示方式:

../_images/image.png
  1. Caffe自带的TransformationParameter 参数表示方法: Caffe自带的表示方法各个参数的执行顺序相对固定(如上图右半部所示),但很难完善表达Tensorflow、Pytorch 等基于Python的框架里面灵活多变的预处理方式,仅适用于 Caffe 模型的默认数据预处理方式。使用此方式,前处理操作和参数直接以 transform_param 的参数的形式定义。

  2. 算能科技自定义的TransformOp 数组表示方法: 我们定义了transform_op结构,将需要进行的预处理分解为不同的 transform_op,按照顺序列在transform_param中,程序会按照顺序分别执行各项计算。

注意

  • 在修改 prototxt 文件添加数据预处理时,使用transform_param和transform_op定义预处理只能二选一,请优先使用transform_op。

  • 关于transform_param和transform_op的更详细内容请查看《 TPU-NNTC开发参考手册 》中的 TransformOp定义

  • 当前版本开始对lmdb有升级,制作lmdb只有python形式的接口提供,示例程序create_lmdb提供了例程可在其基础上修改。推荐在python代码中将预处理一并包含,生成已经预处理过的数据供量化使用,这样就不必在prototxt中定义前处理。 制作lmdb时候需要生成与网络输入shape一致的数据,当此lmdb用作转换fp32umodel命令的-D参数的输入时,上述prototxt的data layer的batch_size参数会自动设置为0,如果转换fp32umodel过程中没有指定-D参数,则手工修改prototxt指定数据源时需要注意将batch_size设置为0。 以前版本二进制convert_imageset工具生成的lmdb配合以前的prototxt是兼容的。

5.3.3.2. 量化网络

使用 calibration_use_pb 可以完成网络的量化,具体请参考《 TPU-NNTC开发参考手册 》量化网络。

5.3.3.3. 优化网络

使用 calibration_use_pb 可以完成网络的优化,默认配置下对输入浮点网络进行优化,包括:batchnorm 与 scale 合并,前处理融合到网络,删除推理过程中不必要的算子等功能。具体请参考《 TPU-NNTC开发参考手册》优化网络。

5.3.3.4. 级联网络量化

提示

级联网络量化 级联网络的量化需要对每个网络分别进行量化,对每个网络分别准备 LMDB 和量化调优。

5.3.4. 精度测试

精度测试是一个可选的操作步骤,用以验证经过 int8 量化后,网络的精度情况。

该步骤可以安排在部署描述的网络部署之前,并配合量化网络反复进行,以达到预期的精度。

根据不同的网络类型,精度测试可能是不同的,精度测试常常意味着要进行完整的前处理和后处理以及精度计算程序开发。

Calibration-tools 对外提供了UFramework 的应用接口,可以对 umodel 进行 float32 或者 int8 推理,从而计算网络推理精度。

注解

在生成新的int8 bmodel后,网络可能需要验证精度损失,SDK提供不同类型网络的精度比对方式。

  1. 分类网络,通过修改网络输出层添加top-k:参考《 TPU-NNTC开发参考手册 》分类网络的精度测试。

  2. 检测网络,通过ufw测试特定图片,与fp32网络比对:参考《 TPU-NNTC开发参考手册 》检测网络的精度测试。

  3. 通过图形界面检查精度差异:参考《 TPU-NNTC开发参考手册 》量化误差定性分析。

更多关于精度测试以及量化误差分析、量化技巧的内容请参考《 TPU-NNTC开发参考手册

5.3.5. 生成INT8 Bmodel

int8umodel是一个临时存在的中间形式,需要进一步转换为可以在算能AI平台上执行的int8 bmodel,本节可以看作是 int8 umodel 的部署操作或者 int8 bmodel 的生成操作。

通过使用SDK提供的BMNETU工具,可以将 3.3.3 生成INT8 Umodel 的输出 int8 umodel(如下)作为输入,方便快捷地转换为 int8 bmodel。

1**.int8umodel,
2**_deploy_int8_unique_top.prototxt

BMNETU是针对BM1684的UFW(Unified Framework)模型编译器,可将某网络的umodel(Unified Model)和 prototxt编译成BMRuntime所需要的文件。而且在编译的同时,支持每一层的NPU模型计算结果和CPU的计算结果进行对比,保证正确性,具体参考:《 TPU-NNTC开发参考手册 》BMNETU使用。

5.3.6. auto_cali一键量化工具

对于常见以图片作为输入的CV类推理网络,推荐使用 auto_cali 一键量化工具。这个工具是分步量化的整合,操作更加简单,支持使用 LMDB 数据集或者原始图片完成量化,可以减少分步量化过程中手工输入引起的错误等,其功能如下:

  • 一键完成从原始框架 (TensorFlow/PyTorch/Caffe/Darknet/MxNet/PaddlePaddle/ONNX) 到 BM1684/BM1684X 芯片bmodel的转换

  • 可根据预设的优化参数组合根据int8模型精度结果自动进行量化策略搜索,找到满足精度要求的最佳量化策略

具体请参考:《 TPU-NNTC开发参考手册 》中的 auto_cali