未验证 提交 39700126 编写于 作者: C cc 提交者: GitHub

Rename quant api, update quant doc, test=develop, test=document (#338)

上级 2ff43527
...@@ -110,7 +110,7 @@ PaddleSlim会从底层能力、技术咨询合作和业务场景等角度支持 ...@@ -110,7 +110,7 @@ PaddleSlim会从底层能力、技术咨询合作和业务场景等角度支持
<a href="https://github.com/PaddlePaddle/PaddleSlim/blob/develop/docs/zh_cn/quick_start/quant_aware_tutorial.md" target="_blank">量化训练快速开始示例</a> <a href="https://github.com/PaddlePaddle/PaddleSlim/blob/develop/docs/zh_cn/quick_start/quant_aware_tutorial.md" target="_blank">量化训练快速开始示例</a>
</li> </li>
<li> <li>
<a href="https://github.com/PaddlePaddle/PaddleSlim/blob/develop/docs/zh_cn/quick_start/quant_post_tutorial.md" target="_blank">离线量化快速开始示例</a> <a href="https://github.com/PaddlePaddle/PaddleSlim/blob/develop/docs/zh_cn/quick_start/quant_post_static_tutorial.md" target="_blank">静态离线量化快速开始示例</a>
</li> </li>
<li> <li>
<a href="https://github.com/PaddlePaddle/PaddleSlim/blob/develop/docs/zh_cn/tutorials/paddledetection_slim_quantization_tutorial.md" target="_blank">检测模型量化教程</a> <a href="https://github.com/PaddlePaddle/PaddleSlim/blob/develop/docs/zh_cn/tutorials/paddledetection_slim_quantization_tutorial.md" target="_blank">检测模型量化教程</a>
......
...@@ -40,9 +40,9 @@ import numpy as np ...@@ -40,9 +40,9 @@ import numpy as np
- **quantize_op_types:** 目前CPU上支持量化 `depthwise_conv2d`, `mul`, `conv2d`, `matmul`, `transpose2`, `reshape2`, `pool2d`, `scale`。但是训练阶段插入fake quantize/dequantize op时,只需在前四种op前后插入fake quantize/dequantize ops,因为后面四种op `matmul`, `transpose2`, `reshape2`, `pool2d`的输入输出scale不变,将从前后方op的输入输出scales获得scales,所以`quantize_op_types` 参数只需要 `depthwise_conv2d`, `mul`, `conv2d`, `matmul` 即可。 - **quantize_op_types:** 目前CPU上支持量化 `depthwise_conv2d`, `mul`, `conv2d`, `matmul`, `transpose2`, `reshape2`, `pool2d`, `scale`。但是训练阶段插入fake quantize/dequantize op时,只需在前四种op前后插入fake quantize/dequantize ops,因为后面四种op `matmul`, `transpose2`, `reshape2`, `pool2d`的输入输出scale不变,将从前后方op的输入输出scales获得scales,所以`quantize_op_types` 参数只需要 `depthwise_conv2d`, `mul`, `conv2d`, `matmul` 即可。
- **其他参数:** 请参考 [PaddleSlim quant_aware API](https://paddlepaddle.github.io/PaddleSlim/api/quantization_api/#quant_aware) - **其他参数:** 请参考 [PaddleSlim quant_aware API](https://paddlepaddle.github.io/PaddleSlim/api/quantization_api/#quant_aware)
#### 2.2 离线量化 #### 2.2 静态离线量化
离线量化模型产出可以参考[分类模型的离线量化流程](https://paddlepaddle.github.io/PaddleSlim/tutorials/quant_post_demo/#_1) 静态离线量化模型产出可以参考[分类模型的静态离线量化流程](https://paddlepaddle.github.io/PaddleSlim/tutorials/quant_post_demo/#_1)
## 3. 转化产出的量化模型为DNNL优化后的INT8模型 ## 3. 转化产出的量化模型为DNNL优化后的INT8模型
为了部署在CPU上,我们将保存的quant模型,通过一个转化脚本,移除fake quantize/dequantize op,fuse一些op,并且完全转化成 INT8 模型。需要使用Paddle所在目录运行下面的脚本,脚本在官网的位置为[save_qat_model.py](https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/fluid/contrib/slim/tests/save_qat_model.py)。复制脚本到demo所在目录下(`/PATH_TO_PaddleSlim/demo/mkldnn_quant/quant_aware/`)并执行如下命令: 为了部署在CPU上,我们将保存的quant模型,通过一个转化脚本,移除fake quantize/dequantize op,fuse一些op,并且完全转化成 INT8 模型。需要使用Paddle所在目录运行下面的脚本,脚本在官网的位置为[save_qat_model.py](https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/fluid/contrib/slim/tests/save_qat_model.py)。复制脚本到demo所在目录下(`/PATH_TO_PaddleSlim/demo/mkldnn_quant/quant_aware/`)并执行如下命令:
......
...@@ -12,7 +12,7 @@ sys.path[0] = os.path.join( ...@@ -12,7 +12,7 @@ sys.path[0] = os.path.join(
os.path.dirname("__file__"), os.path.pardir, os.path.pardir) os.path.dirname("__file__"), os.path.pardir, os.path.pardir)
from paddleslim.common import get_logger from paddleslim.common import get_logger
from paddleslim.analysis import flops from paddleslim.analysis import flops
from paddleslim.quant import quant_aware, quant_post, convert from paddleslim.quant import quant_aware, convert
import models import models
from utility import add_arguments, print_arguments from utility import add_arguments, print_arguments
......
# 离线量化示例 # 静态离线量化示例
本示例介绍如何使用离线量化接口``paddleslim.quant.quant_post``来对训练好的分类模型进行离线量化, 该接口无需对模型进行训练就可得到量化模型,减少模型的存储空间和显存占用。 本示例介绍如何使用离线量化接口``paddleslim.quant.quant_post_static``来对训练好的分类模型进行离线量化, 该接口无需对模型进行训练就可得到量化模型,减少模型的存储空间和显存占用。
## 接口介绍 ## 接口介绍
请参考 <a href='https://paddlepaddle.github.io/PaddleSlim/api_cn/quantization_api.html#quant-post'>量化API文档</a> 请参考 <a href='https://paddlepaddle.github.io/PaddleSlim/api_cn/quantization_api.html#quant-post-static'>量化API文档</a>
## 分类模型的离线量化流程 ## 分类模型的离线量化流程
...@@ -30,10 +30,10 @@ python export_model.py --model "MobileNet" --pretrained_model ./pretrain/MobileN ...@@ -30,10 +30,10 @@ python export_model.py --model "MobileNet" --pretrained_model ./pretrain/MobileN
``` ```
转化之后的模型存储在``inference_model/MobileNet/``文件夹下,可看到该文件夹下有``'model'``, ``'weights'``两个文件。 转化之后的模型存储在``inference_model/MobileNet/``文件夹下,可看到该文件夹下有``'model'``, ``'weights'``两个文件。
### 离线量化 ### 静态离线量化
接下来对导出的模型文件进行离线量化,离线量化的脚本为[quant_post.py](./quant_post.py),脚本中使用接口``paddleslim.quant.quant_post``对模型进行离线量化。运行命令为: 接下来对导出的模型文件进行静态离线量化,静态离线量化的脚本为[quant_post.py](./quant_post.py),脚本中使用接口``paddleslim.quant.quant_post_static``对模型进行离线量化。运行命令为:
``` ```
python quant_post.py --model_path ./inference_model/MobileNet --save_path ./quant_model_train/MobileNet --model_filename model --params_filename weights python quant_post_static.py --model_path ./inference_model/MobileNet --save_path ./quant_model_train/MobileNet --model_filename model --params_filename weights
``` ```
- ``model_path``: 需要量化的模型坐在的文件夹 - ``model_path``: 需要量化的模型坐在的文件夹
......
...@@ -27,7 +27,7 @@ from dataloader.casia import CASIA_Face ...@@ -27,7 +27,7 @@ from dataloader.casia import CASIA_Face
from dataloader.lfw import LFW from dataloader.lfw import LFW
from lfw_eval import parse_filelist, evaluation_10_fold from lfw_eval import parse_filelist, evaluation_10_fold
from paddleslim import models from paddleslim import models
from paddleslim.quant import quant_post from paddleslim.quant import quant_post_static
def now(): def now():
...@@ -331,7 +331,7 @@ def main(): ...@@ -331,7 +331,7 @@ def main():
if args.action == 'train': if args.action == 'train':
train(exe, train_program, train_out, test_program, test_out, args) train(exe, train_program, train_out, test_program, test_out, args)
elif args.action == 'quant': elif args.action == 'quant':
quant_post( quant_post_static(
executor=exe, executor=exe,
model_dir='./out_inference/', model_dir='./out_inference/',
quantize_model_path='./quant_model/', quantize_model_path='./quant_model/',
......
...@@ -8,5 +8,5 @@ Quick Start ...@@ -8,5 +8,5 @@ Quick Start
pruning_tutorial_en.md pruning_tutorial_en.md
nas_tutorial_en.md nas_tutorial_en.md
quant_aware_tutorial_en.md quant_aware_tutorial_en.md
quant_post_tutorial_en.md quant_post_static_tutorial_en.md
量化 量化
==== ====
量化配置 模型量化包含三种量化方法,分别是动态离线量化方法、静态离线量化方法和量化训练方法。
---------------
通过字典配置量化参数 下图展示了如何选择模型量化方法。
.. image:: https://user-images.githubusercontent.com/52520497/83991261-cbe55800-a97e-11ea-880c-d83fb7924454.png
:scale: 80 %
:alt: 图1:选择模型量化方法
:align: center
下图综合对比了模型量化方法的使用条件、易用性、精度损失和预期收益。
.. image:: https://user-images.githubusercontent.com/52520497/83991268-cee04880-a97e-11ea-9ecd-2d0f04a15205.png
:scale: 80 %
:alt: 图2:综合对比模型量化方法
:align: center
quant_post_dynamic
-------------------
.. py:function:: paddleslim.quant.quant_post_dynamic(model_dir, save_model_dir, model_filename=None, params_filename=None, save_model_filename=None, save_params_filename=None, quantizable_op_type=["conv2d", "mul"], weight_bits=8, generate_test_model=False)
`源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/release/1.1.0/paddleslim/quant/quanter.py>`_
动态离线量化,将模型中特定OP的权重从FP32类型量化成INT8/16类型。
该量化模型有两种预测方式:第一种是反量化预测方式,即是首先将INT8/16类型的权重反量化成FP32类型,然后再使用FP32浮运算运算进行预测;第二种量化预测方式,即是预测中动态计算量化OP输入的量化信息,基于量化的输入和权重进行INT8整形运算。
注意,目前只有PaddleLite仅仅支持第一种反量化预测方式,server端预测(PaddleInference)不支持加载该量化模型。
**使用条件:**
* 有训练好的预测模型
**使用步骤:**
* 产出量化模型:使用PaddlePaddle调用动态离线量化离线量化接口,产出量化模型
* 量化模型预测:使用PaddleLite加载量化模型进行预测推理
**优点:**
* 权重量化成INT16类型,模型精度不受影响,模型大小为原始的1/2
* 权重量化成INT8类型,模型精度会受到影响,模型大小为原始的1/4
**缺点:**
* 目前PaddleLite只支持反量化预测方式,主要可以减小模型大小,对特定加载权重费时的模型可以起到一定加速效果
**参数:**
- **model_dir(str)** - 需要量化的模型的存储路径。
- **save_model_dir(str)** - 量化后的模型的存储路径。
- **model_filename(str, optional)** - 模型文件名,如果需要量化的模型的参数存在一个文件中,则需要设置 ``model_filename`` 为模型文件的名称,否则设置为 ``None`` 即可。默认值是 ``None`` 。
- **params_filename(str, optional)** - 参数文件名,如果需要量化的模型的参数存在一个文件中,则需要设置 ``params_filename`` 为参数文件的名称,否则设置为 ``None`` 即可。默认值是 ``None`` 。
- **save_model_filename(str, optional)** - 用于保存量化模型的模型文件名,如果想让参数存在一个文件中,则需要设置 ``save_model_filename`` 为模型文件的名称,否则设置为 ``None`` 即可。默认值是 None 。
- **save_params_filename(str, optional)** - 用于保存模型的参数文件名,如果想让参数存在一个文件中,则需要设置 ``save_params_filename`` 为参数文件的名称,否则设置为 ``None`` 即可。默认值是 None 。
- **quantizable_op_type(list[str])** - 需要量化的 op 类型列表。可选范围为 ``["conv2d", "depthwise_conv2d", "mul"]`` 。 默认值是 ``["conv2d", "mul"]`` 。
- **weight_bits(int)** - weight的量化比特位数, 可选8或者16。 默认值为8。
- **generate_test_model(bool)** - 如果为True, 则会保存一个fake quantized模型,这个模型可用PaddlePaddle加载测试精度。默认为False.
**返回**
**返回类型**
**代码示例**
.. warning::
此示例不能直接运行,因为需要加载 ``${model_dir}`` 下的模型,所以不能直接运行。
.. code-block:: python .. code-block:: python
import paddle.fluid as fluid
import paddle.dataset.mnist as reader
from paddleslim.quant import quant_post_dynamic
TENSORRT_OP_TYPES = [ quant_post_dynamic(
'mul', 'conv2d', 'pool2d', 'depthwise_conv2d', 'elementwise_add', model_dir='./model_path',
'leaky_relu' save_model_dir='./save_path',
] model_filename='__model__',
TRANSFORM_PASS_OP_TYPES = ['conv2d', 'depthwise_conv2d', 'mul'] params_filename='__params__',
save_model_filename='__model__',
save_params_filename='__params__')
QUANT_DEQUANT_PASS_OP_TYPES = [
"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", "relu", "relu6", "leaky_relu", "tanh", "swish"
]
_quant_config_default = {
# weight quantize type, default is 'channel_wise_abs_max'
'weight_quantize_type': 'channel_wise_abs_max',
# activation quantize type, default is 'moving_average_abs_max'
'activation_quantize_type': 'moving_average_abs_max',
# weight quantize bit num, default is 8
'weight_bits': 8,
# activation quantize bit num, default is 8
'activation_bits': 8,
# ops of name_scope in not_quant_pattern list, will not be quantized
'not_quant_pattern': ['skip_quant'],
# ops of type in quantize_op_types, will be quantized
'quantize_op_types': ['conv2d', 'depthwise_conv2d', 'mul'],
# data type after quantization, such as 'uint8', 'int8', etc. default is 'int8'
'dtype': 'int8',
# window size for 'range_abs_max' quantization. defaulf is 10000
'window_size': 10000,
# The decay coefficient of moving average, default is 0.9
'moving_rate': 0.9,
# if True, 'quantize_op_types' will be TENSORRT_OP_TYPES
'for_tensorrt': False,
# if True, 'quantoze_op_types' will be TRANSFORM_PASS_OP_TYPES + QUANT_DEQUANT_PASS_OP_TYPES
'is_full_quantize': False
}
**参数:**
- **weight_quantize_type(str)** - 参数量化方式。可选 ``'abs_max'`` , ``'channel_wise_abs_max'`` , ``'range_abs_max'`` , ``'moving_average_abs_max'`` 。如果使用 ``TensorRT`` 加载量化后的模型来预测,请使用 ``'channel_wise_abs_max'`` 。 默认 ``'channel_wise_abs_max'`` 。
- **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, 可选1-8,推荐设为8,因为量化后的数据类型是 ``int8`` 。
- **activation_bits(int)** - 激活量化bit数,默认8,可选1-8,推荐设为8,因为量化后的数据类型是 ``int8`` 。
- **not_quant_pattern(str | list[str])** - 所有 ``name_scope`` 包含 ``'not_quant_pattern'`` 字符串的 op ,都不量化, 设置方式请参考 `fluid.name_scope <https://www.paddlepaddle.org.cn/documentation/docs/zh/api_cn/fluid_cn/name_scope_cn.html#name-scope>`_ 。
- **quantize_op_types(list[str])** - 需要进行量化的 op 类型,可选的op类型为 ``TRANSFORM_PASS_OP_TYPES + QUANT_DEQUANT_PASS_OP_TYPES`` 。
- **dtype(int8)** - 量化后的参数类型,默认 ``int8`` , 目前仅支持 ``int8`` 。
- **window_size(int)** - ``'range_abs_max'`` 量化方式的 ``window size`` ,默认10000。
- **moving_rate(int)** - ``'moving_average_abs_max'`` 量化方式的衰减系数,默认 0.9。
- **for_tensorrt(bool)** - 量化后的模型是否使用 ``TensorRT`` 进行预测。如果是的话,量化op类型为: ``TENSORRT_OP_TYPES`` 。默认值为False.
- **is_full_quantize(bool)** - 是否量化所有可支持op类型。可量化op为 ``TRANSFORM_PASS_OP_TYPES + QUANT_DEQUANT_PASS_OP_TYPES`` 。 默认值为False.
.. :note:: quant_post_static
---------------
.. py:function:: paddleslim.quant.quant_post_static(executor,model_dir, quantize_model_path, batch_generator=None, sample_generator=None, model_filename=None, params_filename=None, save_model_filename='__model__', save_params_filename='__params__', batch_size=16, batch_nums=None, scope=None, algo='KL', quantizable_op_type=["conv2d","depthwise_conv2d","mul"], is_full_quantize=False, weight_bits=8, activation_bits=8, activation_quantize_type='range_abs_max', weight_quantize_type='channel_wise_abs_max', is_use_cache_file=False, cache_dir="./temp_post_training")
`源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/release/1.1.0/paddleslim/quant/quanter.py>`_
静态离线量化,使用少量校准数据计算量化因子,可以快速得到量化模型。使用该量化模型进行预测,可以减少计算量、降低计算内存、减小模型大小。
注意:在PaddleSlim 1.1.0版本,我们将 `quant_post` 改名为 `quant_post_static`。前者就还可以使用,但是即将被废弃,请使用 `quant_post_static`。
**使用条件:**
* 有训练好的预测模型
* 有少量校准数据,比如100~500张图片
**使用步骤:**
* 产出量化模型:使用PaddleSlim调用静态离线量化接口,产出量化模型
* 量化模型预测:使用PaddleLite或者PaddleInference加载量化模型进行预测推理
**优点:**
* 减小计算量、降低计算内存、减小模型大小
* 不需要大量训练数据
* 快速产出量化模型,简单易用
**缺点:**
* 对少部分的模型,尤其是计算量小、精简的模型,量化后精度可能会受到影响
**参数:**
- **executor (fluid.Executor)** - 执行模型的executor,可以在cpu或者gpu上执行。
- **model_dir(str)** - 需要量化的模型所在的文件夹。
- **quantize_model_path(str)** - 保存量化后的模型的路径
- **batch_generator(python generator)** - 读取数据样本,每次返回一个batch的数据。和 `sample_generator` 只能设置一个。
- **sample_generator(python generator)** - 读取数据样本,每次返回一个样本。
- **model_filename(str, optional)** - 模型文件名,如果需要量化的模型的参数存在一个文件中,则需要设置 ``model_filename`` 为模型文件的名称,否则设置为 ``None`` 即可。默认值是 ``None`` 。
- **params_filename(str, optional)** - 参数文件名,如果需要量化的模型的参数存在一个文件中,则需要设置 ``params_filename`` 为参数文件的名称,否则设置为 ``None`` 即可。默认值是 ``None`` 。
- **save_model_filename(str)** - 用于保存量化模型的模型文件名,如果想让参数存在一个文件中,则需要设置 ``save_model_filename`` 为模型文件的名称,否则设置为 ``None`` 即可。默认值是 ``__model__`` 。
- **save_params_filename(str)** - 用于保存模型的参数文件名,如果想让参数存在一个文件中,则需要设置 ``save_params_filename`` 为参数文件的名称,否则设置为 ``None`` 即可。默认值是 ``__params__`` 。
- **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() <https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/executor_cn/global_scope_cn.html>`_ . 默认值是 ``None`` .
- **algo(str)** - 量化时使用的算法名称,可为 ``'KL'`` 或者 ``'abs_max'`` 。该参数仅针对激活值的量化,因为参数值的量化使用的方式为 ``'channel_wise_abs_max'`` . 当 ``algo`` 设置为 ``'abs_max'`` 时,使用校正数据的激活值的绝对值的最大值当作 ``Scale`` 值,当设置为 ``'KL'`` 时,则使用KL散度的方法来计算 ``Scale`` 值。默认值为 ``'KL'`` 。
- **quantizable_op_type(list[str])** - 需要量化的 op 类型列表。默认值为 ``["conv2d", "depthwise_conv2d", "mul"]`` 。
- **is_full_quantize(bool)** - 是否量化所有可支持的op类型。如果设置为False, 则按照 ``'quantizable_op_type'`` 的设置进行量化。如果设置为True, 则按照 `量化配置 <#id2>`_ 中 ``QUANT_DEQUANT_PASS_OP_TYPES + QUANT_DEQUANT_PASS_OP_TYPES`` 定义的op进行量化。
- **weight_bits(int)** - weight的量化比特位数, 默认值为8。
- **activation_bits(int)** - 激活值的量化比特位数, 默认值为8。
- **weight_quantize_type(str)** - weight的量化方式,可选 `abs_max` 或者 `channel_wise_abs_max` ,通常情况下选 `channel_wise_abs_max` 模型量化精度更高。
- **activation_quantize_type(str)** - 激活值的量化方式, 可选 `range_abs_max` 和 `moving_average_abs_max` 。设置激活量化方式不会影响计算scale的算法,只是影响在保存模型时使用哪种operator。
- **is_use_cache_file(bool)** - 是否使用硬盘对中间结果进行存储。如果为False, 则将中间结果存储在内存中。默认值为False。
- **cache_dir(str)** - 如果 ``'is_use_cache_file'`` 为True, 则将中间结果存储在此参数设置的路径下。默认值为 ``./temp_post_training`` 。
**返回**
无。
.. note::
- 因为该接口会收集校正数据的所有的激活值,当校正图片比较多时,请设置 ``'is_use_cache_file'`` 为True, 将中间结果存储在硬盘中。另外,``'KL'`` 散度的计算比较耗时。
- 目前 ``Paddle-Lite`` 有int8 kernel来加速的op只有 ``['conv2d', 'depthwise_conv2d', 'mul']`` , 其他op的int8 kernel将陆续支持。
**代码示例**
.. warning::
此示例不能直接运行,因为需要加载 ``${model_dir}`` 下的模型,所以不能直接运行。
.. code-block:: python
import paddle.fluid as fluid
import paddle.dataset.mnist as reader
from paddleslim.quant import quant_post_static
val_reader = reader.train()
use_gpu = True
place = fluid.CUDAPlace(0) if use_gpu else fluid.CPUPlace()
exe = fluid.Executor(place)
quant_post_static(
executor=exe,
model_dir='./model_path',
quantize_model_path='./save_path',
sample_generator=val_reader,
model_filename='__model__',
params_filename='__params__',
batch_size=16,
batch_nums=10)
更详细的用法请参考 `离线量化demo <https://github.com/PaddlePaddle/PaddleSlim/tree/release/1.1.0/demo/quant/quant_post>`_ 。
目前 ``Paddle-Lite`` 有int8 kernel来加速的op只有 ``['conv2d', 'depthwise_conv2d', 'mul']``, 其他op的int8 kernel将陆续支持。
quant_aware quant_aware
...@@ -173,76 +296,71 @@ convert ...@@ -173,76 +296,71 @@ convert
更详细的用法请参考 `量化训练demo <https://github.com/PaddlePaddle/PaddleSlim/tree/release/1.1.0/demo/quant/quant_aware>`_ 。 更详细的用法请参考 `量化训练demo <https://github.com/PaddlePaddle/PaddleSlim/tree/release/1.1.0/demo/quant/quant_aware>`_ 。
quant_post
---------------
.. py:function:: paddleslim.quant.quant_post(executor, model_dir, quantize_model_path, batch_generator=None, sample_generator=None, model_filename=None, params_filename=None, save_model_filename='__model__', save_params_filename='__params__', batch_size=16, batch_nums=None, scope=None, algo='KL', quantizable_op_type=["conv2d","depthwise_conv2d","mul"], is_full_quantize=False, weight_bits=8, activation_bits=8, activation_quantize_type='range_abs_max', weight_quantize_type='channel_wise_abs_max', is_use_cache_file=False, cache_dir="./temp_post_training")
`源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/release/1.1.0/paddleslim/quant/quanter.py>`_
对保存在 ``${model_dir}`` 下的模型进行量化,使用 ``sample_generator`` 或者 ``batch_generator`` 的数据进行参数校正。
**参数:**
- **executor (fluid.Executor)** - 执行模型的executor,可以在cpu或者gpu上执行。 量化训练方法的参数配置
- **model_dir(str)** - 需要量化的模型所在的文件夹。 ---------------
- **quantize_model_path(str)** - 保存量化后的模型的路径 通过字典配置量化参数
- **batch_generator(python generator)** - 读取数据样本,每次返回一个batch的数据。和 `sample_generator` 只能设置一个。
- **sample_generator(python generator)** - 读取数据样本,每次返回一个样本。
- **model_filename(str, optional)** - 模型文件名,如果需要量化的模型的参数存在一个文件中,则需要设置 ``model_filename`` 为模型文件的名称,否则设置为 ``None`` 即可。默认值是 ``None`` 。
- **params_filename(str, optional)** - 参数文件名,如果需要量化的模型的参数存在一个文件中,则需要设置 ``params_filename`` 为参数文件的名称,否则设置为 ``None`` 即可。默认值是 ``None`` 。
- **save_model_filename(str)** - 用于保存量化模型的模型文件名,如果想让参数存在一个文件中,则需要设置 ``save_model_filename`` 为模型文件的名称,否则设置为 ``None`` 即可。默认值是 ``__model__`` 。
- **save_params_filename(str)** - 用于保存模型的参数文件名,如果想让参数存在一个文件中,则需要设置 ``save_params_filename`` 为参数文件的名称,否则设置为 ``None`` 即可。默认值是 ``__params__`` 。
- **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() <https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/executor_cn/global_scope_cn.html>`_ . 默认值是 ``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"]`` 。
- **is_full_quantize(bool)** - 是否量化所有可支持的op类型。如果设置为False, 则按照 ``'quantizable_op_type'`` 的设置进行量化。如果设置为True, 则按照 `量化配置 <#id2>`_ 中 ``QUANT_DEQUANT_PASS_OP_TYPES + QUANT_DEQUANT_PASS_OP_TYPES`` 定义的op进行量化。
- **weight_bits(int)** - weight的量化比特位数, 默认值为8。
- **activation_bits(int)** - 激活值的量化比特位数, 默认值为8。
- **weight_quantize_type(str)** - weight的量化方式,可选 `abs_max` 或者 `channel_wise_abs_max` ,通常情况下选 `channel_wise_abs_max` 模型量化精度更高。
- **activation_quantize_type(str)** - 激活值的量化方式, 可选 `range_abs_max` 和 `moving_average_abs_max` 。设置激活量化方式不会影响计算scale的算法,只是影响在保存模型时使用哪种operator。
- **is_use_cache_file(bool)** - 是否使用硬盘对中间结果进行存储。如果为False, 则将中间结果存储在内存中。默认值为False。
- **cache_dir(str)** - 如果 ``'is_use_cache_file'`` 为True, 则将中间结果存储在此参数设置的路径下。默认值为 ``./temp_post_training`` 。
**返回**
无。
.. note:: .. code-block:: python
- 因为该接口会收集校正数据的所有的激活值,当校正图片比较多时,请设置 ``'is_use_cache_file'`` 为True, 将中间结果存储在硬盘中。另外,``'KL'`` 散度的计算比较耗时。
- 目前 ``Paddle-Lite`` 有int8 kernel来加速的op只有 ``['conv2d', 'depthwise_conv2d', 'mul']`` , 其他op的int8 kernel将陆续支持。
**代码示例** TENSORRT_OP_TYPES = [
'mul', 'conv2d', 'pool2d', 'depthwise_conv2d', 'elementwise_add',
'leaky_relu'
]
TRANSFORM_PASS_OP_TYPES = ['conv2d', 'depthwise_conv2d', 'mul']
.. warning:: QUANT_DEQUANT_PASS_OP_TYPES = [
"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", "relu", "relu6", "leaky_relu", "tanh", "swish"
]
此示例不能直接运行,因为需要加载 ``${model_dir}`` 下的模型,所以不能直接运行。 _quant_config_default = {
# weight quantize type, default is 'channel_wise_abs_max'
'weight_quantize_type': 'channel_wise_abs_max',
# activation quantize type, default is 'moving_average_abs_max'
'activation_quantize_type': 'moving_average_abs_max',
# weight quantize bit num, default is 8
'weight_bits': 8,
# activation quantize bit num, default is 8
'activation_bits': 8,
# ops of name_scope in not_quant_pattern list, will not be quantized
'not_quant_pattern': ['skip_quant'],
# ops of type in quantize_op_types, will be quantized
'quantize_op_types': ['conv2d', 'depthwise_conv2d', 'mul'],
# data type after quantization, such as 'uint8', 'int8', etc. default is 'int8'
'dtype': 'int8',
# window size for 'range_abs_max' quantization. defaulf is 10000
'window_size': 10000,
# The decay coefficient of moving average, default is 0.9
'moving_rate': 0.9,
# if True, 'quantize_op_types' will be TENSORRT_OP_TYPES
'for_tensorrt': False,
# if True, 'quantoze_op_types' will be TRANSFORM_PASS_OP_TYPES + QUANT_DEQUANT_PASS_OP_TYPES
'is_full_quantize': False
}
.. code-block:: python **参数:**
import paddle.fluid as fluid - **weight_quantize_type(str)** - 参数量化方式。可选 ``'abs_max'`` , ``'channel_wise_abs_max'`` , ``'range_abs_max'`` , ``'moving_average_abs_max'`` 。如果使用 ``TensorRT`` 加载量化后的模型来预测,请使用 ``'channel_wise_abs_max'`` 。 默认 ``'channel_wise_abs_max'`` 。
import paddle.dataset.mnist as reader - **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'`` 。
from paddleslim.quant import quant_post - **weight_bits(int)** - 参数量化bit数,默认8, 可选1-8,推荐设为8,因为量化后的数据类型是 ``int8`` 。
val_reader = reader.train() - **activation_bits(int)** - 激活量化bit数,默认8,可选1-8,推荐设为8,因为量化后的数据类型是 ``int8`` 。
use_gpu = True - **not_quant_pattern(str | list[str])** - 所有 ``name_scope`` 包含 ``'not_quant_pattern'`` 字符串的 op ,都不量化, 设置方式请参考 `fluid.name_scope <https://www.paddlepaddle.org.cn/documentation/docs/zh/api_cn/fluid_cn/name_scope_cn.html#name-scope>`_ 。
place = fluid.CUDAPlace(0) if use_gpu else fluid.CPUPlace() - **quantize_op_types(list[str])** - 需要进行量化的 op 类型,可选的op类型为 ``TRANSFORM_PASS_OP_TYPES + QUANT_DEQUANT_PASS_OP_TYPES`` 。
- **dtype(int8)** - 量化后的参数类型,默认 ``int8`` , 目前仅支持 ``int8`` 。
- **window_size(int)** - ``'range_abs_max'`` 量化方式的 ``window size`` ,默认10000。
- **moving_rate(int)** - ``'moving_average_abs_max'`` 量化方式的衰减系数,默认 0.9。
- **for_tensorrt(bool)** - 量化后的模型是否使用 ``TensorRT`` 进行预测。如果是的话,量化op类型为: ``TENSORRT_OP_TYPES`` 。默认值为False.
- **is_full_quantize(bool)** - 是否量化所有可支持op类型。可量化op为 ``TRANSFORM_PASS_OP_TYPES + QUANT_DEQUANT_PASS_OP_TYPES`` 。 默认值为False.
exe = fluid.Executor(place) .. :note::
quant_post(
executor=exe,
model_dir='./model_path',
quantize_model_path='./save_path',
sample_generator=val_reader,
model_filename='__model__',
params_filename='__params__',
batch_size=16,
batch_nums=10)
目前 ``Paddle-Lite`` 有int8 kernel来加速的op只有 ``['conv2d', 'depthwise_conv2d', 'mul']``, 其他op的int8 kernel将陆续支持。
更详细的用法请参考 `离线量化demo <https://github.com/PaddlePaddle/PaddleSlim/tree/release/1.1.0/demo/quant/quant_post>`_ 。
quant_embedding quant_embedding
------------------- -------------------
...@@ -303,52 +421,3 @@ fluid.Program ...@@ -303,52 +421,3 @@ fluid.Program
更详细的用法请参考 `Embedding量化demo <https://github.com/PaddlePaddle/PaddleSlim/tree/release/1.1.0/demo/quant/quant_embedding>`_ 更详细的用法请参考 `Embedding量化demo <https://github.com/PaddlePaddle/PaddleSlim/tree/release/1.1.0/demo/quant/quant_embedding>`_
quant_post_only_weight
-------------------
.. py:function:: paddleslim.quant.quant_post_only_weight(model_dir, save_model_dir, model_filename=None, params_filename=None, save_model_filename=None, save_params_filename=None, quantizable_op_type=["conv2d", "mul"], weight_bits=8, generate_test_model=False)
`源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/release/1.1.0/paddleslim/quant/quanter.py>`_
离线量化方法,只量化weight, 不需要输入数据。
**参数:**
- **model_dir(str)** - 需要量化的模型的存储路径。
- **save_model_dir(str)** - 量化后的模型的存储路径。
- **model_filename(str, optional)** - 模型文件名,如果需要量化的模型的参数存在一个文件中,则需要设置 ``model_filename`` 为模型文件的名称,否则设置为 ``None`` 即可。默认值是 ``None`` 。
- **params_filename(str, optional)** - 参数文件名,如果需要量化的模型的参数存在一个文件中,则需要设置 ``params_filename`` 为参数文件的名称,否则设置为 ``None`` 即可。默认值是 ``None`` 。
- **save_model_filename(str, optional)** - 用于保存量化模型的模型文件名,如果想让参数存在一个文件中,则需要设置 ``save_model_filename`` 为模型文件的名称,否则设置为 ``None`` 即可。默认值是 None 。
- **save_params_filename(str, optional)** - 用于保存模型的参数文件名,如果想让参数存在一个文件中,则需要设置 ``save_params_filename`` 为参数文件的名称,否则设置为 ``None`` 即可。默认值是 None 。
- **quantizable_op_type(list[str])** - 需要量化的 op 类型列表。可选范围为 ``["conv2d", "depthwise_conv2d", "mul"]`` 。 默认值是 ``["conv2d", "mul"]`` 。
- **weight_bits(int)** - weight的量化比特位数, 可选8或者16。 默认值为8。
- **generate_test_model(bool)** - 如果为True, 则会保存一个fake quantized模型,这个模型可用PaddlePaddle加载测试精度。默认为False.
**返回**
**返回类型**
**代码示例**
.. warning::
此示例不能直接运行,因为需要加载 ``${model_dir}`` 下的模型,所以不能直接运行。
.. code-block:: python
import paddle.fluid as fluid
import paddle.dataset.mnist as reader
from paddleslim.quant import quant_post_only_weight
quant_post_only_weight(
model_dir='./model_path',
save_model_dir='./save_path',
model_filename='__model__',
params_filename='__params__',
save_model_filename='__model__',
save_params_filename='__params__')
...@@ -19,7 +19,8 @@ PaddleSlim会从底层能力、技术咨询合作和业务场景等角度支持 ...@@ -19,7 +19,8 @@ PaddleSlim会从底层能力、技术咨询合作和业务场景等角度支持
- 定点量化 - 定点量化
- 在线量化训练(training aware) - 在线量化训练(training aware)
- 离线量化(post training) - 静态离线量化(static post training)
- 动态离线量化(dynamic post training)
- 知识蒸馏 - 知识蒸馏
- 支持单进程知识蒸馏 - 支持单进程知识蒸馏
......
...@@ -8,6 +8,6 @@ ...@@ -8,6 +8,6 @@
pruning_tutorial.md pruning_tutorial.md
distillation_tutorial.md distillation_tutorial.md
quant_aware_tutorial.md quant_aware_tutorial.md
quant_post_tutorial.md quant_post_static_tutorial.md
nas_tutorial.md nas_tutorial.md
# 图像分类模型量化训练-快速开始 # 图像分类模型量化训练-快速开始
该教程以图像分类模型MobileNetV1为例,说明如何快速使用PaddleSlim的[量化训练接口](https://paddlepaddle.github.io/PaddleSlim/api_cn/quantization_api.html)。 该示例包含以下步骤: 该教程以图像分类模型MobileNetV1为例,说明如何快速使用PaddleSlim的[量化训练接口](../api_cn/quantization_api.html)。 该示例包含以下步骤:
1. 导入依赖 1. 导入依赖
2. 构建模型 2. 构建模型
......
# 图像分类模型离线量化-快速开始 # 图像分类模型静态离线量化-快速开始
该教程以图像分类模型MobileNetV1为例,说明如何快速使用PaddleSlim的[离线量化接口](https://paddlepaddle.github.io/PaddleSlim/api_cn/quantization_api.html#quant-post)。 该示例包含以下步骤: 该教程以图像分类模型MobileNetV1为例,说明如何快速使用PaddleSlim的[静态离线量化接口](../api_cn/quantization_api.html#quant-post-static)。 该示例包含以下步骤:
1. 导入依赖 1. 导入依赖
2. 构建模型 2. 构建模型
3. 训练模型 3. 训练模型
4. 离线量化 4. 静态离线量化
## 1. 导入依赖 ## 1. 导入依赖
PaddleSlim依赖Paddle1.7版本,请确认已正确安装Paddle,然后按以下方式导入Paddle和PaddleSlim: PaddleSlim依赖Paddle1.7版本,请确认已正确安装Paddle,然后按以下方式导入Paddle和PaddleSlim:
...@@ -90,7 +90,7 @@ test(val_program) ...@@ -90,7 +90,7 @@ test(val_program)
``` ```
保存inference model,将训练好的分类模型保存在``'./inference_model'``下,后续进行离线量化时将加载保存在此处的模型。 保存inference model,将训练好的分类模型保存在``'./inference_model'``下,后续进行静态离线量化时将加载保存在此处的模型。
```python ```python
...@@ -102,29 +102,29 @@ fluid.io.save_inference_model(dirname='./inference_model', ...@@ -102,29 +102,29 @@ fluid.io.save_inference_model(dirname='./inference_model',
main_program=val_program) main_program=val_program)
``` ```
## 4. 离线量化 ## 4. 静态离线量化
调用离线量化接口,加载文件夹``'./inference_model'``训练好的分类模型,并使用10个batch的数据进行参数校正。此过程无需训练,只需跑前向过程来计算量化所需参数。离线量化后的模型保存在文件夹``'./quant_post_model'``下。 调用静态离线量化接口,加载文件夹``'./inference_model'``训练好的分类模型,并使用10个batch的数据进行参数校正。此过程无需训练,只需跑前向过程来计算量化所需参数。静态离线量化后的模型保存在文件夹``'./quant_post_static_model'``下。
```python ```python
slim.quant.quant_post( slim.quant.quant_post_static(
executor=exe, executor=exe,
model_dir='./inference_model', model_dir='./inference_model',
quantize_model_path='./quant_post_model', quantize_model_path='./quant_post_static_model',
sample_generator=reader.test(), sample_generator=reader.test(),
batch_nums=10) batch_nums=10)
``` ```
加载保存在文件夹``'./quant_post_model'``下的量化后的模型进行测试,可看到精度和``3.2 训练和测试``中得到的测试精度相近,因此离线量化过程对于此分类模型几乎无损。 加载保存在文件夹``'./quant_post_static_model'``下的量化后的模型进行测试,可看到精度和``3.2 训练和测试``中得到的测试精度相近,因此静态离线量化过程对于此分类模型几乎无损。
```python ```python
quant_post_prog, feed_target_names, fetch_targets = fluid.io.load_inference_model( quant_post_static_prog, feed_target_names, fetch_targets = fluid.io.load_inference_model(
dirname='./quant_post_model', dirname='./quant_post_static_model',
model_filename='__model__', model_filename='__model__',
params_filename='__params__', params_filename='__params__',
executor=exe) executor=exe)
test(quant_post_prog, fetch_targets) test(quant_post_static_prog, fetch_targets)
``` ```
# CPU部署预测INT8模型 # CPU上部署量化模型教程
在Intel(R) Xeon(R) Gold 6271机器上,经过量化和DNNL加速,INT8模型在单线程上性能为原FP32模型的3~4倍;在 Intel(R) Xeon(R) Gold 6148,单线程性能为原FP32模型的1.5倍,而精度仅有极小下降。图像分类量化的样例教程请参考[图像分类INT8模型在CPU优化部署和预测](https://github.com/PaddlePaddle/PaddleSlim/tree/develop/demo/mkldnn_quant/quant_aware/PaddleCV_mkldnn_quantaware_tutorial_cn.md)。自然语言处理模型的量化请参考[ERNIE INT8 模型精度与性能复现](https://github.com/PaddlePaddle/benchmark/tree/master/Inference/c%2B%2B/ernie/mkldnn) 在Intel(R) Xeon(R) Gold 6271机器上,经过量化和DNNL加速,INT8模型在单线程上性能为原FP32模型的3~4倍;在 Intel(R) Xeon(R) Gold 6148,单线程性能为原FP32模型的1.5倍,而精度仅有极小下降。图像分类量化的样例教程请参考[图像分类INT8模型在CPU优化部署和预测](https://github.com/PaddlePaddle/PaddleSlim/tree/develop/demo/mkldnn_quant/quant_aware/PaddleCV_mkldnn_quantaware_tutorial_cn.md)。自然语言处理模型的量化请参考[ERNIE INT8 模型精度与性能复现](https://github.com/PaddlePaddle/benchmark/tree/master/Inference/c%2B%2B/ernie/mkldnn)
......
...@@ -6,11 +6,11 @@ ...@@ -6,11 +6,11 @@
:maxdepth: 1 :maxdepth: 1
image_classification_sensitivity_analysis_tutorial.md image_classification_sensitivity_analysis_tutorial.md
image_classification_mkldnn_quant_aware_tutorial.md
darts_nas_turorial.md darts_nas_turorial.md
paddledetection_slim_distillation_tutorial.md paddledetection_slim_distillation_tutorial.md
paddledetection_slim_nas_tutorial.md paddledetection_slim_nas_tutorial.md
paddledetection_slim_pruing_tutorial.md paddledetection_slim_pruing_tutorial.md
paddledetection_slim_prune_dist_tutorial.md paddledetection_slim_prune_dist_tutorial.md
paddledetection_slim_quantization_tutorial.md paddledetection_slim_quantization_tutorial.md
image_classification_mkldnn_quant_aware_tutorial.md
paddledetection_slim_sensitivy_tutorial.md paddledetection_slim_sensitivy_tutorial.md
# 目标检测模型定点量化教程 # 目标检测模型量化教程
教程内容请参考:https://github.com/PaddlePaddle/PaddleDetection/blob/release/0.2/slim/quantization/README.md 教程内容请参考:https://github.com/PaddlePaddle/PaddleDetection/blob/release/0.2/slim/quantization/README.md
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
### 训练策略 ### 训练策略
- 量化策略`post`为使用离线量化得到的模型,`aware`为在线量化训练得到的模型。 - 量化策略`post`为使用静态离线量化方法得到的模型,`aware`为在线量化训练方法得到的模型。
### YOLOv3 on COCO ### YOLOv3 on COCO
......
...@@ -21,7 +21,8 @@ _logger = get_logger(__name__, level=logging.INFO) ...@@ -21,7 +21,8 @@ _logger = get_logger(__name__, level=logging.INFO)
try: try:
fluid.require_version('2.0.0') fluid.require_version('2.0.0')
from .quanter import quant_aware, quant_post, convert, quant_post_only_weight from .quanter import quant_aware, convert, quant_post_static, quant_post_dynamic
from .quanter import quant_post, quant_post_only_weight
except Exception as e: except Exception as e:
_logger.warning( _logger.warning(
"If you want to use training-aware and post-training quantization, " "If you want to use training-aware and post-training quantization, "
......
...@@ -233,7 +233,7 @@ def quant_aware(program, place, config=None, scope=None, for_test=False): ...@@ -233,7 +233,7 @@ def quant_aware(program, place, config=None, scope=None, for_test=False):
return quant_program return quant_program
def quant_post(executor, def quant_post_static(executor,
model_dir, model_dir,
quantize_model_path, quantize_model_path,
batch_generator=None, batch_generator=None,
...@@ -255,10 +255,10 @@ def quant_post(executor, ...@@ -255,10 +255,10 @@ def quant_post(executor,
is_use_cache_file=False, is_use_cache_file=False,
cache_dir="./temp_post_training"): cache_dir="./temp_post_training"):
""" """
The function utilizes post training quantization method to quantize the The function utilizes static post training quantization method to
fp32 model. It uses calibrate data to calculate the scale factor of quantize the fp32 model. It uses calibrate data to calculate the
quantized variables, and inserts fake quantization and dequantization scale factor of quantized variables, and inserts fake quantization
operators to obtain the quantized model. and dequantization operators to obtain the quantized model.
Args: Args:
executor(fluid.Executor): The executor to load, run and save the executor(fluid.Executor): The executor to load, run and save the
...@@ -340,26 +340,40 @@ def quant_post(executor, ...@@ -340,26 +340,40 @@ def quant_post(executor,
model_filename=save_model_filename, model_filename=save_model_filename,
params_filename=save_params_filename) params_filename=save_params_filename)
# We have changed the quant_post to quant_post_static.
# For compatibility, we keep quant_post api for now, and it will be
# deprecated in the future.
quant_post = quant_post_static
def convert(program, place, config=None, scope=None, save_int8=False): def convert(program, place, config=None, scope=None, save_int8=False):
""" """
convert quantized and well-trained ``program`` to final quantized ``program`` that can be used to save ``inference model``. convert quantized and well-trained ``program`` to final quantized
``program``that can be used to save ``inference model``.
Args: Args:
program(fluid.Program): quantized and well-trained ``test program``. program(fluid.Program): quantized and well-trained ``test program``.
place(fluid.CPUPlace or fluid.CUDAPlace): This parameter represents the executor run on which device. place(fluid.CPUPlace or fluid.CUDAPlace): This parameter represents
config(dict, optional): configs for convert. if set None, will use default config. the executor run on which device.
It must be same with config that used in 'quant_aware'. Default: None. config(dict, optional): configs for convert. if set None, will use
scope(fluid.Scope, optional): Scope records the mapping between variable names and variables, default config. It must be same with config that used in
similar to brackets in programming languages. Usually users can use 'quant_aware'. Default is None.
`fluid.global_scope <https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/executor_cn/global_scope_cn.html>`_. When ``None`` will use `fluid.global_scope() <https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/executor_cn/global_scope_cn.html>`_ . Default: ``None``. scope(fluid.Scope, optional): Scope records the mapping between
save_int8: Whether to return ``program`` which model parameters' dtype is ``int8``. variable names and variables, similar to brackets in
This parameter can only be used to get model size. Default: ``False``. programming languages. Usually users can use
`fluid.global_scope <https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/executor_cn/global_scope_cn.html>`_.
When ``None`` will use
`fluid.global_scope() <https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/executor_cn/global_scope_cn.html>`_
. Default: ``None``.
save_int8: Whether to return ``program`` which model parameters'
dtype is ``int8``. This parameter can only be used to
get model size. Default: ``False``.
Returns: Returns:
Tuple : freezed program which can be used for inference. Tuple : freezed program which can be used for inference.
when ``save_int8`` is False, return ``freezed_program(fluid.Program)``. when ``save_int8`` is False, return ``freezed_program(fluid.Program)``.
when ``save_int8`` is True, return ``freezed_program(fluid.Program)`` and ``freezed_program_int8(fluid.Program)`` when ``save_int8`` is True, return ``freezed_program(fluid.Program)``
and ``freezed_program_int8(fluid.Program)``
""" """
scope = fluid.global_scope() if not scope else scope scope = fluid.global_scope() if not scope else scope
...@@ -395,7 +409,7 @@ def convert(program, place, config=None, scope=None, save_int8=False): ...@@ -395,7 +409,7 @@ def convert(program, place, config=None, scope=None, save_int8=False):
return freezed_program return freezed_program
def quant_post_only_weight(model_dir, def quant_post_dynamic(model_dir,
save_model_dir, save_model_dir,
model_filename=None, model_filename=None,
params_filename=None, params_filename=None,
...@@ -405,19 +419,26 @@ def quant_post_only_weight(model_dir, ...@@ -405,19 +419,26 @@ def quant_post_only_weight(model_dir,
weight_bits=8, weight_bits=8,
generate_test_model=False): generate_test_model=False):
''' '''
In order to reduce the size of model, this api quantizes the weight The function utilizes static post training quantization method to
of some ops from float32 to int8/16. In the inference stage, the quantize the fp32 model. In details, it quantizes the weight of some
quantized weight will be dequantized to float32 again. ops from float32 to int8/16. For the quantized model, there are two
kinds of calculation method in the reference stage. Firstly, the
quantized weight will be dequantized to float32, and then apply the
float32 calculation. Secondly, collect the quantized scales of the
inputs, and then apply the int8 calculation.
Args: Args:
model_dir(str): The path of the fp32 model that will be quantized, model_dir(str): The path of the fp32 model that will be quantized,
and the model and params files are under the path. and the model and params files are under the path.
save_model_dir(str): The path to save the quantized model. save_model_dir(str): The path to save the quantized model.
model_filename(str, optional): The name of file used to load the inference model_filename(str, optional): The name of file used to load the
program. If it is None, the default filename '__model__' will be used. Default is 'None'. inference program. If it is None, the default filename
params_filename(str, optional): The name of file used to load all parameters. When all parameters were saved '__model__' will be used. Default is 'None'.
in a single binary file, set it as the real filename. If parameters were saved in separate files, params_filename(str, optional): The name of file used to load all
set it as 'None'. Default is 'None'. parameters. When all parameters were saved in a single
binary file, set it as the real filename. If parameters
were saved in separate files, set it as 'None'. Default is
'None'.
save_model_dir(str): The path used to save the quantized model. save_model_dir(str): The path used to save the quantized model.
save_model_filename(str, optional): The name of file to save_model_filename(str, optional): The name of file to
save the inference program. If it is None, the default save the inference program. If it is None, the default
...@@ -442,6 +463,7 @@ def quant_post_only_weight(model_dir, ...@@ -442,6 +463,7 @@ def quant_post_only_weight(model_dir,
model_dir=model_dir, model_dir=model_dir,
model_filename=model_filename, model_filename=model_filename,
params_filename=params_filename) params_filename=params_filename)
weight_quant.quantize_weight_to_int( weight_quant.quantize_weight_to_int(
save_model_dir=save_model_dir, save_model_dir=save_model_dir,
save_model_filename=save_model_filename, save_model_filename=save_model_filename,
...@@ -449,3 +471,9 @@ def quant_post_only_weight(model_dir, ...@@ -449,3 +471,9 @@ def quant_post_only_weight(model_dir,
quantizable_op_type=quantizable_op_type, quantizable_op_type=quantizable_op_type,
weight_bits=weight_bits, weight_bits=weight_bits,
generate_test_model=generate_test_model) generate_test_model=generate_test_model)
# We have changed the quant_post_only_weight to quant_post_dynamic.
# For compatibility, we keep quant_post_only_weight api for now,
# and it will be deprecated in the future.
quant_post_only_weight = quant_post_dynamic
\ No newline at end of file
...@@ -16,7 +16,7 @@ sys.path.append("../") ...@@ -16,7 +16,7 @@ sys.path.append("../")
import unittest import unittest
import paddle import paddle
import paddle.fluid as fluid import paddle.fluid as fluid
from paddleslim.quant import quant_post from paddleslim.quant import quant_post_static
sys.path.append("../demo") sys.path.append("../demo")
from models import MobileNet from models import MobileNet
from layers import conv_bn_layer from layers import conv_bn_layer
...@@ -98,7 +98,7 @@ class TestQuantAwareCase1(unittest.TestCase): ...@@ -98,7 +98,7 @@ class TestQuantAwareCase1(unittest.TestCase):
model_filename='model', model_filename='model',
params_filename='params') params_filename='params')
quant_post( quant_post_static(
exe, exe,
'./test_quant_post', './test_quant_post',
'./test_quant_post_inference', './test_quant_post_inference',
......
...@@ -16,7 +16,7 @@ sys.path.append("../") ...@@ -16,7 +16,7 @@ sys.path.append("../")
import unittest import unittest
import paddle import paddle
import paddle.fluid as fluid import paddle.fluid as fluid
from paddleslim.quant import quant_post_only_weight from paddleslim.quant import quant_post_dynamic
sys.path.append("../demo") sys.path.append("../demo")
from models import MobileNet from models import MobileNet
from layers import conv_bn_layer from layers import conv_bn_layer
...@@ -90,7 +90,7 @@ class TestQuantPostOnlyWeightCase1(unittest.TestCase): ...@@ -90,7 +90,7 @@ class TestQuantPostOnlyWeightCase1(unittest.TestCase):
train(main_prog) train(main_prog)
top1_1, top5_1 = test(val_prog) top1_1, top5_1 = test(val_prog)
fluid.io.save_inference_model( fluid.io.save_inference_model(
dirname='./test_quant_post', dirname='./test_quant_post_dynamic',
feeded_var_names=[image.name, label.name], feeded_var_names=[image.name, label.name],
target_vars=[avg_cost, acc_top1, acc_top5], target_vars=[avg_cost, acc_top1, acc_top5],
main_program=val_prog, main_program=val_prog,
...@@ -98,7 +98,7 @@ class TestQuantPostOnlyWeightCase1(unittest.TestCase): ...@@ -98,7 +98,7 @@ class TestQuantPostOnlyWeightCase1(unittest.TestCase):
model_filename='model', model_filename='model',
params_filename='params') params_filename='params')
quant_post_only_weight( quant_post_dynamic(
model_dir='./test_quant_post', model_dir='./test_quant_post',
save_model_dir='./test_quant_post_inference', save_model_dir='./test_quant_post_inference',
model_filename='model', model_filename='model',
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册