模型量化-有校准数据训练后量化

    有校准数据训练后量化,使用少量校准数据计算量化因子,可以快速得到量化模型。使用该量化模型进行预测,可以减少计算量、降低计算内存、减小模型大小。

    有校准数据训练后量化中,有两种计算量化因子的方法,非饱和量化方法和饱和量化方法。非饱和量化方法计算整个Tensor的绝对值最大值,将其映射为127。饱和量化方法使用KL散度计算一个合适的阈值T (0<T<mab_max),将其映射为127。一般而言,待量化Op的权重采用非饱和量化方法,待量化Op的激活(输入和输出)采用饱和量化方法 。

    使用条件:

    • 有训练好的预测模型
    • 有少量校准数据,比如100~500张图片

    使用步骤:

    • 产出量化模型:使用PaddlePaddle或者PaddleSlim调用有校准数据训练后量化接口,产出量化模型
    • 量化模型预测:使用PaddleLite加载量化模型进行预测推理

    优点:

    • 减小计算量、降低计算内存、减小模型大小
    • 不需要大量训练数据
    • 快速产出量化模型,简单易用

    缺点:

    • 对少部分的模型,尤其是计算量小、精简的模型,量化后精度可能会受到影响

    大家可以使用PaddlePaddle或者PaddleSlim调用有校准数据训练后量化接口,得到量化模型。本文主要介绍使用PaddlePaddle产出量化模型,使用PaddleSlim可以参考文档

    参考PaddlePaddle,安装PaddlePaddle CPU/GPU 1.7版本。

    2.2 准备模型和校准数据

    有校准数据训练后量化内部使用异步数据读取的方式读取校准数据,大家只需要根据模型的输入,配置读取数据的sample_generator。sample_generator是Python生成器,必须每次返回单个样本数据,会用作DataLoader.set_sample_generator()的数据源。 建议参考和本文示例,学习如何配置校准数据生成器。

    2.4 调用有校准数据训练后量化

    对于调用有校准数据训练后量化,首先给出一个例子,让大家有个直观了解。

    对于调用有校准数据训练后量化,以下对接口进行详细介绍。

    1. class PostTrainingQuantization(
    2. scope=None,
    3. model_dir=None,
    4. model_filename=None,
    5. params_filename=None,
    6. sample_generator=None,
    7. batch_size=10,
    8. batch_nums=None,
    9. quantizable_op_type=["conv2d", "depthwise_conv2d", "mul"],
    10. is_full_quantize=False,
    11. weight_bits=8,
    12. activation_bits=8,
    13. is_use_cache_file=False,
    14. cache_dir="./temp_post_training"):

    调用上述api,传入必要的参数。参数说明如下:

    • executor(fluid.Executor):执行模型的executor,可以指定在cpu或者gpu上执行。
    • scope(fluid.Scope, optional):模型运行时使用的scope,默认为None,则会使用global_scope()。行首有optional,说明用户可以不设置该输入参数,直接使用默认值,下同。
    • model_dir(str):待量化模型的路径,其中保存模型文件和权重文件。
    • model_filename(str, optional):待量化模型的模型文件名,如果模型文件名不是__model__,则需要使用model_filename设置模型文件名。
    • params_filename(str, optional):待量化模型的权重文件名,如果所有权重保存成一个文件,则需要使用params_filename设置权重文件名。
    • sample_generator(Python Generator):配置的校准数据生成器。
    • batch_size(int, optional):一次读取校准数据的数量。
    • algo(str, optional):计算待量化激活Tensor的量化因子的方法。设置为KL,则使用饱和量化方法,设置为direct,则使用非饱和量化方法。默认为KL
    • quantizable_op_type(list[str], optional): 需要量化的op类型,默认是["conv2d", "depthwise_conv2d", "mul"],列表中的值可以是任意支持量化的op类型。
    • is_full_quantize(bool, optional):是否进行全量化。设置为True,则对模型中所有支持量化的op进行量化;设置为False,则只对quantizable_op_type 中op类型进行量化。目前支持的量化类型如下:’conv2d’, ‘depthwise_conv2d’, ‘mul’, “pool2d”, “elementwise_add”, “concat”, “softmax”, “argmax”, “transpose”, “equal”, “gather”, “greater_equal”, “greater_than”, “less_equal”, “less_than”, “mean”, “not_equal”, “reshape”, “reshape2”, “bilinear_interp”, “nearest_interp”, “trilinear_interp”, “slice”, “squeeze”, “elementwise_sub”。
    • weight_bits(int, optional):权重量化的比特数,可以设置为1~16。PaddleLite目前仅支持加载权重量化为8bit的量化模型。
    • activation_bits(int, optional): 激活量化的比特数,可以设置为1~16。PaddleLite目前仅支持加载激活量化为8bit的量化模型。
    • is_use_cache_file(bool, optional):是否使用缓存文件。如果设置为True,训练后量化过程中的采样数据会保存到磁盘文件中;如果设置为False,所有采样数据会保存到内存中。当待量化的模型很大或者校准数据数量很大,建议设置is_use_cache_file为True。默认为False。
    • cache_dir(str, optional):当is_use_cache_file等于True,会将采样数据保存到该文件中。量化完成后,该文件中的临时文件会自动删除。

    调用上述接口开始训练后量化。根据校准数据数量、模型的大小和量化op类型不同,训练后量化需要的时间也不一样。比如使用ImageNet2012数据集中100图片对MobileNetV1进行训练后量化,花费大概1分钟。

    调用上述接口保存训练后量化模型,其中save_model_path为保存的路径。

    训练后量化支持部分量化功能:

    • 方法1:设置quantizable_op_type,则只会对quantizable_op_type中的Op类型进行量化,模型中其他Op类型保持不量化。
    • 方法2:构建网络的时候,将不需要量化的特定Op定义在 skip_quant 的name_scope中,则可以跳过特定Op的量化,示例如下。
    1. with fluid.name_scope('skip_quant'):
    2. pool = fluid.layers.pool2d(input=hidden, pool_size=2, pool_type='avg', pool_stride=2)
    3. # 不对pool2d进行量化

    首先,使用PaddleLite提供的模型转换工具(model_optimize_tool)将量化模型转换成移动端预测的模型,然后加载转换后的模型进行预测部署。

    参考使用模型转换工具。注意opt命令的输入参数—prefer_int8_kernel必须设置为true,其他参数按照实际情况参考文档设置。比如在安卓手机ARM端进行预测,模型转换的命令为:

    1. ./opt --model_dir=./mobilenet_v1_quant \
    2. --optimize_out_type=naive_buffer \
    3. --optimize_out=mobilenet_v1_quant_opt \
    4. --valid_targets=arm \
    5. --prefer_int8_kernel=true

    3.2 量化模型预测

    和FP32模型一样,转换后的量化模型可以在Android/IOS APP中加载预测,建议参考、Java Demo、。

    参考本文 “2.1 安装PaddlePaddle” 安装PaddlePaddle。

    下载打包文件,解压到本地。

    执行下面的命令,自动下载预测模型(mobilenetv1_fp32_model)和校准数据集,然后调用有校准数据训练后方法产出量化模型。

    1. sh run_post_training_quanzation.sh

    量化模型保存在mobilenetv1_int8_model文件夹中。

    4.2 量化模型预测

    下载测试文件(benchmark_bin)或者参考编译测试文件。

    将mobilenetv1_fp32_model、mobilenetv1_int8_model和benchmark_bin文件都保存到手机上。

    1. adb push mobilenetv1_fp32_model /data/local/tmp
    2. adb push mobilenetv1_int8_model /data/local/tmp
    3. adb push benchmark_bin /data/local/tmp

    在res.txt文件中可以看到INT8量化模型和FP32原始模型的速度。 举例来说,在骁龙855手机、单线程的情况下测试mobilenetv1,INT8量化模型的计算时间是14.52ms,FP32原始模型的计算时间是31.7ms。