From ea8299a9d1fa317a15133cdce114c73d7dea176f Mon Sep 17 00:00:00 2001
From: Liufang Sang
Date: Fri, 11 Oct 2019 12:55:53 +0800
Subject: [PATCH] fix yolov3 quantization doc (#3491)
---
.../slim/quantization/README.md | 78 +++++++++++-----
.../slim/quantization/compress.py | 3 +-
.../PaddleDetection/slim/quantization/eval.py | 14 ++-
.../quantization/images/ConvertToInt8Pass.png | Bin 0 -> 87692 bytes
.../slim/quantization/images/FreezePass.png | Bin 0 -> 113558 bytes
.../images/TransformForMobilePass.png | Bin 0 -> 93620 bytes
.../quantization/images/TransformPass.png | Bin 0 -> 135591 bytes
.../quantization/yolov3_mobilenet_v1_voc.yml | 87 ++++++++++++++++++
8 files changed, 156 insertions(+), 26 deletions(-)
create mode 100644 PaddleCV/PaddleDetection/slim/quantization/images/ConvertToInt8Pass.png
create mode 100644 PaddleCV/PaddleDetection/slim/quantization/images/FreezePass.png
create mode 100644 PaddleCV/PaddleDetection/slim/quantization/images/TransformForMobilePass.png
create mode 100644 PaddleCV/PaddleDetection/slim/quantization/images/TransformPass.png
create mode 100644 PaddleCV/PaddleDetection/slim/quantization/yolov3_mobilenet_v1_voc.yml
diff --git a/PaddleCV/PaddleDetection/slim/quantization/README.md b/PaddleCV/PaddleDetection/slim/quantization/README.md
index 5c53d275..b044778e 100644
--- a/PaddleCV/PaddleDetection/slim/quantization/README.md
+++ b/PaddleCV/PaddleDetection/slim/quantization/README.md
@@ -37,7 +37,23 @@
- config: 检测库的配置,其中配置了训练超参数、数据集信息等。
- slim_file: PaddleSlim的配置文件,参见[配置文件说明](#配置文件说明)。
-您可以通过运行脚本`run.sh`运行该示例,请确保已正确下载[pretrained model](https://github.com/PaddlePaddle/models/tree/develop/PaddleCV/image_classification#%E5%B7%B2%E5%8F%91%E5%B8%83%E6%A8%A1%E5%9E%8B%E5%8F%8A%E5%85%B6%E6%80%A7%E8%83%BD)。
+您可以通过运行以下命令运行该示例,请确保已正确下载[pretrained model](https://github.com/PaddlePaddle/models/tree/develop/PaddleCV/image_classification#%E5%B7%B2%E5%8F%91%E5%B8%83%E6%A8%A1%E5%9E%8B%E5%8F%8A%E5%85%B6%E6%80%A7%E8%83%BD)。
+
+step1: 开启显存优化策略
+```
+export FLAGS_fast_eager_deletion_mode=1
+export FLAGS_eager_delete_tensor_gb=0.0
+```
+step2: 设置gpu卡
+```
+export CUDA_VISIBLE_DEVICES=0
+```
+step3: 开始训练
+```
+python compress.py \
+ -s yolov3_mobilenet_v1_slim.yaml \
+ -c yolov3_mobilenet_v1_voc.yml
+```
### 训练时的模型结构
这部分介绍来源于[量化low-level API介绍](https://github.com/PaddlePaddle/models/tree/develop/PaddleSlim/quant_low_level_api#1-%E9%87%8F%E5%8C%96%E8%AE%AD%E7%BB%83low-level-apis%E4%BB%8B%E7%BB%8D)。
@@ -58,23 +74,12 @@ PaddlePaddle框架中有四个和量化相关的IrPass, 分别是QuantizationTra
>注意:配置文件中的信息不会保存在断点中,重启前对配置文件的修改将会生效。
-## 评估
-
-如果在配置文件中设置了`checkpoint_path`,则每个epoch会保存一个量化后的用于评估的模型,
-该模型会保存在`${checkpoint_path}/${epoch_id}/eval_model/`路径下,包含`__model__`和`__params__`两个文件。
-其中,`__model__`用于保存模型结构信息,`__params__`用于保存参数(parameters)信息。模型结构和训练时一样。
-
-如果不需要保存评估模型,可以在定义Compressor对象时,将`save_eval_model`选项设置为False(默认为True)。
-
-脚本slim/quantization/eval.py中为使用该模型在评估数据集上做评估的示例。
-
-
-## 预测
+### 保存评估和预测模型
如果在配置文件的量化策略中设置了`float_model_save_path`, `int8_model_save_path`, `mobile_model_save_path`, 在训练结束后,会保存模型量化压缩之后用于预测的模型。接下来介绍这三种预测模型的区别。
-### float预测模型
-在介绍量化训练时的模型结构时介绍了PaddlePaddle框架中有四个和量化相关的IrPass, 分别是QuantizationTransformPass、QuantizationFreezePass、ConvertToInt8Pass以及TransformForMobilePass。float预测模型是在应用QuantizationFreezePass并删除eval_program中多余的operators之后,保存的模型。
+#### FP32模型
+在介绍量化训练时的模型结构时介绍了PaddlePaddle框架中有四个和量化相关的IrPass, 分别是QuantizationTransformPass、QuantizationFreezePass、ConvertToInt8Pass以及TransformForMobilePass。FP32模型是在应用QuantizationFreezePass并删除eval_program中多余的operators之后,保存的模型。
QuantizationFreezePass主要用于改变IrGraph中量化op和反量化op的顺序,即将类似图1中的量化op和反量化op顺序改变为图2中的布局。除此之外,QuantizationFreezePass还会将`conv2d`、`depthwise_conv2d`、`mul`等算子的权重离线量化为int8_t范围内的值(但数据类型仍为float32),以减少预测过程中对权重的量化操作,示例如图2:
@@ -83,7 +88,7 @@ QuantizationFreezePass主要用于改变IrGraph中量化op和反量化op的顺
图2:应用QuantizationFreezePass后的结果
-### int8预测模型
+#### 8-bit模型
在对训练网络进行QuantizationFreezePass之后,执行ConvertToInt8Pass,
其主要目的是将执行完QuantizationFreezePass后输出的权重类型由`FP32`更改为`INT8`。换言之,用户可以选择将量化后的权重保存为float32类型(不执行ConvertToInt8Pass)或者int8_t类型(执行ConvertToInt8Pass),示例如图3:
@@ -92,7 +97,7 @@ QuantizationFreezePass主要用于改变IrGraph中量化op和反量化op的顺
图3:应用ConvertToInt8Pass后的结果
-### mobile预测模型
+#### mobile模型
经TransformForMobilePass转换后,用户可得到兼容[paddle-lite](https://github.com/PaddlePaddle/Paddle-Lite)移动端预测库的量化模型。paddle-mobile中的量化op和反量化op的名称分别为`quantize`和`dequantize`。`quantize`算子和PaddlePaddle框架中的`fake_quantize_abs_max`算子簇的功能类似,`dequantize` 算子和PaddlePaddle框架中的`fake_dequantize_max_abs`算子簇的功能相同。若选择paddle-mobile执行量化训练输出的模型,则需要将`fake_quantize_abs_max`等算子改为`quantize`算子以及将`fake_dequantize_max_abs`等算子改为`dequantize`算子,示例如图4:
@@ -100,18 +105,43 @@ QuantizationFreezePass主要用于改变IrGraph中量化op和反量化op的顺
图4:应用TransformForMobilePass后的结果
-### python预测
+## 评估
+### 每个epoch保存的评估模型
+因为量化的最终模型只有在end_epoch时保存一次,不能保证保存的模型是最好的,因此
+如果在配置文件中设置了`checkpoint_path`,则每个epoch会保存一个量化后的用于评估的模型,
+该模型会保存在`${checkpoint_path}/${epoch_id}/eval_model/`路径下,包含`__model__`和`__params__`两个文件。
+其中,`__model__`用于保存模型结构信息,`__params__`用于保存参数(parameters)信息。模型结构和训练时一样。
-### PaddleLite预测
-float预测模型可使用PaddleLite进行加载预测,可参见教程[Paddle-Lite如何加载运行量化模型](https://github.com/PaddlePaddle/Paddle-Lite/wiki/model_quantization)
+如果不需要保存评估模型,可以在定义Compressor对象时,将`save_eval_model`选项设置为False(默认为True)。
+
+脚本slim/quantization/eval.py中为使用该模型在评估数据集上做评估的示例。
+运行命令为:
+```
+python eval.py --model_path ${checkpoint_path}/${epoch_id}/eval_model/ --model_name __model__ --params_name __params__ -c yolov3_mobilenet_v1_voc.yml
+```
-## 从评估模型保存预测模型
-从[配置文件说明](#配置文件说明)中可以看到,在 `end_epoch` 时将保存可用于预测的 `float`, `int8`, `mobile`模型,但是在训练之前不能准确地保存结果最好的epoch的结果,因此,提供了从`${checkpoint_path}/${epoch_id}/eval_model/`下保存的评估模型转化为预测模型的接口 `freeze.py `, 需要配置的参数为:
+在评估之后,选取效果最好的epoch的模型,可使用脚本 slim/quantization/freeze.py将该模型转化为以上介绍的三种模型:float模型,int8模型,mobile模型,需要配置的参数为:
- model_path, 加载的模型路径,`为${checkpoint_path}/${epoch_id}/eval_model/`
- weight_quant_type 模型参数的量化方式,和配置文件中的类型保持一致
-- save_path `float`, `int8`, `mobile`模型的保存路径,分别为 `${save_path}/float/`, `${save_path}/int8/`, `${save_path}/mobile/`
+- save_path `FP32`, `8-bit`, `mobile`模型的保存路径,分别为 `${save_path}/float/`, `${save_path}/int8/`, `${save_path}/mobile/`
+
+### 最终评估模型
+最终使用的评估模型是float模型,使用脚本slim/quantization/eval.py中为使用该模型在评估数据集上做评估的示例。
+运行命令为:
+```
+python eval.py --model_path ${float_model_path} --model_name model --params_name params -c yolov3_mobilenet_v1_voc.yml
+```
+
+## 预测
+
+### python预测
+
+
+### PaddleLite预测
+FP32模型可使用PaddleLite进行加载预测,可参见教程[Paddle-Lite如何加载运行量化模型](https://github.com/PaddlePaddle/Paddle-Lite/wiki/model_quantization)
+
## 示例结果
@@ -128,3 +158,5 @@ float预测模型可使用PaddleLite进行加载预测,可参见教程[Paddle-
## FAQ
+
+
diff --git a/PaddleCV/PaddleDetection/slim/quantization/compress.py b/PaddleCV/PaddleDetection/slim/quantization/compress.py
index ef4319e1..70166f14 100644
--- a/PaddleCV/PaddleDetection/slim/quantization/compress.py
+++ b/PaddleCV/PaddleDetection/slim/quantization/compress.py
@@ -198,7 +198,8 @@ def main():
exe.run(startup_prog)
start_iter = 0
- checkpoint.load_pretrain(exe, train_prog, cfg.pretrain_weights)
+
+ checkpoint.load_params(exe, train_prog, cfg.pretrain_weights)
def eval_func(program, scope):
diff --git a/PaddleCV/PaddleDetection/slim/quantization/eval.py b/PaddleCV/PaddleDetection/slim/quantization/eval.py
index df817a66..e4f162a5 100644
--- a/PaddleCV/PaddleDetection/slim/quantization/eval.py
+++ b/PaddleCV/PaddleDetection/slim/quantization/eval.py
@@ -142,8 +142,8 @@ def main():
assert os.path.exists(FLAGS.model_path)
infer_prog, feed_names, fetch_targets = fluid.io.load_inference_model(
dirname=FLAGS.model_path, executor=exe,
- model_filename='model',
- params_filename='params')
+ model_filename=FLAGS.model_name,
+ params_filename=FLAGS.params_name)
eval_keys = ['bbox', 'gt_box', 'gt_label', 'is_difficult']
eval_values = ['multiclass_nms_0.tmp_0', 'gt_box', 'gt_label', 'is_difficult']
@@ -179,6 +179,16 @@ if __name__ == '__main__':
default=None,
type=str,
help="Dataset path, same as DataFeed.dataset.dataset_dir")
+ parser.add_argument(
+ "--model_name",
+ default='model',
+ type=str,
+ help="model file name to load_inference_model")
+ parser.add_argument(
+ "--params_name",
+ default='params',
+ type=str,
+ help="params file name to load_inference_model")
FLAGS = parser.parse_args()
main()
diff --git a/PaddleCV/PaddleDetection/slim/quantization/images/ConvertToInt8Pass.png b/PaddleCV/PaddleDetection/slim/quantization/images/ConvertToInt8Pass.png
new file mode 100644
index 0000000000000000000000000000000000000000..8b5849819c0bc8e592dc8f864d8945330df85ab1
GIT binary patch
literal 87692
zcmeEug;!MV_pcxz0s?}dbV*4`cc^p=(y4SycZmo}=g=L}Fu(vqi{#MA(4jO#cXJQm
z`~AMZd)NI7?mcTUi*?qC=h?kKd++mASyAc{1~JCHd-op6NQY&eZcj!hTXvtKqu{;9Y&_0-w?<9L)AD8fyFN3+xbi{$iz9^E
z2DSQ6RtX7Zad8RUoTqDz$9S(P3DBP}dd_yI&P-TSnZ#`LU#+