Skip to content

Commit eda52f4

Browse files
authored
[Enhancement] Replace with_xxx with output_op in export.py (#2547)
* [Enhancement] Replace with_xxx with output_op in export.py
1 parent d01eef2 commit eda52f4

File tree

3 files changed

+86
-98
lines changed

3 files changed

+86
-98
lines changed

docs/model_export.md

+25-26
Original file line numberDiff line numberDiff line change
@@ -2,54 +2,53 @@ English | [简体中文](model_export_cn.md)
22

33
# Model Export
44

5-
The trained model needs to be exported as a prediction model before deployment.
5+
After model training, we can export the inference model and deploy it using inference library, which achieves faster inference speed.
66

77
This tutorial will show how to export a trained model。
88

99

10-
## Acquire the Pre-training Model
10+
## Acquire trained weight
11+
12+
After model training, the weight with the highest accuracy is saved in ` path/to/save/best_ model/model.pdparams`.
13+
14+
For the convenience of this demo, we run the following commands to download the [trained weight](https://paddleseg.bj.bcebos.com/dygraph/cityscapes/pp_liteseg_stdc1_cityscapes_1024x512_scale0.5_160k/model.pdparams) of PP-LiteSeg.
15+
1116

12-
In this example,BiseNetV2 model will be used. Run the following command or click [link](https://paddleseg.bj.bcebos.com/dygraph/cityscapes/bisenet_cityscapes_1024x1024_160k/model.pdparams) to download the pretrained model.
1317
```shell
14-
mkdir bisenet && cd bisenet
15-
wget https://paddleseg.bj.bcebos.com/dygraph/cityscapes/bisenet_cityscapes_1024x1024_160k/model.pdparams
16-
cd ..
18+
wget https://paddleseg.bj.bcebos.com/dygraph/cityscapes/pp_liteseg_stdc1_cityscapes_1024x512_scale0.5_160k/model.pdparams
1719
```
1820

1921
## Export the prediction Model
2022

21-
Make sure you have installed PaddleSeg and are in the PaddleSeg directory.
22-
23-
Run the following command, and the prediction model will be saved in `output` directory.
23+
Run the following command in the root of PaddleSeg, the inference model is saved in `output/inference_model`.
2424

2525
```shell
26-
export CUDA_VISIBLE_DEVICES=0 # Set a usable GPU.
27-
# If on windows, Run the following command:
28-
# set CUDA_VISIBLE_DEVICES=0
2926
python export.py \
30-
--config configs/bisenet/bisenet_cityscapes_1024x1024_160k.yml \
31-
--model_path bisenet/model.pdparams\
32-
--save_dir output
33-
--input_shape 1 3 512 1024
27+
--config configs/pp_liteseg/pp_liteseg_stdc1_cityscapes_1024x512_scale0.5_160k.yml \
28+
--model_path model.pdparams \
29+
--save_dir output/inference_model
3430
```
3531

36-
### Description of Exported Script Parameters
32+
**Description of Exported Script Parameters**
3733

38-
|parammeter|purpose|is needed|default|
34+
|Parammeter|Purpose|Is Needed|Default|
3935
|-|-|-|-|
40-
|config|Config file|yes|-|
41-
|save_dir|Save root path for model and VisualDL log files|no|output|
42-
|model_path|Path of pre-training model parameters|no|The value in config file|
43-
|with_softmax|Add softmax operator at the end of the network. Since PaddleSeg networking returns Logits by default, you can set it to True if you want the deployment model to get the probability value|no|False|
44-
|without_argmax|Whether or not to add argmax operator at the end of the network. Since PaddleSeg networking returns Logits by default, we add argmax operator at the end of the network by default in order to directly obtain the prediction results for the deployment model|no|False|
45-
|input_shape| Set the input shape of exported model, such as `--input_shape 1 3 1024 1024`。if input_shape is not provided,the Default input shape of exported model is [-1, 3, -1, -1] | no (If the image shape in prediction is consistent, you should set the input_shape) | None |
36+
|config|The path of config file|yes|-|
37+
|model_path|The path of trained weight|no|-|
38+
|save_dir| The save dir for the inference model|no|output/inference_model|
39+
|input_shape| Set the input shape (`N*C*H*W`) of the inference model, such as `--input_shape 1 3 1024 1024`。if input_shape is not provided,the input shape of the inference model is [-1, 3, -1, -1]. If the image shape in prediction is fixed, you should set the input_shape. | no | None |
40+
|output_op | Set the op that is appended to the inference model, should in [`argmax`, `softmax`, `none`]. PaddleSeg models outputs logits (`N*C*H*W`) by default. Adding `argmax` operation, we get the label for every pixel, the dimension of output is `N*H*W`. Adding `softmax` operation, we get the probability of different classes for every pixel. | no | argmax |
41+
|with_softmax| Deprecated params, please use --output_op. Add softmax operator at the end of the network. Since PaddleSeg networking returns Logits by default, you can set it to True if you want the deployment model to get the probability value|no|False|
42+
|without_argmax|Deprecated params, please use --output_op. Whether or not to add argmax operator at the end of the network. Since PaddleSeg networking returns Logits by default, we add argmax operator at the end of the network by default in order to directly obtain the prediction results for the deployment model|no|False|
43+
4644

47-
**If you encounter shape-relevant issue, please try to set the input_shape.**
45+
Note that:
46+
* If you encounter shape-relevant issue, please try to set the input_shape.
4847

4948
## Prediction Model Files
5049

5150
```shell
52-
output
51+
output/inference_model
5352
├── deploy.yaml # Config file of deployment
5453
├── model.pdiparams # Paramters of static model
5554
├── model.pdiparams.info # Additional information witch is not concerned generally

docs/model_export_cn.md

+23-26
Original file line numberDiff line numberDiff line change
@@ -2,56 +2,53 @@
22

33
# 导出预测模型
44

5-
PaddleSeg训练好模型后,需要将模型导出为预测模型,才可以进行模型部署
5+
使用PaddleSeg训练好模型后,我们将模型导出为预测模型、使用预测库进行部署,可以实现更快的推理速度
66

7-
本教程提供一个示例介绍模型导出的过程
7+
本教程基于一个示例介绍模型导出的过程
88

9-
## 1. 获取预训练莫模型
9+
## 1. 获取模型权重
1010

11-
本示例中,我们使用BiseNetV2模型,大家执行如下命令或者点击[链接](https://paddleseg.bj.bcebos.com/dygraph/cityscapes/bisenet_cityscapes_1024x1024_160k/model.pdparams)下载模型预训练权重。
11+
完成模型训练后,精度最高的模型权重保存在`path/to/save/best_model/model.pdparams`
12+
13+
本示例为了演示方便,大家执行如下命令或者点击[链接](https://paddleseg.bj.bcebos.com/dygraph/cityscapes/pp_liteseg_stdc1_cityscapes_1024x512_scale0.5_160k/model.pdparams)下载PP-LiteSeg模型训练好的权重。
1214

1315
```shell
14-
mkdir bisenet && cd bisenet
15-
wget https://paddleseg.bj.bcebos.com/dygraph/cityscapes/bisenet_cityscapes_1024x1024_160k/model.pdparams
16-
cd ..
16+
wget https://paddleseg.bj.bcebos.com/dygraph/cityscapes/pp_liteseg_stdc1_cityscapes_1024x512_scale0.5_160k/model.pdparams
1717
```
1818

1919
## 2. 导出预测模型
2020

21-
确保正确安装PaddleSeg后,在PaddleSeg目录下执行如下命令,则预测模型会保存在output文件夹
21+
在PaddleSeg根目录下,执行如下命令,导出预测模型,保存在`output/inference_model`目录
2222

2323
```shell
24-
# 设置1张可用的卡
25-
export CUDA_VISIBLE_DEVICES=0
26-
# windows下请执行以下命令
27-
# set CUDA_VISIBLE_DEVICES=0
2824
python export.py \
29-
--config configs/bisenet/bisenet_cityscapes_1024x1024_160k.yml \
30-
--model_path bisenet/model.pdparams \
31-
--save_dir output
32-
--input_shape 1 3 512 1024
25+
--config configs/pp_liteseg/pp_liteseg_stdc1_cityscapes_1024x512_scale0.5_160k.yml \
26+
--model_path model.pdparams \
27+
--save_dir output/inference_model
3328
```
3429

35-
### 导出脚本参数解释
30+
**导出脚本参数解释**
3631

3732
|参数名|用途|是否必选项|默认值|
3833
|-|-|-|-|
39-
|config|配置文件||-|
40-
|model_path|预训练权重的路径||配置文件中指定的预训练权重路径|
41-
|save_dir|保存预测模型的路径||output|
42-
|input_shape| 设置导出模型的输入shape,比如传入`--input_shape 1 3 1024 1024`。如果不设置input_shape,默认导出模型的输入shape是[-1, 3, -1, -1] | 否( 如果预测shape固定,建议指定input_shape参数 ) | None |
43-
|with_softmax|在网络末端添加softmax算子。由于PaddleSeg组网默认返回logits,如果想要部署模型获取概率值,可以置为True||False|
44-
|without_argmax|是否不在网络末端添加argmax算子。由于PaddleSeg组网默认返回logits,为部署模型可以直接获取预测结果,我们默认在网络末端添加argmax算子||False|
34+
|config | 配置文件的路径 || - |
35+
|model_path | 模型权重的路径 || - |
36+
|save_dir | 预测模型保存的目录 || `./output/inference_model` |
37+
|input_shape | 设置模型的输入shape (`N*C*H*W`),比如传入`--input_shape 1 3 1024 1024`。如果不设置input_shape,默认导出模型的输入shape是`[-1, 3, -1, -1]`。 预测shape固定时,建议指定input_shape参数。 || None |
38+
|output_op | 设置在模型末端添加的输出算子,支持[`argmax`, `softmax`, `none`]。PaddleSeg模型默认返回logits (`N*C*H*W`);添加`argmax`算子,可以得到每个像素的分割类别,结果的维度是`N*H*W`、数据类型是`int32`;添加`softmax`算子,可以得到每个像素每类的概率,结果的维度是`N*C*H*W`、数据类型是`float32` || argmax |
39+
|with_softmax | 即将废弃的输入参数,建议使用`--output_op`。在网络末端添加softmax算子。由于PaddleSeg组网默认返回logits,如果想要部署模型获取概率值,可以置为True || False |
40+
|without_argmax| 即将废弃的输入参数,建议使用`--output_op`。由于PaddleSeg组网默认返回logits,为部署模型可以直接获取预测结果,我们默认在网络末端添加argmax算子。如果设置`--without_argmax`,则不会在网络末端添加argmax算子。 || False |
4541

46-
**如果导出出现和shape相关的问题,请尝试指定input_shape。**
42+
注意:
43+
* 如果部署模型时,出现和shape相关的问题,请尝试指定input_shape。
4744

4845
## 3. 预测模型文件
4946

5047
如下是导出的预测模型文件。
5148

5249
```shell
53-
output
54-
├── deploy.yaml # 部署相关的配置文件,主要说明数据预处理的方式
50+
output/inference_model
51+
├── deploy.yaml # 部署相关的配置文件,主要说明数据预处理方式等信息
5552
├── model.pdmodel # 预测模型的拓扑结构文件
5653
├── model.pdiparams # 预测模型的权重文件
5754
└── model.pdiparams.info # 参数额外信息,一般无需关注

export.py

+38-46
Original file line numberDiff line numberDiff line change
@@ -24,35 +24,27 @@
2424

2525
def parse_args():
2626
parser = argparse.ArgumentParser(description='Model export.')
27-
# params of training
2827
parser.add_argument(
29-
"--config",
30-
dest="cfg",
31-
help="The config file.",
32-
default=None,
33-
type=str,
34-
required=True)
28+
"--config", help="The config file.", type=str, required=True)
29+
parser.add_argument(
30+
'--model_path', help='The path of model for export', type=str)
3531
parser.add_argument(
3632
'--save_dir',
37-
dest='save_dir',
3833
help='The directory for saving the exported model',
3934
type=str,
40-
default='./output')
35+
default='./output/inference_model')
4136
parser.add_argument(
42-
'--model_path',
43-
dest='model_path',
44-
help='The path of model for export',
45-
type=str,
46-
default=None)
37+
'--output_op',
38+
choices=['argmax', 'softmax', 'none'],
39+
default="argmax",
40+
help="Select which op to be appended to output result, default: argmax")
4741
parser.add_argument(
4842
'--without_argmax',
49-
dest='without_argmax',
50-
help='Do not add the argmax operation at the end of the network',
43+
help='Do not add the argmax operation at the end of the network. [Deprecated]',
5144
action='store_true')
5245
parser.add_argument(
5346
'--with_softmax',
54-
dest='with_softmax',
55-
help='Add the softmax operation at the end of the network',
47+
help='Add the softmax operation at the end of the network. [Deprecated]',
5648
action='store_true')
5749
parser.add_argument(
5850
"--input_shape",
@@ -65,41 +57,33 @@ def parse_args():
6557

6658

6759
class SavedSegmentationNet(paddle.nn.Layer):
68-
def __init__(self, net, without_argmax=False, with_softmax=False):
60+
def __init__(self, net, output_op):
6961
super().__init__()
7062
self.net = net
71-
self.post_processer = PostPorcesser(without_argmax, with_softmax)
63+
self.output_op = output_op
64+
assert output_op in ['argmax', 'softmax'], \
65+
"output_op should in ['argmax', 'softmax']"
7266

7367
def forward(self, x):
7468
outs = self.net(x)
75-
outs = self.post_processer(outs)
76-
return outs
77-
78-
79-
class PostPorcesser(paddle.nn.Layer):
80-
def __init__(self, without_argmax, with_softmax):
81-
super().__init__()
82-
self.without_argmax = without_argmax
83-
self.with_softmax = with_softmax
8469

85-
def forward(self, outs):
8670
new_outs = []
8771
for out in outs:
88-
if self.with_softmax:
72+
if self.output_op == 'argmax':
73+
out = paddle.argmax(out, axis=1, dtype='int32')
74+
elif self.output_op == 'softmax':
8975
out = paddle.nn.functional.softmax(out, axis=1)
90-
if not self.without_argmax:
91-
out = paddle.argmax(out, axis=1)
9276
new_outs.append(out)
9377
return new_outs
9478

9579

9680
def main(args):
9781
os.environ['PADDLESEG_EXPORT_STAGE'] = 'True'
98-
cfg = Config(args.cfg)
82+
cfg = Config(args.config)
9983
cfg.check_sync_info()
10084
net = cfg.model
10185

102-
if args.model_path:
86+
if args.model_path is not None:
10387
para_state_dict = paddle.load(args.model_path)
10488
net.set_dict(para_state_dict)
10589
logger.info('Loaded trained params of model successfully.')
@@ -109,17 +93,24 @@ def main(args):
10993
else:
11094
shape = args.input_shape
11195

112-
if not args.without_argmax or args.with_softmax:
113-
new_net = SavedSegmentationNet(net, args.without_argmax,
114-
args.with_softmax)
115-
else:
116-
new_net = net
117-
96+
output_op = args.output_op
97+
if args.without_argmax:
98+
logger.warning(
99+
'--without_argmax will be deprecated, please use --output_op')
100+
output_op = 'none'
101+
if args.with_softmax:
102+
logger.warning(
103+
'--with_softmax will be deprecated, please use --output_op')
104+
output_op = 'softmax'
105+
106+
new_net = net if output_op == 'none' else SavedSegmentationNet(net,
107+
output_op)
118108
new_net.eval()
119109
new_net = paddle.jit.to_static(
120110
new_net,
121111
input_spec=[paddle.static.InputSpec(
122112
shape=shape, dtype='float32')])
113+
123114
save_path = os.path.join(args.save_dir, 'model')
124115
paddle.jit.save(new_net, save_path)
125116

@@ -128,19 +119,20 @@ def main(args):
128119
transforms = cfg.export_config.get('transforms', [{
129120
'type': 'Normalize'
130121
}])
122+
output_dtype = 'int32' if output_op == 'argmax' else 'float32'
131123
data = {
132124
'Deploy': {
133-
'transforms': transforms,
134125
'model': 'model.pdmodel',
135126
'params': 'model.pdiparams',
136-
'with_softmax': args.with_softmax,
137-
'with_argmax': not args.without_argmax,
138-
'input_shape': shape
127+
'transforms': transforms,
128+
'input_shape': shape,
129+
'output_op': output_op,
130+
'output_dtype': output_dtype
139131
}
140132
}
141133
yaml.dump(data, file)
142134

143-
logger.info(f'Model is saved in {args.save_dir}.')
135+
logger.info(f'The inference model is saved in {args.save_dir}')
144136

145137

146138
if __name__ == '__main__':

0 commit comments

Comments
 (0)