From 493779a9598b06a29a9de7aa9f5d2471f75d30b2 Mon Sep 17 00:00:00 2001 From: Liufang Sang Date: Tue, 25 Feb 2020 22:16:21 -0600 Subject: [PATCH] cherry-pick fix quantization api and tutorial doc (#158) --- .../en/quick_start/quant_aware_tutorial_en.md | 6 +- docs/en/quick_start/quant_post_tutorial_en.md | 2 +- docs/zh_cn/api_cn/quantization_api.rst | 62 ++++++++++--------- .../zh_cn/quick_start/quant_aware_tutorial.md | 8 +-- docs/zh_cn/quick_start/quant_post_tutorial.md | 6 +- 5 files changed, 43 insertions(+), 41 deletions(-) diff --git a/docs/en/quick_start/quant_aware_tutorial_en.md b/docs/en/quick_start/quant_aware_tutorial_en.md index bd20f2c6..938e85f5 100644 --- a/docs/en/quick_start/quant_aware_tutorial_en.md +++ b/docs/en/quick_start/quant_aware_tutorial_en.md @@ -1,6 +1,6 @@ # Training-aware Quantization of image classification model - quick start -This tutorial shows how to do training-aware quantization using [API](https://github.com/PaddlePaddle/PaddleSlim/blob/develop/docs/docs/api/quantization_api.md) in PaddleSlim. We use MobileNetV1 to train image classification model as example. The tutorial contains follow sections: +This tutorial shows how to do training-aware quantization using [API](https://paddlepaddle.github.io/PaddleSlim/api_en/paddleslim.quant.html#paddleslim.quant.quanter.quant_aware) in PaddleSlim. We use MobileNetV1 to train image classification model as example. The tutorial contains follow sections: 1. Necessary imports 2. Model architecture @@ -89,7 +89,7 @@ test(val_program) ## 4. Quantization -We call ``quant_aware`` API to add quantization and dequantization operators in ``train_program`` and ``val_program`` according to [default configuration](https://paddlepaddle.github.io/PaddleSlim/api/quantization_api/#_1). +We call ``quant_aware`` API to add quantization and dequantization operators in ``train_program`` and ``val_program`` according to [default configuration](https://paddlepaddle.github.io/PaddleSlim/api_cn/quantization_api.html#id2). ```python quant_program = slim.quant.quant_aware(train_program, exe.place, for_test=False) @@ -114,7 +114,7 @@ test(val_quant_program) ## 6. Save model after quantization -The model in ``4. Quantization`` after calling ``slim.quant.quant_aware`` API is only suitable to train. To get the inference model, we should use [slim.quant.convert](https://paddlepaddle.github.io/PaddleSlim/api/quantization_api/#convert) API to change model architecture and use [fluid.io.save_inference_model](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/io_cn/save_inference_model_cn.html#save-inference-model) to save model. ``float_prog``'s parameters are float32 dtype but in int8's range which can be used in ``fluid`` or ``paddle-lite``. ``paddle-lite`` will change the parameters' dtype from float32 to int8 first when loading the inference model. ``int8_prog``'s parameters are int8 dtype and we can get model size after quantization by saving it. ``int8_prog`` cannot be used in ``fluid`` or ``paddle-lite``. +The model in ``4. Quantization`` after calling ``slim.quant.quant_aware`` API is only suitable to train. To get the inference model, we should use [slim.quant.convert](https://paddlepaddle.github.io/PaddleSlim/api_en/paddleslim.quant.html#paddleslim.quant.quanter.convert) API to change model architecture and use [fluid.io.save_inference_model](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/io_cn/save_inference_model_cn.html#save-inference-model) to save model. ``float_prog``'s parameters are float32 dtype but in int8's range which can be used in ``fluid`` or ``paddle-lite``. ``paddle-lite`` will change the parameters' dtype from float32 to int8 first when loading the inference model. ``int8_prog``'s parameters are int8 dtype and we can get model size after quantization by saving it. ``int8_prog`` cannot be used in ``fluid`` or ``paddle-lite``. ```python diff --git a/docs/en/quick_start/quant_post_tutorial_en.md b/docs/en/quick_start/quant_post_tutorial_en.md index aa599e61..a46329f3 100644 --- a/docs/en/quick_start/quant_post_tutorial_en.md +++ b/docs/en/quick_start/quant_post_tutorial_en.md @@ -1,6 +1,6 @@ # Post-training Quantization of image classification model - quick start -This tutorial shows how to do post training quantization using [API](https://github.com/PaddlePaddle/PaddleSlim/blob/develop/docs/docs/api/quantization_api.md) in PaddleSlim. We use MobileNetV1 to train image classification model as example. The tutorial contains follow sections: +This tutorial shows how to do post training quantization using [API](https://paddlepaddle.github.io/PaddleSlim/api_en/paddleslim.quant.html#paddleslim.quant.quanter.quant_post) in PaddleSlim. We use MobileNetV1 to train image classification model as example. The tutorial contains follow sections: 1. Necessary imports 2. Model architecture diff --git a/docs/zh_cn/api_cn/quantization_api.rst b/docs/zh_cn/api_cn/quantization_api.rst index faa37918..dc332a5c 100644 --- a/docs/zh_cn/api_cn/quantization_api.rst +++ b/docs/zh_cn/api_cn/quantization_api.rst @@ -53,8 +53,8 @@ - **activation_quantize_type(str)** - 激活量化方式,可选 ``'abs_max'`` , ``'range_abs_max'`` , ``'moving_average_abs_max'`` 。如果使用 ``TensorRT`` 加载量化后的模型来预测,请使用 ``'range_abs_max', 'moving_average_abs_max'`` 。,默认 ``'moving_average_abs_max'`` 。 - **weight_bits(int)** - 参数量化bit数,默认8, 推荐设为8。 - **activation_bits(int)** - 激活量化bit数,默认8, 推荐设为8。 -- **not_quant_pattern(str | list[str])** - 所有 ``name_scope`` 包含 ``'not_quant_pattern'`` 字符串的 ``op`` ,都不量化, 设置方式请参考 `fluid.name_scope `_ 。 -- **quantize_op_types(list[str])** - 需要进行量化的 ``op`` 类型,目前支持 ``'conv2d', 'depthwise_conv2d', 'mul'`` 。 +- **not_quant_pattern(str | list[str])** - 所有 ``name_scope`` 包含 ``'not_quant_pattern'`` 字符串的 op ,都不量化, 设置方式请参考 `fluid.name_scope `_ 。 +- **quantize_op_types(list[str])** - 需要进行量化的 op 类型,目前支持 ``'conv2d', 'depthwise_conv2d', 'mul'`` 。 - **dtype(int8)** - 量化后的参数类型,默认 ``int8`` , 目前仅支持 ``int8`` 。 - **window_size(int)** - ``'range_abs_max'`` 量化方式的 ``window size`` ,默认10000。 - **moving_rate(int)** - ``'moving_average_abs_max'`` 量化方式的衰减系数,默认 0.9。 @@ -69,22 +69,24 @@ quant_aware ------------ -.. py:function:: paddleslim.quant.quant_aware(program, place, config, scope=None, for_test=False)[[源代码]](https://github.com/PaddlePaddle/PaddleSlim/blob/develop/paddleslim/quant/quanter.py) +.. py:function:: paddleslim.quant.quant_aware(program, place, config, scope=None, for_test=False) -在 ``program`` 中加入量化和反量化 ``op``, 用于量化训练。 +`源代码 `_ + +在 program 中加入量化和反量化op, 用于量化训练。 **参数:** -- **program (fluid.Program)** - 传入训练或测试 ``program`` 。 +- **program (fluid.Program)** - 传入训练或测试program 。 - **place(fluid.CPUPlace | fluid.CUDAPlace)** - 该参数表示 ``Executor`` 执行所在的设备。 - **config(dict)** - 量化配置表。 - **scope(fluid.Scope, optional)** - 传入用于存储 ``Variable`` 的 ``scope`` ,需要传入 ``program`` 所使用的 ``scope`` ,一般情况下,是 `fluid.global_scope() `_ 。设置为 ``None`` 时将使用 `fluid.global_scope() `_ ,默认值为 ``None`` 。 -- **for_test(bool)** - 如果 ``program`` 参数是一个测试 ``program`` , ``for_test`` 应设为 ``True`` ,否则设为 ``False`` 。 +- **for_test(bool)** - 如果 ``program`` 参数是一个测试 ``program`` , ``for_test`` 应设为True,否则设为False 。 **返回** -含有量化和反量化 ``operator`` 的 ``program`` 。 +含有量化和反量化 operator 的 program 。 **返回类型** @@ -93,10 +95,10 @@ quant_aware .. note:: - - 此接口会改变 ``program`` 结构,并且可能增加一些``persistable``的变量,所以加载模型参数时请注意和相应的``program``对应。 - - 此接口底层经历了``fluid.Program``-> ``fluid.framework.IrGraph``->``fluid.Program``的转变,在``fluid.framework.IrGraph``中没有``Parameter``的概念,``Variable``只有``persistable``和``not persistable``的区别,所以在保存和加载参数时,请使用``fluid.io.save_persistables``和``fluid.io.load_persistables``接口。 - - 由于此接口会根据``program``的结构和量化配置来对``program``添加op,所以``Paddle``中一些通过``fuse op``来加速训练的策略不能使用。已知以下策略在使用量化时必须设为``False``: ``fuse_all_reduce_ops, sync_batch_norm``。 - - 如果传入的 ``program`` 中存在和任何op都没有连接的 ``Variable`` ,则会在量化的过程中被优化掉。 + - 此接口会改变program 结构,并且可能增加一些persistable的变量,所以加载模型参数时请注意和相应的 program 对应。 + - 此接口底层经历了 fluid.Program -> fluid.framework.IrGraph -> fluid.Program 的转变,在 ``fluid.framework.IrGraph`` 中没有 ``Parameter`` 的概念,``Variable`` 只有 persistable 和not persistable的区别,所以在保存和加载参数时,请使用 ``fluid.io.save_persistables`` 和 ``fluid.io.load_persistables`` 接口。 + - 由于此接口会根据 program 的结构和量化配置来对program 添加op,所以 ``Paddle`` 中一些通过 ``fuse op`` 来加速训练的策略不能使用。已知以下策略在使用量化时必须设为False : ``fuse_all_reduce_ops, sync_batch_norm`` 。 + - 如果传入的 program 中存在和任何op都没有连接的 ``Variable`` ,则会在量化的过程中被优化掉。 @@ -108,24 +110,24 @@ convert `源代码 `_ -把训练好的量化 ``program`` ,转换为可用于保存 ``inference model`` 的 ``program`` 。 +把训练好的量化 program ,转换为可用于保存 ``inference model`` 的 program 。 **参数:** -- **program (fluid.Program)** - 传入测试``program``。 -- **place(fluid.CPUPlace | fluid.CUDAPlace)** - 该参数表示``Executor``执行所在的设备。 +- **program (fluid.Program)** - 传入测试 program 。 +- **place(fluid.CPUPlace | fluid.CUDAPlace)** - 该参数表示 ``Executor`` 执行所在的设备。 - **config(dict)** - 量化配置表。 -- **scope(fluid.Scope)** - 传入用于存储``Variable``的``scope``,需要传入``program``所使用的``scope``,一般情况下,是 `fluid.global_scope() `_ 。设置为 ``None`` 时将使用 `fluid.global_scope() `_ ,默认值为 ``None`` 。 -- **save_int8(bool)** - 是否需要返回参数为 ``int8`` 的 ``program`` 。该功能目前只能用于确认模型大小。默认值为 ``False`` 。 +- **scope(fluid.Scope)** - 传入用于存储 ``Variable`` 的 ``scope`` ,需要传入 ``program`` 所使用的 ``scope`` ,一般情况下,是 `fluid.global_scope() `_ 。设置为 ``None`` 时将使用 `fluid.global_scope() `_ ,默认值为 ``None`` 。 +- **save_int8(bool)** - 是否需要返回参数为 ``int8`` 的 program 。该功能目前只能用于确认模型大小。默认值为 ``False`` 。 **返回** -- **program (fluid.Program)** - freezed program,可用于保存inference model,参数为``float32``类型,但其数值范围可用int8表示。 -- **int8_program (fluid.Program)** - freezed program,可用于保存inference model,参数为``int8``类型。当``save_int8``为``False``时,不返回该值。 +- **program (fluid.Program)** - freezed program,可用于保存inference model,参数为 ``float32`` 类型,但其数值范围可用int8表示。 +- **int8_program (fluid.Program)** - freezed program,可用于保存inference model,参数为 ``int8`` 类型。当 ``save_int8`` 为False 时,不返回该值。 .. note:: - 因为该接口会对``op``和``Variable``做相应的删除和修改,所以此接口只能在训练完成之后调用。如果想转化训练的中间模型,可加载相应的参数之后再使用此接口。 + 因为该接口会对 op 和 Variable 做相应的删除和修改,所以此接口只能在训练完成之后调用。如果想转化训练的中间模型,可加载相应的参数之后再使用此接口。 **代码示例** @@ -186,13 +188,13 @@ quant_post - **model_dir(str)** - 需要量化的模型所在的文件夹。 - **quantize_model_path(str)** - 保存量化后的模型的路径 - **sample_generator(python generator)** - 读取数据样本,每次返回一个样本。 -- **model_filename(str, optional)** - 模型文件名,如果需要量化的模型的参数存在一个文件中,则需要设置``model_filename``为模型文件的名称,否则设置为``None``即可。默认值是``None``。 -- **params_filename(str)** - 参数文件名,如果需要量化的模型的参数存在一个文件中,则需要设置``params_filename``为参数文件的名称,否则设置为``None``即可。默认值是``None``。 +- **model_filename(str, optional)** - 模型文件名,如果需要量化的模型的参数存在一个文件中,则需要设置 ``model_filename`` 为模型文件的名称,否则设置为 ``None`` 即可。默认值是 ``None`` 。 +- **params_filename(str)** - 参数文件名,如果需要量化的模型的参数存在一个文件中,则需要设置 ``params_filename`` 为参数文件的名称,否则设置为 ``None`` 即可。默认值是 ``None`` 。 - **batch_size(int)** - 每个batch的图片数量。默认值为16 。 -- **batch_nums(int, optional)** - 迭代次数。如果设置为``None``,则会一直运行到``sample_generator`` 迭代结束, 否则,迭代次数为``batch_nums``, 也就是说参与对 ``Scale`` 进行校正的样本个数为 ``'batch_nums' * 'batch_size'`` . -- **scope(fluid.Scope, optional)** - 用来获取和写入 ``Variable`` , 如果设置为 ``None`` ,则使用 `fluid.global_scope() `_ . 默认值是``None``. +- **batch_nums(int, optional)** - 迭代次数。如果设置为 ``None`` ,则会一直运行到 ``sample_generator`` 迭代结束, 否则,迭代次数为 ``batch_nums``, 也就是说参与对 ``Scale`` 进行校正的样本个数为 ``'batch_nums' * 'batch_size'`` . +- **scope(fluid.Scope, optional)** - 用来获取和写入 ``Variable`` , 如果设置为 ``None`` ,则使用 `fluid.global_scope() `_ . 默认值是 ``None`` . - **algo(str)** - 量化时使用的算法名称,可为 ``'KL'`` 或者 ``'direct'`` 。该参数仅针对激活值的量化,因为参数值的量化使用的方式为 ``'channel_wise_abs_max'`` . 当 ``algo`` 设置为 ``'direct'`` 时,使用校正数据的激活值的绝对值的最大值当作 ``Scale`` 值,当设置为 ``'KL'`` 时,则使用KL散度的方法来计算 ``Scale`` 值。默认值为 ``'KL'`` 。 -- **quantizable_op_type(list[str])** - 需要量化的 ``op`` 类型列表。默认值为 ``["conv2d", "depthwise_conv2d", "mul"]`` 。 +- **quantizable_op_type(list[str])** - 需要量化的 op 类型列表。默认值为 ``["conv2d", "depthwise_conv2d", "mul"]`` 。 - **is_full_quantize(bool)** - 是否量化所有可支持的op类型。如果设置为False, 则按照 ``'quantizable_op_type'`` 的设置进行量化。 - **weight_bits(int)** - weight的量化比特位数。 - **activation_bits(int)** - 激活值的量化比特位数。 @@ -205,14 +207,14 @@ quant_post .. note:: - - 因为该接口会收集校正数据的所有的激活值,当校正图片比较多时,请设置``'is_use_cache_file'``为True, 将中间结果存储在硬盘中。另外,``'KL'``散度的计算比较耗时。 - - 目前``Paddle-Lite``有int8 kernel来加速的op只有 ``['conv2d', 'depthwise_conv2d', 'mul']``, 其他op的int8 kernel将陆续支持。 + - 因为该接口会收集校正数据的所有的激活值,当校正图片比较多时,请设置 ``'is_use_cache_file'`` 为True, 将中间结果存储在硬盘中。另外,``'KL'`` 散度的计算比较耗时。 + - 目前 ``Paddle-Lite`` 有int8 kernel来加速的op只有 ``['conv2d', 'depthwise_conv2d', 'mul']`` , 其他op的int8 kernel将陆续支持。 **代码示例** .. warning:: - 此示例不能直接运行,因为需要加载``${model_dir}``下的模型,所以不能直接运行。 + 此示例不能直接运行,因为需要加载 ``${model_dir}`` 下的模型,所以不能直接运行。 .. code-block:: python @@ -249,12 +251,12 @@ quant_embedding **参数:** - **program(fluid.Program)** - 需要量化的program -- **scope(fluid.Scope, optional)** - 用来获取和写入``Variable``, 如果设置为``None``,则使用 `fluid.global_scope() `_ . +- **scope(fluid.Scope, optional)** - 用来获取和写入 ``Variable``, 如果设置为 ``None``,则使用 `fluid.global_scope() `_ . - **place(fluid.CPUPlace | fluid.CUDAPlace)** - 运行program的设备 - **config(dict)** - 定义量化的配置。可以配置的参数有: - ``'params_name'`` (str, required): 需要进行量化的参数名称,此参数必须设置。 - - ``'quantize_type'`` (str, optional): 量化的类型,目前支持的类型是 ``'abs_max'``, 待支持的类型有 ``'log', 'product_quantization'`` 。 默认值是``'abs_max'`` . - - ``'quantize_bits'`` (int, optional): 量化的 ``bit`` 数,目前支持的 ``bit`` 数为8。默认值是8. + - ``'quantize_type'`` (str, optional): 量化的类型,目前支持的类型是 ``'abs_max'``, 待支持的类型有 ``'log', 'product_quantization'`` 。 默认值是 ``'abs_max'`` . + - ``'quantize_bits'`` (int, optional): 量化的bit数,目前支持的bit数为8。默认值是8. - ``'dtype'`` (str, optional): 量化之后的数据类型, 目前支持的是 ``'int8'``. 默认值是 ``int8`` 。 - ``'threshold'`` (float, optional): 量化之前将根据此阈值对需要量化的参数值进行 ``clip``. 如果不设置,则跳过 ``clip`` 过程直接量化。 diff --git a/docs/zh_cn/quick_start/quant_aware_tutorial.md b/docs/zh_cn/quick_start/quant_aware_tutorial.md index 802f0b73..5dfc3837 100644 --- a/docs/zh_cn/quick_start/quant_aware_tutorial.md +++ b/docs/zh_cn/quick_start/quant_aware_tutorial.md @@ -1,6 +1,6 @@ # 图像分类模型量化训练-快速开始 -该教程以图像分类模型MobileNetV1为例,说明如何快速使用PaddleSlim的[量化训练接口](https://github.com/PaddlePaddle/PaddleSlim/blob/develop/docs/docs/api/quantization_api.md)。 该示例包含以下步骤: +该教程以图像分类模型MobileNetV1为例,说明如何快速使用PaddleSlim的[量化训练接口](https://paddlepaddle.github.io/PaddleSlim/api_cn/quantization_api.html)。 该示例包含以下步骤: 1. 导入依赖 2. 构建模型 @@ -61,7 +61,7 @@ def train(prog): if iter % 100 == 0: print('train iter={}, top1={}, top5={}, loss={}'.format(iter, acc1.mean(), acc5.mean(), loss.mean())) iter += 1 - + def test(prog): iter = 0 res = [[], []] @@ -93,7 +93,7 @@ test(val_program) ## 4. 量化 -按照[默认配置](https://paddlepaddle.github.io/PaddleSlim/api/quantization_api/#_1)在``train_program``和``val_program``中加入量化和反量化op. +按照[默认配置](https://paddlepaddle.github.io/PaddleSlim/api_cn/quantization_api.html#id2)在``train_program``和``val_program``中加入量化和反量化op. ```python @@ -121,7 +121,7 @@ test(val_quant_program) ## 6. 保存量化后的模型 -在``4. 量化``中使用接口``slim.quant.quant_aware``接口得到的模型只适合训练时使用,为了得到最终使用时的模型,需要使用[slim.quant.convert](https://paddlepaddle.github.io/PaddleSlim/api/quantization_api/#convert)接口,然后使用[fluid.io.save_inference_model](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/io_cn/save_inference_model_cn.html#save-inference-model)保存模型。``float_prog``的参数数据类型是float32,但是数据范围是int8, 保存之后可使用fluid或者paddle-lite加载使用,paddle-lite在使用时,会先将类型转换为int8。``int8_prog``的参数数据类型是int8, 保存后可看到量化后模型大小,不可加载使用。 +在``4. 量化``中使用接口``slim.quant.quant_aware``接口得到的模型只适合训练时使用,为了得到最终使用时的模型,需要使用[slim.quant.convert](https://paddlepaddle.github.io/PaddleSlim/api_cn/quantization_api.html#convert)接口,然后使用[fluid.io.save_inference_model](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/io_cn/save_inference_model_cn.html#save-inference-model)保存模型。``float_prog``的参数数据类型是float32,但是数据范围是int8, 保存之后可使用fluid或者paddle-lite加载使用,paddle-lite在使用时,会先将类型转换为int8。``int8_prog``的参数数据类型是int8, 保存后可看到量化后模型大小,不可加载使用。 ```python diff --git a/docs/zh_cn/quick_start/quant_post_tutorial.md b/docs/zh_cn/quick_start/quant_post_tutorial.md index 84ec2cc0..5904b872 100755 --- a/docs/zh_cn/quick_start/quant_post_tutorial.md +++ b/docs/zh_cn/quick_start/quant_post_tutorial.md @@ -1,6 +1,6 @@ # 图像分类模型离线量化-快速开始 -该教程以图像分类模型MobileNetV1为例,说明如何快速使用PaddleSlim的[离线量化接口](https://github.com/PaddlePaddle/PaddleSlim/blob/develop/docs/docs/api/quantization_api.md)。 该示例包含以下步骤: +该教程以图像分类模型MobileNetV1为例,说明如何快速使用PaddleSlim的[离线量化接口](https://paddlepaddle.github.io/PaddleSlim/api_cn/quantization_api.html#quant-post)。 该示例包含以下步骤: 1. 导入依赖 2. 构建模型 @@ -19,7 +19,7 @@ import numpy as np ``` ## 2. 构建网络 -该章节构造一个用于对MNIST数据进行分类的分类模型,选用`MobileNetV1`,并将输入大小设置为`[1, 28, 28]`,输出类别数为10。 为了方便展示示例,我们在`paddleslim.models`下预定义了用于构建分类模型的方法,执行以下代码构建分类模型: +该章节构造一个用于对MNIST数据进行分类的分类模型,选用`MobileNetV1`,并将输入大小设置为`[1, 28, 28]`,输出类别数为10。为了方便展示示例,我们在`paddleslim.models`下预定义了用于构建分类模型的方法,执行以下代码构建分类模型: >注意:paddleslim.models下的API并非PaddleSlim常规API,是为了简化示例而封装预定义的一系列方法,比如:模型结构的定义、Program的构建等。 @@ -60,7 +60,7 @@ def train(prog): if iter % 100 == 0: print('train', acc1.mean(), acc5.mean(), loss.mean()) iter += 1 - + def test(prog, outputs=outputs): iter = 0 res = [[], []] -- GitLab