From f984f0580c9f0b8792a15af913567d079c37b2e6 Mon Sep 17 00:00:00 2001 From: Liufang Sang Date: Sat, 12 Oct 2019 12:03:32 +0800 Subject: [PATCH] [PaddleSlim] add eval and infer cmd example in doc (#3519) --- PaddleSlim/classification/eval.py | 34 +++++++++++--- PaddleSlim/classification/infer.py | 9 ++-- .../classification/quantization/README.md | 44 ++++++++++++++++++- 3 files changed, 77 insertions(+), 10 deletions(-) diff --git a/PaddleSlim/classification/eval.py b/PaddleSlim/classification/eval.py index 43e10659..f091a9e9 100644 --- a/PaddleSlim/classification/eval.py +++ b/PaddleSlim/classification/eval.py @@ -29,6 +29,8 @@ parser = argparse.ArgumentParser(description=__doc__) add_arg = functools.partial(add_arguments, argparser=parser) add_arg('use_gpu', bool, False, "Whether to use GPU or not.") add_arg('model_path', str, "./pruning/checkpoints/resnet50/2/eval_model/", "Whether to use pretrained model.") +add_arg('model_name', str, "__model__", "model filename for inference model") +add_arg('params_name', str, "__params__", "params filename for inference model") # yapf: enable def eval(args): @@ -39,8 +41,8 @@ def eval(args): val_program, feed_target_names, fetch_targets = fluid.io.load_inference_model(args.model_path, exe, - model_filename="__model__", - params_filename="__params__") + model_filename=args.model_name, + params_filename=args.params_name) val_reader = paddle.batch(reader.val(), batch_size=128) feeder = fluid.DataFeeder(place=place, feed_list=feed_target_names, program=val_program) @@ -48,11 +50,33 @@ def eval(args): for batch_id, data in enumerate(val_reader()): # top1_acc, top5_acc - result = exe.run(val_program, + if len(feed_target_names) == 1: + # eval "infer model", which input is image, output is classification probability + image = [[d[0]] for d in data] + label = [[d[1]] for d in data] + feed_data = feeder.feed(image) + pred = exe.run(val_program, + feed=feed_data, + fetch_list=fetch_targets) + pred = np.array(pred[0]) + label = np.array(label) + sort_array = pred.argsort(axis=1) + top_1_pred = sort_array[:, -1:][:, ::-1] + top_1 = np.mean(label == top_1_pred) + top_5_pred = sort_array[:, -5:][:, ::-1] + acc_num = 0 + for i in range(len(label)): + if label[i][0] in top_5_pred[i]: + acc_num += 1 + top_5 = acc_num / len(label) + results.append([top_1, top_5]) + else: + # eval "eval model", which inputs are image and label, output is top1 and top5 accuracy + result = exe.run(val_program, feed=feeder.feed(data), fetch_list=fetch_targets) - result = [np.mean(r) for r in result] - results.append(result) + result = [np.mean(r) for r in result] + results.append(result) result = np.mean(np.array(results), axis=0) print("top1_acc/top5_acc= {}".format(result)) sys.stdout.flush() diff --git a/PaddleSlim/classification/infer.py b/PaddleSlim/classification/infer.py index 127b1404..9f872301 100644 --- a/PaddleSlim/classification/infer.py +++ b/PaddleSlim/classification/infer.py @@ -29,6 +29,8 @@ parser = argparse.ArgumentParser(description=__doc__) add_arg = functools.partial(add_arguments, argparser=parser) add_arg('use_gpu', bool, False, "Whether to use GPU or not.") add_arg('model_path', str, "./pruning/checkpoints/resnet50/2/eval_model/", "Whether to use pretrained model.") +add_arg('model_name', str, "__model__.infer", "inference model filename") +add_arg('params_name', str, "__params__", "inference model params filename") # yapf: enable def infer(args): @@ -39,8 +41,8 @@ def infer(args): test_program, feed_target_names, fetch_targets = fluid.io.load_inference_model(args.model_path, exe, - model_filename="__model__.infer", - params_filename="__params__") + model_filename=args.model_name, + params_filename=args.params_name) test_reader = paddle.batch(reader.test(), batch_size=1) feeder = fluid.DataFeeder(place=place, feed_list=feed_target_names, program=test_program) @@ -51,7 +53,8 @@ def infer(args): result = exe.run(test_program, feed=feeder.feed(data), fetch_list=fetch_targets) - print result + result = np.array(result[0]) + print(result.argsort(axis=1)[:,-1:][::-1]) sys.stdout.flush() def main(): diff --git a/PaddleSlim/classification/quantization/README.md b/PaddleSlim/classification/quantization/README.md index be65ff71..77a81207 100644 --- a/PaddleSlim/classification/quantization/README.md +++ b/PaddleSlim/classification/quantization/README.md @@ -94,6 +94,13 @@ QuantizationFreezePass主要用于改变IrGraph中量化op和反量化op的顺 图4:应用TransformForMobilePass后的结果

+> 综上,可得在量化过程中有以下几种模型结构: +1. 原始模型 +2. 经QuantizationTransformPass之后得到的适用于训练的量化模型结构,在${checkpoint_path}下保存的`eval_model`是这种结构,在训练过程中每个epoch结束时也使用这个网络结构进行评估,虽然这个模型结构不是最终想要的模型结构,但是每个epoch的评估结果可用来挑选模型。 +3. 经QuantizationFreezePass之后得到的FP32模型结构,具体结构已在上面进行介绍。本文档中列出的数据集的评估结果是对FP32模型结构进行评估得到的结果。这种模型结构在训练过程中只会保存一次,也就是在量化配置文件中设置的`end_epoch`结束时进行保存,如果想将其他epoch的训练结果转化成FP32模型,可使用脚本 PaddleSlim/classification/quantization/freeze.py进行转化,具体使用方法在[评估](#评估)中介绍。 +4. 经ConvertToInt8Pass之后得到的8-bit模型结构,具体结构已在上面进行介绍。这种模型结构在训练过程中只会保存一次,也就是在量化配置文件中设置的`end_epoch`结束时进行保存,如果想将其他epoch的训练结果转化成8-bit模型,可使用脚本 PaddleSlim/classification/quantization/freeze.py进行转化,具体使用方法在[评估](#评估)中介绍。 +5. 经TransformForMobilePass之后得到的mobile模型结构,具体结构已在上面进行介绍。这种模型结构在训练过程中只会保存一次,也就是在量化配置文件中设置的`end_epoch`结束时进行保存,如果想将其他epoch的训练结果转化成mobile模型,可使用脚本 PaddleSlim/classification/quantization/freeze.py进行转化,具体使用方法在[评估](#评估)中介绍。 + ## 评估 ### 每个epoch保存的评估模型 @@ -106,14 +113,38 @@ QuantizationFreezePass主要用于改变IrGraph中量化op和反量化op的顺 脚本PaddleSlim/classification/eval.py中为使用该模型在评估数据集上做评估的示例。 -在评估之后,选取效果最好的epoch的模型,可使用脚本 PaddleSlim/classification/freeze.py将该模型转化为以上介绍的三种模型:FP32模型,8-bit模型,mobile模型,需要配置的参数为: +运行命令示例: +``` +python eval.py \ + --use_gpu 1 \ + --model_path ${checkpoint_path}/${epoch_id}/eval_model +``` + +在评估之后,选取效果最好的epoch的模型,可使用脚本 PaddleSlim/classification/quantization/freeze.py将该模型转化为以上介绍的三种模型:FP32模型,8-bit模型,mobile模型,需要配置的参数为: - model_path, 加载的模型路径,`为${checkpoint_path}/${epoch_id}/eval_model/` - weight_quant_type 模型参数的量化方式,和配置文件中的类型保持一致 - save_path `FP32`, `8-bit`, `mobile`模型的保存路径,分别为 `${save_path}/float/`, `${save_path}/int8/`, `${save_path}/mobile/` +运行命令示例: +``` +python freeze.py \ + --model_path ${checkpoint_path}/${epoch_id}/eval_model/ \ + --weight_quant_type ${weight_quant_type} \ + --save_path ${any path you want} +``` + ### 最终评估模型 -最终使用的评估模型是FP32模型,使用脚本PaddleSlim/classification/eval.py中为使用该模型在评估数据集上做评估的示例。 +最终使用的评估模型是FP32模型,使用脚本PaddleSlim/classification/eval.py该模型在评估数据集上做评估。 +运行命令示例: +``` +python eval.py \ + --use_gpu 1 \ + --model_path ${save_path}/float \ + --model_name model \ + --params_name weights + +``` ## 预测 @@ -123,6 +154,15 @@ FP32模型可直接使用原生PaddlePaddle Fluid预测方法进行预测。 在脚本PaddleSlim/classification/infer.py中展示了如何使用fluid python API加载使用预测模型进行预测。 +运行命令示例: +``` +python infer.py \ + --model_path ${save_path}/float \ + --use_gpu 1 \ + --model_name model \ + --params_name weights +``` + ### PaddleLite预测 FP32模型可使用Paddle-Lite进行加载预测,可参见教程[Paddle-Lite如何加载运行量化模型](https://github.com/PaddlePaddle/Paddle-Lite/wiki/model_quantization)。 -- GitLab