未验证 提交 89e8fa20 编写于 作者: littletomatodonkey's avatar littletomatodonkey 提交者: GitHub

add inference doc (#5404)

* add inference doc

* fix reprod log

* fix test inference

* add predict into reprod

* fix readme

* add py serving doc

* fix tipc test

* fix

* fix
上级 fe27ab9d
此差异已折叠。
docs/lwfx/images/framework_reprodcv.png

627.0 KB | W: | H:

docs/lwfx/images/framework_reprodcv.png

702.6 KB | W: | H:

docs/lwfx/images/framework_reprodcv.png
docs/lwfx/images/framework_reprodcv.png
docs/lwfx/images/framework_reprodcv.png
docs/lwfx/images/framework_reprodcv.png
  • 2-up
  • Swipe
  • Onion skin
# 飞桨训推一体全流程(TIPC)模型开发文档 # Linux GPU/CPU 基础训练推理开发规范
## 1. TIPC简介 # 目录
飞桨除了基本的模型训练和预测,还提供了支持多端多平台的高性能推理部署工具。飞桨训推一体全流程(Training and Inference Pipeline Criterion(TIPC))旨在建立模型从学术研究到产业落地的桥梁,方便模型更广泛的使用。 - [1. 简介](#1)
- [2. 模型复现流程与规范](#2)
- [2.1 复现流程](#2.1)
- [2.2 核验点](#2.2)
- [3. 模型推理开发规范](#3)
- [3.1 开发流程](#3.1)
- [3.2 核验点](#3.2)
- [4. 基础训练推理测试开发规范](4)
- [4.1 开发流程](#4.1)
- [4.2 核验点](#4.2)
<div align="center"> <a name="1"></a>
<img src="images/tipc_guide.png" width="800">
</div> ## 1. 简介
该系列文档主要介绍飞桨模型基于 Linux GPU/CPU 基础训练推理开发过程,主要包含三个步骤。
1. 参考 [《模型复现指南》](../../lwfx/ArticleReproduction_CV.md),完成模型的训练与基于训练引擎的预测过程。
2. 参考[《Linux GPU/CPU 模型推理开发文档》](./py_inference.md),在基于训练引擎预测的基础上,完成基于Paddle Inference的推理过程开发。
3. 参考[《Linux GPU/CPU 基础训练推理测试开发文档》](./test_linux_train_infer_python.md),完成Linux GPU/CPU 训练、推理测试功能开发。
<a name="2"></a>
## 2. 论文复现流程与规范 ## 2. 模型复现流程与规范
<a name="2.1"></a>
### 2.1 复现流程 ### 2.1 复现流程
如果您对于论文复现过程已经非常熟悉,在复现过程中可以按照自己的复现方法进行复现。但是需要注意训练日志与文档内容符合规范。可以参考`2.2章节` 如果您对于模型复现过程已经非常熟悉,在复现过程中可以按照自己的复现方法进行复现。但是需要注意训练日志与文档内容符合规范。可以参考`2.2章节`
如果您在论文复现方面经验较少或者复现过程中遇到问题,希望定位问题,强烈建议您按照论文复现指南进行操作。以CV任务为例,复现指南将论文复现分为12个步骤,如下所示。 如果您在模型复现方面经验较少,或者复现过程中遇到问题,希望快速排查问题,强烈建议您按照模型复现指南进行操作。以CV任务为例,复现指南将模型复现分为13个步骤,如下所示。
<div align="center"> <div align="center">
<img src="../../lwfx/images/framework_reprodcv.png" width="800"> <img src="../../lwfx/images/framework_reprodcv.png" width="800">
</div> </div>
更多内容请参考:[CV方向论文复现指南](../lwfx/ArticleReproduction_CV.md) 更多内容请参考:[模型复现指南](../lwfx/ArticleReproduction_CV.md)
### 2.2 规范验收点 <a name="2.2"></a>
#### 2.2.1 小数据集 ### 2.2 核验点
repo中包含`lite_data`小数据集压缩包,解压之后可以获取`lite_data`小数据集文件夹。 在模型复现过程中,至少需要产出下面的内容。
#### 2.2.1 小数据集
需要准备好小数据集。方便快速验证 * repo中包含`lite_data`小数据集压缩包,解压之后可以获取`lite_data`小数据集文件夹。该数据集可以便于快速验证训练过程的能否跑通,其中包含的数据也可以用于验证推理部署过程
#### 2.2.2 代码与精度 #### 2.2.2 代码与精度
...@@ -38,47 +61,87 @@ repo中包含`lite_data`小数据集压缩包,解压之后可以获取`lite_da ...@@ -38,47 +61,87 @@ repo中包含`lite_data`小数据集压缩包,解压之后可以获取`lite_da
#### 2.2.3 训练日志 #### 2.2.3 训练日志
* 输出目录中包含`train.log`文件,每个迭代过程中,至少包含`epoch`, `iter`, `loss`, `avg_reader_cost`, `avg_batch_cost`, `avg_ips`关键字段。含义如下所示。 * 日志文件中,每个迭代过程的输出信息至少包含`loss`, `avg_reader_cost`, `avg_batch_cost`, `avg_ips`关键字段。含义如下所示。
* `epoch`: 当前训练所处的epoch数
* `iter`: 该epoch中,当前训练的具体迭代轮数
* `loss`: 过去若干个iter的loss值 * `loss`: 过去若干个iter的loss值
* `avg_reader_cost`: 过去若干个iter的平均reader耗时 (单位: sec) * `avg_reader_cost`: 过去若干个iter的平均reader耗时 (单位: sec)
* `avg_batch_cost`: 过去若干个iter的平均训练耗时 (单位: sec) * `avg_batch_cost`: 过去若干个iter的平均训练耗时 (单位: sec)
* `avg_ips`: 过段若干个iter个训练速度(单位: images/sec) * `avg_ips`: 过段若干个iter个训练速度(单位: images/sec)
#### 2.2.3 文档 #### 2.2.4 文档
* 说明文档中需要有数据准备以及模型训练、评估、预测的命令。 * 说明文档中需要有数据准备以及模型训练、评估、预测的命令。
* 介绍预测命令(predict.py)时,需要提供示例图片,并根据示例图片,可视化出使用提供的预测命令运行得到的结果。 * 介绍预测命令(`predict.py`)时,需要提供示例图片,并根据示例图片,可视化出使用提供的预测命令运行得到的结果。
<a name="3"></a>
## 3. 模型推理开发规范 ## 3. 模型推理开发规范
<a name="3.1"></a>
### 3.1 开发流程 ### 3.1 开发流程
基于Paddle Inference的预测过程分为下面4个步骤。 基于Paddle Inference的预测过程分为下面9个步骤。
<div align="center"> <div align="center">
<img src="./images/inference_pipeline.png" width="500"> <img src="./images/py_inference_pipeline.png" width="800">
</div> </div>
更多的介绍可以参考:[模型推理开发规范](./inference.md) 更多的介绍可以参考:[模型推理开发规范](./inference.md)
### 3.2 规范验收点 <a name="3.2"></a>
#### 3.1.1 代码与预测结果 ### 3.2 核验点
* 项目中需要包含`模型动转静`脚本(`export_model.py`)以及`模型基于预测引擎的`预测脚本(`infer.py`)。 #### 3.2.1 代码与预测结果
#### 3.1.2 文档 * 项目中需要包含`模型动转静`脚本(`export_model.py`)以及`模型基于 Paddle Inference 的`预测脚本(`infer.py`)。
* 说明文档中,需要包含`模型动转静``模型基于预测引擎`的说明。 #### 3.2.2 文档
## 4. TIPC测试开发规范 * 说明文档中,需要包含`模型动转静``模型基于预测引擎`的使用命令说明。
<a name="4"></a>
## 4. 基础训练推理测试开发规范
<a name="4.1"></a>
### 4.1 开发流程 ### 4.1 开发流程
TIPC测试开发流程与规范可以参考:[Linux GPU/CPU 基础训练推理测试开发规范](./train_infer_python.md) 基础训练推理测试开发的流程如下所示。
<div align="center">
<img src="./images/test_linux_train_infer_python_pipeline.png" width="400">
</div>
更多的介绍可以参考:[Linux GPU/CPU 基础训练推理测试开发规范](./test_linux_train_infer_python.md)
<a name="4.2"></a>
### 4.2 核验点
#### 4.2.1 目录结构
在repo根目录下面新建`test_tipc`文件夹,目录结构如下所示。
```
test_tipc
|--configs # 配置目录
| |--model_name # 您的模型名称
| |--train_infer_python.txt # 基础训练推理测试配置文件
|--docs # 文档目录
| |--test_train_inference_python.md # 基础训练推理测试说明文档
|----README.md # TIPC说明文档
|----test_train_inference_python.sh # TIPC基础训练推理测试解析脚本,无需改动
|----common_func.sh # TIPC基础训练推理测试常用函数,无需改动
```
### 4.2 规范验收点 #### 4.2.2 配置文件和说明文档
验收点包含`目录结构、配置文件、说明文档`,具体内容可以参考[Linux GPU/CPU 基础训练推理测试开发规范](./train_infer_python.md)`3.3章节` * `test_tipc/README.md` 文档中对该模型支持的的功能进行总体介绍。
* `test_tipc/docs/test_train_inference_python.md` 文档中对**Linux GPU/CPU 基础训练推理**的功能进行详细介绍。
* 根据文档内容,基于配置文件,跑通自动化训练、推理的测试过程。
# Linux GPU/CPU 模型推理开发文档
# 目录
- [1. 简介](#1)
- [2. 推理过程开发](#2)
- [2.1 准备推理数据与环境](#.21)
- [2.2 准备推理模型](#2.2)
- [2.3 准备推理所需代码](#2.3)
- [2.4 初始化推理引擎](#2.4)
- [2.5 开发数据预处理程序](#2.5)
- [2.6 开发推理程序](#2.6)
- [2.7 开发推理结果后处理程序](#2.7)
- [2.8 验证推理结果正确性](#2.8)
- [2.9 添加推理日志](#2.9)
- [3. FAQ](#3)
<a name="1"></a>
## 1. 简介
Paddle Inference 是飞桨的原生推理库, 作用于服务器端和云端,提供高性能的推理能力。相比于直接基于预训练模型进行预测,Paddle Inference可使用MKLDNN、CUDNN、TensorRT进行预测加速,从而实现更优的推理性能。
更多关于Paddle Inference推理引擎的介绍,可以参考[Paddle Inference官网教程](https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/05_inference_deployment/inference/inference_cn.html)
本文档主要介绍飞桨模型在 Linux GPU/CPU 下基于预测引擎的推理过程开发。主要包含三个步骤:
(1)参考 [《模型复现指南》](./ArticleReproduction_CV.md),完成模型的训练与基于训练引擎的预测。
(2)在基于训练引擎预测的基础上,完成基于预测引擎的推理过程开发。
(3)完成Linux GPU/CPU 训练、推理测试开发([《Linux GPU/CPU 基础训练推理测试开发规范》](./test_linux_train_infer_python.md))。
<a name="2"></a>
## 2. 推理过程开发
基于Paddle Inference的推理过程可以分为9个步骤,如下图所示。
<div align="center">
<img src="./images/py_inference_pipeline.png" width="600">
</div>
其中设置了3个核验点,分别为
* 准备推理模型
* 验证推理结果正确性
* 添加推理日志
<a name="2.1"></a>
### 2.1 准备推理数据与环境
**【数据】**
从验证集或者测试集中抽出至少一张图像,用于后续推理过程验证。
**【环境】**
* 安装好PaddlePaddle的whl包之后,便可以直接体验Paddle的Inference推理功能。
* 如果希望体验基于Paddle Inference的TensorRT推理,可以参考:[Paddle Inference TensorRT推理教程](https://paddle-inference.readthedocs.io/en/latest/optimize/paddle_trt.html)
<a name="2.2"></a>
### 2.2 准备推理模型
`模型动转静`方法可以将训练得到的动态图模型转化为用于推理的静态图模型,下面详细介绍`模型动转静`流程。
该小节的代码模板位于[export_model.py](./template/code/export_model.py),您可以基于这段代码进行修改。
具体地,关于AlexNet的导出代码可以参考:[export_model.py](https://github.com/littletomatodonkey/AlexNet-Prod/blob/tipc/pipeline/Step5/AlexNet_paddle/tools/export_model.py)
#### 2.2.1 定义模型
**【基本流程】**
在模型导出之前,首先需要定义好模型结构,模型结构与训练时的模型结构相同。
**【注意事项】**
* 模型组网建议直接参考预测代码中的组网部分。
* 图像分类任务中,训练组网时,在输出层一般没有加上`softmax`激活函数,在预测推理时,为了得到模型预测推理结果的概率值,可以在网络后面添加`softmax`激活函数。
**【实战】**
AlexNet中模型定义与组网如下所示,参考链接:[export_model.py](https://github.com/littletomatodonkey/AlexNet-Prod/blob/tipc/pipeline/Step5/AlexNet_paddle/tools/export_model.py)
```python
model = paddlevision.models.__dict__[args.model](
pretrained=args.pretrained, num_classes=args.num_classes)
model = nn.Sequential(model, nn.Softmax())
model.eval()
```
#### 2.2.2 模型动转静(`jit.to_static`)
**【基本流程】**
`paddle.jit.to_static`接口是完全模型动转静的唯一接口,需要使用该接口对模型进行装饰。
**【注意事项】**
* 如果有多个输入,则在`input_spec`接口中定义多个`InputSpec`对象即可。
* `batch_size`维度建议使用`None`
* 如果希望使用TensorRT进行预测,需要保证导出时设置的尺度与最终实际预测时的尺度保持一致。
**【实战】**
AlexNet中模型动转静代码如下所示,参考链接:[export_model.py](https://github.com/littletomatodonkey/AlexNet-Prod/blob/tipc/pipeline/Step5/AlexNet_paddle/tools/export_model.py)
```python
model = paddle.jit.to_static(
model,
input_spec=[
InputSpec(
shape=[None, 3, args.img_size, args.img_size], dtype='float32')
])
```
#### 2.2.3 保存模型(`jit.save`)
**【基本流程】**
对于装饰后的模型,可以使用`paddle.jit.save` API完成模型保存。
**【注意事项】**
* 保存过程中遇到的问题可以参考[动转静报错调试教程](https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/04_dygraph_to_static/debugging_cn.html)
**【实战】**
AlexNet中模型保存代码如下所示,参考链接:[export_model.py](https://github.com/littletomatodonkey/AlexNet-Prod/blob/tipc/pipeline/Step5/AlexNet_paddle/tools/export_model.py)
```python
paddle.jit.save(model, os.path.join(args.save_inference_dir, "inference"))
```
**【验收】**
保存路径下面会生成3个文件,如下所示,其中在Inference推理中用到的为`inference.pdiparams``inference.pdmodel`
```
inference.pdiparams : 模型参数文件
inference.pdmodel : 模型结构文件
inference.pdiparams.info: 模型参数信息文件
```
<a name="2.3"></a>
### 2.3 准备推理所需代码
**【基本流程】**
基于预测引擎的推理过程包含4个步骤:初始化预测引擎、预处理、推理、后处理。文件`template/code/infer.py`中提供了一个模板类,您可以将这个文件拷贝到自己的项目中,修改对应的部分。
```py
class InferenceEngine(object):
def __init__(self, args):
super().__init__()
pass
def load_predictor(self, model_file_path, params_file_path):
pass
def preprocess(self, img_path):
pass
def postprocess(self, x):
pass
def run(self, x):
pass
```
**【实战】**
该模板类对应AlexNet的实现位于:[infer.py](https://github.com/littletomatodonkey/AlexNet-Prod/blob/tipc/pipeline/Step5/AlexNet_paddle/deploy/py_inference/infer.py)
其中每个子模块的操作在下面详细介绍。
<a name="2.4"></a>
### 2.4 初始化推理引擎
**【基本流程】**
传入配置,如模型参数和结构文件路径、GPU、MKLDNN等配置,初始化推理引擎。
**【注意事项】**
* 如果在使用MKLDNN或者TensorRT进行推理的过程中出现报错,可以给在[这里](https://github.com/PaddlePaddle/Paddle/issues/new/choose)提一个ISSUE,我们会高优跟进。
**【实战】**
针对AlexNet模型,推理引擎初始化函数实现如下,其中模型结构和参数文件路径、是否使用GPU、是否开启MKLDNN等内容都是可以配置的。
```py
# https://github.com/littletomatodonkey/AlexNet-Prod/blob/tipc/pipeline/Step5/AlexNet_paddle/deploy/py_inference/infer.py#L38
def load_predictor(self, model_file_path, params_file_path):
args = self.args
config = inference.Config(model_file_path, params_file_path)
if args.use_gpu:
config.enable_use_gpu(1000, 0)
else:
config.disable_gpu()
if args.use_mkldnn:
config.enable_mkldnn()
config.set_cpu_math_library_num_threads(args.cpu_threads)
# enable memory optim
config.enable_memory_optim()
config.disable_glog_info()
config.switch_use_feed_fetch_ops(False)
config.switch_ir_optim(True)
# create predictor
predictor = inference.create_predictor(config)
# get input and output tensor property
input_names = predictor.get_input_names()
input_tensor = predictor.get_input_handle(input_names[0])
output_names = predictor.get_output_names()
output_tensor = predictor.get_output_handle(output_names[0])
return predictor, config, input_tensor, output_tensor
```
<a name="2.5"></a>
### 2.5 开发数据预处理程序
**【基本流程】**
读取指定图像,对其进行数据变换,转化为符合模型推理所需要的输入格式。
**【注意事项】**
* 在模型评估过程中,为了保证数据可以组batch,我们一般会使用resize/crop/padding等方法去保持尺度的一致性,在预测推理过程中,需要注意crop是否合适,比如OCR识别任务中,crop的操作会导致识别结果不全。
**【实战】**
图像分类AlexNet为例,预处理包含`Resize`, `CenterCrop`, `Normalize`, `ToCHW` 4个步骤,预处理实现如下所示。
```py
# https://github.com/littletomatodonkey/AlexNet-Prod/blob/tipc/pipeline/Step5/AlexNet_paddle/deploy/py_inference/infer.py#L68
def preprocess(self, img_path):
with open(img_path, "rb") as f:
img = Image.open(f)
img = img.convert("RGB")
img = self.transforms(img)
img = np.expand_dims(img, axis=0)
return img
```
<a name="2.6"></a>
### 2.6 开发推理程序
**【基本流程】**
将数据从CPU拷贝到推理引擎中,运行,并拷贝回CPU。
**【实战】**
AlexNet的推理引擎运行代码如下所示。
```py
def run(self, x):
# inference using inference engine
self.input_tensor.copy_from_cpu(x)
self.predictor.run()
output = self.output_tensor.copy_to_cpu()
return output
```
<a name="2.7"></a>
### 2.7 开发推理结果后处理程序
**【基本流程】**
对于模型的推理输出,对其进行后处理,得到最终有实际含义的输出。
**【实战】**
AlexNet的后处理代码如下所示。
```py
def postprocess(self, x):
x = x.flatten()
class_id = x.argmax()
prob = x[class_id]
return class_id, prob
```
<a name="2.8"></a>
### 2.8 验证推理结果正确性
**【基本流程】**
与基于训练引擎的预测结果进行对比,确保结果二者结果一致。
**【实战】**
以AlexNet为例,将二者的结果(clas_id, score)分别使用`reprod_log`工具进行保存,再进行对比。
Inference推理结果保存逻辑如下。
```py
args = get_args()
class_id, prob = infer_main(args)
reprod_logger = ReprodLogger()
reprod_logger.add("class_id", np.array([class_id]))
reprod_logger.add("prob", np.array([prob]))
reprod_logger.save("output_inference_engine.npy")
```
**【核验】**
* 基于训练引擎和预测引擎的推理结果相同。参考链接:[check_inference.py](https://github.com/littletomatodonkey/AlexNet-Prod/blob/tipc/pipeline/Step5/check_inference.py)
<a name="2.9"></a>
### 2.9 添加推理日志
**【背景】**
推理过程一般包含预处理、预测引擎运行、后处理三个步骤,对这三个步骤的预测耗时进行记录,可以帮助我们更好地分析模型推理的耗时瓶颈,有助于后续的模型性能优化。
**【基本流程】**
在训练代码中添加日志统计信息,对推理中的信息进行统计。推荐使用`AutoLog`工具。
基于`AutoLog`工具规范化推理日志的过程包括:初始化、在每个节点的、输出日志。
**【注意事项】**
* 使用下面的方法安装`AutoLog`工具,更多使用方法可以参考[AutoLog](https://github.com/LDOUBLEV/AutoLog)
**【实战】**
AlexNet推理脚本中,打开`benchmark`选项,即可输出规范化的推理日志,可以参考:[infer.py](https://github.com/littletomatodonkey/AlexNet-Prod/blob/tipc/pipeline/Step5/AlexNet_paddle/deploy/pdinference/infer.py)
```py
# init benchmark
if args.benchmark:
import auto_log
autolog = auto_log.AutoLogger(
model_name="classification",
batch_size=args.batch_size,
inference_config=inference_engine.config,
gpu_ids="auto" if args.use_gpu else None)
# enable benchmark
if args.benchmark:
autolog.times.start()
# preprocess
img = inference_engine.preprocess(args.img_path)
if args.benchmark:
autolog.times.stamp()
# run
output = inference_engine.run(img)
if args.benchmark:
autolog.times.stamp()
# postprocess
class_id, prob = inference_engine.postprocess(output)
if args.benchmark:
autolog.times.stamp()
autolog.times.end(stamp=True)
autolog.report()
```
<a name="3"></a>
## 3. FAQ
import paddle
import paddle.nn as nn
import paddle.nn.functional as F
from paddle.static import InputSpec
import os
import sys
import numpy as np
def get_args(add_help=True):
import argparse
parser = argparse.ArgumentParser(
description='PaddlePaddle Args', add_help=add_help)
args = parser.parse_args()
return args
def build_model(args):
pass
def export(args):
# build your own model
model = build_model(args)
# decorate model with jit.save
model = paddle.jit.to_static(
model,
input_spec=[
InputSpec(
shape=[None, 3, args.img_size, args.img_size], dtype='float32')
])
# save inference model
paddle.jit.save(model, os.path.join(args.save_inference_dir, "inference"))
if __name__ == "__main__":
args = get_args()
export(args)
import os
import paddle
from paddle import inference
import numpy as np
from PIL import Image
from reprod_log import ReprodLogger
from preprocess_ops import ResizeImage, CenterCropImage, NormalizeImage, ToCHW, Compose
class InferenceEngine(object):
def __init__(self, args):
super().__init__()
pass
def load_predictor(self, model_file_path, params_file_path):
pass
def preprocess(self, img_path):
pass
def postprocess(self, x):
pass
def run(self, x):
pass
def get_args(add_help=True):
import argparse
def str2bool(v):
return v.lower() in ("true", "t", "1")
parser = argparse.ArgumentParser(
description="PaddlePaddle", add_help=add_help)
args = parser.parse_args()
return args
def infer_main(args):
# init inference engine
inference_engine = InferenceEngine(args)
# init benchmark
if args.benchmark:
import auto_log
autolog = auto_log.AutoLogger(
model_name="example",
batch_size=args.batch_size,
inference_config=inference_engine.config,
gpu_ids="auto" if args.use_gpu else None)
# enable benchmark
if args.benchmark:
autolog.times.start()
# preprocess
img = inference_engine.preprocess(args.img_path)
if args.benchmark:
autolog.times.stamp()
output = inference_engine.run(img)
if args.benchmark:
autolog.times.stamp()
# postprocess
class_id, prob = inference_engine.postprocess(output)
if args.benchmark:
autolog.times.stamp()
autolog.times.end(stamp=True)
autolog.report()
return class_id, prob
if __name__ == "__main__":
args = get_args()
infer_main(args)
\ No newline at end of file
#!/bin/bash
function func_parser_key(){
strs=$1
IFS=":"
array=(${strs})
tmp=${array[0]}
echo ${tmp}
}
function func_parser_value(){
strs=$1
IFS=":"
array=(${strs})
tmp=${array[1]}
echo ${tmp}
}
function func_set_params(){
key=$1
value=$2
if [ ${key}x = "null"x ];then
echo " "
elif [[ ${value} = "null" ]] || [[ ${value} = " " ]] || [ ${#value} -le 0 ];then
echo " "
else
echo "${key}=${value}"
fi
}
function func_parser_params(){
strs=$1
IFS=":"
array=(${strs})
key=${array[0]}
tmp=${array[1]}
IFS="|"
res=""
for _params in ${tmp[*]}; do
IFS="="
array=(${_params})
mode=${array[0]}
value=${array[1]}
if [[ ${mode} = ${MODE} ]]; then
IFS="|"
#echo $(func_set_params "${mode}" "${value}")
echo $value
break
fi
IFS="|"
done
echo ${res}
}
function status_check(){
last_status=$1 # the exit code
run_command=$2
run_log=$3
if [ $last_status -eq 0 ]; then
echo -e "\033[33m Run successfully with command - ${run_command}! \033[0m" | tee -a ${run_log}
else
echo -e "\033[33m Run failed with command - ${run_command}! \033[0m" | tee -a ${run_log}
fi
}
# 飞桨训推一体全流程(TIPC)
## 1. 简介
飞桨除了基本的模型训练和预测,还提供了支持多端多平台的高性能推理部署工具。本文档提供了`您的模型`中所有模型的飞桨训推一体全流程(Training and Inference Pipeline Criterion(TIPC))信息和测试工具,方便用户查阅每种模型的训练推理部署打通情况,并可以进行一键测试。
<div align="center">
<img src="docs/tipc_guide.png" width="1000">
</div>
## 2. 汇总信息
打通情况汇总如下,已填写的部分表示可以使用本工具进行一键测试,未填写的表示正在支持中。
**字段说明:**
- 基础训练预测:包括模型训练、Paddle Inference Python预测。
- 更多训练方式:包括多机多卡、混合精度。
- 模型压缩:包括裁剪、离线/在线量化、蒸馏。
- 其他预测部署:包括Paddle Inference C++预测、Paddle Serving部署、Paddle-Lite部署等。
更详细的MKLDNN、Tensorrt等预测加速相关功能的支持情况可以查看各测试工具的[更多教程](#more)
| 算法论文 | 模型名称 | 模型类型 | 基础<br>训练预测 | 更多<br>训练方式 | 模型压缩 | 其他预测部署 |
| :--- | :--- | :----: | :--------: | :---- | :---- | :---- |
| - | - | - | 支持 | - | - | - |
## 3. 测试工具简介
### 3.1 目录介绍
```
test_tipc
|--configs # 配置目录
| |--model_name # 您的模型名称
| |--train_infer_python.txt # 基础训练推理测试配置文件
|--docs # 文档目录
| |--test_train_inference_python.md # 基础训练推理测试说明文档
|----README.md # TIPC说明文档
|----test_train_inference_python.sh # TIPC基础训练推理测试解析脚本,无需改动
|----common_func.sh # TIPC基础训练推理测试常用函数,无需改动
```
### 3.2 测试流程概述
使用本工具,可以测试不同功能的支持情况,以及预测结果是否对齐。测试过程包含
1. 准备数据与环境
2. 运行测试脚本,观察不同配置是否运行成功。
具体内容可以参考第4章中的测试文档链接。
<a name="more"></a>
## 4. 更多测试功能
更多测试功能可以参考
* [Linux GPU/CPU 基础训练推理测试文档](docs/test_train_inference_python.md)
* [PaddleServing 测试文档](docs/test_serving.md)
# Linux端基础训练推理功能测试
Linux端基础训练推理功能测试的主程序为`test_train_inference_python.sh`,可以测试基于Python的模型训练、评估、推理等基本功能,包括裁剪、量化、蒸馏。
## 1. 测试结论汇总
- 训练相关:
| 算法名称 | 模型名称 | 单机单卡 | 单机多卡 | 多机多卡 | 模型压缩(单机多卡) |
| :----: | :----: | :----: | :----: | :----: | :----: |
| - | - | 正常训练 | 正常训练 | - | - |
- 推理相关:基于训练是否使用量化,可以将训练产出的模型可以分为`正常模型``量化模型`,这两类模型对应的推理功能汇总如下,
| 算法名称 | 模型名称 | 模型类型 | device | batchsize | tensorrt | mkldnn | cpu多线程 |
| :----: | :----: | ---- | :----: | :----: | :----: | :----: | :----: |
| - | - | 正常模型 | GPU | 1 | - | - | - |
| - | - | 正常模型 | CPU | 1 | - | fp32 | 支持 |
## 2. 测试流程
### 2.1 准备数据
用于基础训练推理测试的数据位于`test_images/lite_data.tar`,直接解压即可(如果已经解压完成,则无需运行下面的命令)。
```bash
tar -xf test_images/lite_data.tar
```
### 2.2 准备环境
- 安装PaddlePaddle >= 2.1
- 安装AlexNet依赖
```
pip3 install -r ../requirements.txt
```
- 安装AutoLog(规范化日志输出工具)
```
git clone https://github.com/LDOUBLEV/AutoLog
cd AutoLog
pip install -r requirements.txt
python setup.py bdist_wheel
pip3 install ./dist/auto_log-1.0.0-py3-none-any.whl
cd ../
```
### 2.3 功能测试
测试方法如下所示,希望测试不同的模型文件,只需更换为自己的参数配置文件,即可完成对应模型的测试。
```bash
bash test_tipc/test_train_inference_python.sh ${your_params_file} lite_train_lite_infer
```
`${您的模型名称}``Linux GPU/CPU 基础训练推理测试`为例,命令如下所示。
```bash
bash test_tipc/test_train_inference_python.sh test_tipc/configs/AlexNet/train_infer_python.txt lite_train_lite_infer
```
输出结果如下,表示命令运行成功。
```
Run successfully with command - xxx
```
## 3. 更多教程
本文档为功能测试用,更丰富的训练预测使用教程请参考:
* [模型训练、预测、推理教程](../../README.md)
#!/bin/bash
source test_tipc/common_func.sh
FILENAME=$1
# MODE be one of ['lite_train_lite_infer' 'lite_train_whole_infer' 'whole_train_whole_infer', 'whole_infer', 'klquant_whole_infer']
MODE=$2
dataline=$(awk 'NR==1, NR==51{print}' $FILENAME)
# parser params
IFS=$'\n'
lines=(${dataline})
# The training params
model_name=$(func_parser_value "${lines[1]}")
python=$(func_parser_value "${lines[2]}")
gpu_list=$(func_parser_value "${lines[3]}")
train_use_gpu_key=$(func_parser_key "${lines[4]}")
train_use_gpu_value=$(func_parser_value "${lines[4]}")
autocast_list=$(func_parser_value "${lines[5]}")
autocast_key=$(func_parser_key "${lines[5]}")
epoch_key=$(func_parser_key "${lines[6]}")
epoch_num=$(func_parser_params "${lines[6]}" "${MODE}")
save_model_key=$(func_parser_key "${lines[7]}")
train_batch_key=$(func_parser_key "${lines[8]}")
train_batch_value=$(func_parser_params "${lines[8]}" "${MODE}")
pretrain_model_key=$(func_parser_key "${lines[9]}")
pretrain_model_value=$(func_parser_value "${lines[9]}")
train_model_name=$(func_parser_value "${lines[10]}")
train_infer_img_dir=$(func_parser_value "${lines[11]}")
train_param_key1=$(func_parser_key "${lines[12]}")
train_param_value1=$(func_parser_value "${lines[12]}")
trainer_list=$(func_parser_value "${lines[14]}")
trainer_norm=$(func_parser_key "${lines[15]}")
norm_trainer=$(func_parser_value "${lines[15]}")
pact_key=$(func_parser_key "${lines[16]}")
pact_trainer=$(func_parser_value "${lines[16]}")
fpgm_key=$(func_parser_key "${lines[17]}")
fpgm_trainer=$(func_parser_value "${lines[17]}")
distill_key=$(func_parser_key "${lines[18]}")
distill_trainer=$(func_parser_value "${lines[18]}")
trainer_key1=$(func_parser_key "${lines[19]}")
trainer_value1=$(func_parser_value "${lines[19]}")
trainer_key2=$(func_parser_key "${lines[20]}")
trainer_value2=$(func_parser_value "${lines[20]}")
eval_py=$(func_parser_value "${lines[23]}")
eval_key1=$(func_parser_key "${lines[24]}")
eval_value1=$(func_parser_value "${lines[24]}")
save_infer_key=$(func_parser_key "${lines[27]}")
export_weight=$(func_parser_key "${lines[28]}")
norm_export=$(func_parser_value "${lines[29]}")
pact_export=$(func_parser_value "${lines[30]}")
fpgm_export=$(func_parser_value "${lines[31]}")
distill_export=$(func_parser_value "${lines[32]}")
export_key1=$(func_parser_key "${lines[33]}")
export_value1=$(func_parser_value "${lines[33]}")
export_key2=$(func_parser_key "${lines[34]}")
export_value2=$(func_parser_value "${lines[34]}")
inference_dir=$(func_parser_value "${lines[35]}")
# parser inference model
infer_model_dir_list=$(func_parser_value "${lines[36]}")
infer_export_list=$(func_parser_value "${lines[37]}")
infer_is_quant=$(func_parser_value "${lines[38]}")
# parser inference
inference_py=$(func_parser_value "${lines[39]}")
use_gpu_key=$(func_parser_key "${lines[40]}")
use_gpu_list=$(func_parser_value "${lines[40]}")
use_mkldnn_key=$(func_parser_key "${lines[41]}")
use_mkldnn_list=$(func_parser_value "${lines[41]}")
cpu_threads_key=$(func_parser_key "${lines[42]}")
cpu_threads_list=$(func_parser_value "${lines[42]}")
batch_size_key=$(func_parser_key "${lines[43]}")
batch_size_list=$(func_parser_value "${lines[43]}")
use_trt_key=$(func_parser_key "${lines[44]}")
use_trt_list=$(func_parser_value "${lines[44]}")
precision_key=$(func_parser_key "${lines[45]}")
precision_list=$(func_parser_value "${lines[45]}")
infer_model_key=$(func_parser_key "${lines[46]}")
image_dir_key=$(func_parser_key "${lines[47]}")
infer_img_dir=$(func_parser_value "${lines[47]}")
save_log_key=$(func_parser_key "${lines[48]}")
benchmark_key=$(func_parser_key "${lines[49]}")
benchmark_value=$(func_parser_value "${lines[49]}")
infer_key1=$(func_parser_key "${lines[50]}")
infer_value1=$(func_parser_value "${lines[50]}")
# parser klquant_infer
if [ ${MODE} = "klquant_whole_infer" ]; then
dataline=$(awk 'NR==1, NR==17{print}' $FILENAME)
lines=(${dataline})
model_name=$(func_parser_value "${lines[1]}")
python=$(func_parser_value "${lines[2]}")
export_weight=$(func_parser_key "${lines[3]}")
save_infer_key=$(func_parser_key "${lines[4]}")
# parser inference model
infer_model_dir_list=$(func_parser_value "${lines[5]}")
infer_export_list=$(func_parser_value "${lines[6]}")
infer_is_quant=$(func_parser_value "${lines[7]}")
# parser inference
inference_py=$(func_parser_value "${lines[8]}")
use_gpu_key=$(func_parser_key "${lines[9]}")
use_gpu_list=$(func_parser_value "${lines[9]}")
use_mkldnn_key=$(func_parser_key "${lines[10]}")
use_mkldnn_list=$(func_parser_value "${lines[10]}")
cpu_threads_key=$(func_parser_key "${lines[11]}")
cpu_threads_list=$(func_parser_value "${lines[11]}")
batch_size_key=$(func_parser_key "${lines[12]}")
batch_size_list=$(func_parser_value "${lines[12]}")
use_trt_key=$(func_parser_key "${lines[13]}")
use_trt_list=$(func_parser_value "${lines[13]}")
precision_key=$(func_parser_key "${lines[14]}")
precision_list=$(func_parser_value "${lines[14]}")
infer_model_key=$(func_parser_key "${lines[15]}")
image_dir_key=$(func_parser_key "${lines[16]}")
infer_img_dir=$(func_parser_value "${lines[16]}")
save_log_key=$(func_parser_key "${lines[17]}")
save_log_value=$(func_parser_value "${lines[17]}")
benchmark_key=$(func_parser_key "${lines[18]}")
benchmark_value=$(func_parser_value "${lines[18]}")
infer_key1=$(func_parser_key "${lines[19]}")
infer_value1=$(func_parser_value "${lines[19]}")
fi
LOG_PATH="./test_tipc/output"
mkdir -p ${LOG_PATH}
status_log="${LOG_PATH}/results_python.log"
function func_inference(){
IFS='|'
_python=$1
_script=$2
_model_dir=$3
_log_path=$4
_img_dir=$5
_flag_quant=$6
# inference
for use_gpu in ${use_gpu_list[*]}; do
if [ ${use_gpu} = "False" ] || [ ${use_gpu} = "cpu" ]; then
for use_mkldnn in ${use_mkldnn_list[*]}; do
if [ ${use_mkldnn} = "False" ] && [ ${_flag_quant} = "True" ]; then
continue
fi
for threads in ${cpu_threads_list[*]}; do
for batch_size in ${batch_size_list[*]}; do
for precision in ${precision_list[*]}; do
if [ ${use_mkldnn} = "False" ] && [ ${precision} = "fp16" ]; then
continue
fi # skip when enable fp16 but disable mkldnn
if [ ${_flag_quant} = "True" ] && [ ${precision} != "int8" ]; then
continue
fi # skip when quant model inference but precision is not int8
set_precision=$(func_set_params "${precision_key}" "${precision}")
_save_log_path="${_log_path}/python_infer_cpu_usemkldnn_${use_mkldnn}_threads_${threads}_precision_${precision}_batchsize_${batch_size}.log"
set_infer_data=$(func_set_params "${image_dir_key}" "${_img_dir}")
set_benchmark=$(func_set_params "${benchmark_key}" "${benchmark_value}")
set_batchsize=$(func_set_params "${batch_size_key}" "${batch_size}")
set_cpu_threads=$(func_set_params "${cpu_threads_key}" "${threads}")
set_model_dir=$(func_set_params "${infer_model_key}" "${_model_dir}")
set_infer_params0=$(func_set_params "${save_log_key}" "${save_log_value}")
set_infer_params1=$(func_set_params "${infer_key1}" "${infer_value1}")
command="${_python} ${_script} ${use_gpu_key}=${use_gpu} ${use_mkldnn_key}=${use_mkldnn} ${set_cpu_threads} ${set_model_dir} ${set_batchsize} ${set_infer_params0} ${set_infer_data} ${set_benchmark} ${set_precision} ${set_infer_params1} > ${_save_log_path} 2>&1 "
eval $command
last_status=${PIPESTATUS[0]}
eval "cat ${_save_log_path}"
status_check $last_status "${command}" "${status_log}"
done
done
done
done
elif [ ${use_gpu} = "True" ] || [ ${use_gpu} = "gpu" ]; then
for use_trt in ${use_trt_list[*]}; do
for precision in ${precision_list[*]}; do
if [[ ${_flag_quant} = "False" ]] && [[ ${precision} =~ "int8" ]]; then
continue
fi
if [[ ${precision} =~ "fp16" || ${precision} =~ "int8" ]] && [ ${use_trt} = "False" ]; then
continue
fi
if [[ ${use_trt} = "False" || ${precision} =~ "int8" ]] && [ ${_flag_quant} = "True" ]; then
continue
fi
for batch_size in ${batch_size_list[*]}; do
_save_log_path="${_log_path}/python_infer_gpu_usetrt_${use_trt}_precision_${precision}_batchsize_${batch_size}.log"
set_infer_data=$(func_set_params "${image_dir_key}" "${_img_dir}")
set_benchmark=$(func_set_params "${benchmark_key}" "${benchmark_value}")
set_batchsize=$(func_set_params "${batch_size_key}" "${batch_size}")
set_tensorrt=$(func_set_params "${use_trt_key}" "${use_trt}")
set_precision=$(func_set_params "${precision_key}" "${precision}")
set_model_dir=$(func_set_params "${infer_model_key}" "${_model_dir}")
set_infer_params0=$(func_set_params "${save_log_key}" "${save_log_value}")
set_infer_params1=$(func_set_params "${infer_key1}" "${infer_value1}")
command="${_python} ${_script} ${use_gpu_key}=${use_gpu} ${set_tensorrt} ${set_precision} ${set_model_dir} ${set_batchsize} ${set_infer_data} ${set_benchmark} ${set_infer_params1} ${set_infer_params0} > ${_save_log_path} 2>&1 "
eval $command
last_status=${PIPESTATUS[0]}
eval "cat ${_save_log_path}"
status_check $last_status "${command}" "${status_log}"
done
done
done
else
echo "Does not support hardware other than CPU and GPU Currently!"
fi
done
}
if [ ${MODE} = "whole_infer" ] || [ ${MODE} = "klquant_whole_infer" ]; then
GPUID=$3
if [ ${#GPUID} -le 0 ];then
env=" "
else
env="export CUDA_VISIBLE_DEVICES=${GPUID}"
fi
# set CUDA_VISIBLE_DEVICES
eval $env
export Count=0
IFS="|"
infer_run_exports=(${infer_export_list})
infer_quant_flag=(${infer_is_quant})
for infer_model in ${infer_model_dir_list[*]}; do
# run export
if [ ${infer_run_exports[Count]} != "null" ];then
save_infer_dir=$(dirname $infer_model)
set_export_weight=$(func_set_params "${export_weight}" "${infer_model}")
set_save_infer_key=$(func_set_params "${save_infer_key}" "${save_infer_dir}")
export_cmd="${python} ${infer_run_exports[Count]} ${set_export_weight} ${set_save_infer_key}"
echo ${infer_run_exports[Count]}
echo $export_cmd
eval $export_cmd
status_export=$?
status_check $status_export "${export_cmd}" "${status_log}"
else
save_infer_dir=${infer_model}
fi
#run inference
is_quant=${infer_quant_flag[Count]}
if [ ${MODE} = "klquant_whole_infer" ]; then
is_quant="True"
fi
func_inference "${python}" "${inference_py}" "${save_infer_dir}" "${LOG_PATH}" "${infer_img_dir}" ${is_quant}
Count=$(($Count + 1))
done
else
IFS="|"
export Count=0
USE_GPU_KEY=(${train_use_gpu_value})
for gpu in ${gpu_list[*]}; do
train_use_gpu=${USE_GPU_KEY[Count]}
Count=$(($Count + 1))
ips=""
if [ ${gpu} = "-1" ];then
env=""
elif [ ${#gpu} -le 1 ];then
env="export CUDA_VISIBLE_DEVICES=${gpu}"
eval ${env}
elif [ ${#gpu} -le 15 ];then
IFS=","
array=(${gpu})
env="export CUDA_VISIBLE_DEVICES=${array[0]}"
IFS="|"
else
IFS=";"
array=(${gpu})
ips=${array[0]}
gpu=${array[1]}
IFS="|"
env=" "
fi
for autocast in ${autocast_list[*]}; do
if [ ${autocast} = "amp" ]; then
set_amp_config="Global.use_amp=True Global.scale_loss=1024.0 Global.use_dynamic_loss_scaling=True"
else
set_amp_config=" "
fi
for trainer in ${trainer_list[*]}; do
flag_quant=False
if [ ${trainer} = ${pact_key} ]; then
run_train=${pact_trainer}
run_export=${pact_export}
flag_quant=True
elif [ ${trainer} = "${fpgm_key}" ]; then
run_train=${fpgm_trainer}
run_export=${fpgm_export}
elif [ ${trainer} = "${distill_key}" ]; then
run_train=${distill_trainer}
run_export=${distill_export}
elif [ ${trainer} = ${trainer_key1} ]; then
run_train=${trainer_value1}
run_export=${export_value1}
elif [[ ${trainer} = ${trainer_key2} ]]; then
run_train=${trainer_value2}
run_export=${export_value2}
else
run_train=${norm_trainer}
run_export=${norm_export}
fi
if [ ${run_train} = "null" ]; then
continue
fi
set_autocast=$(func_set_params "${autocast_key}" "${autocast}")
set_epoch=$(func_set_params "${epoch_key}" "${epoch_num}")
set_pretrain=$(func_set_params "${pretrain_model_key}" "${pretrain_model_value}")
set_batchsize=$(func_set_params "${train_batch_key}" "${train_batch_value}")
set_train_params1=$(func_set_params "${train_param_key1}" "${train_param_value1}")
set_use_gpu=$(func_set_params "${train_use_gpu_key}" "${train_use_gpu}")
if [ ${#ips} -le 26 ];then
save_log="${LOG_PATH}/${trainer}_gpus_${gpu}_autocast_${autocast}"
nodes=1
else
IFS=","
ips_array=(${ips})
IFS="|"
nodes=${#ips_array[@]}
save_log="${LOG_PATH}/${trainer}_gpus_${gpu}_autocast_${autocast}_nodes_${nodes}"
fi
# load pretrain from norm training if current trainer is pact or fpgm trainer
if ([ ${trainer} = ${pact_key} ] || [ ${trainer} = ${fpgm_key} ]) && [ ${nodes} -le 1 ]; then
set_pretrain="${load_norm_train_model}"
fi
set_save_model=$(func_set_params "${save_model_key}" "${save_log}")
if [ ${#gpu} -le 2 ];then # train with cpu or single gpu
cmd="${python} ${run_train} ${set_use_gpu} ${set_save_model} ${set_epoch} ${set_pretrain} ${set_autocast} ${set_batchsize} ${set_train_params1} ${set_amp_config} "
elif [ ${#ips} -le 26 ];then # train with multi-gpu
cmd="${python} -m paddle.distributed.launch --gpus=${gpu} ${run_train} ${set_use_gpu} ${set_save_model} ${set_epoch} ${set_pretrain} ${set_autocast} ${set_batchsize} ${set_train_params1} ${set_amp_config}"
else # train with multi-machine
cmd="${python} -m paddle.distributed.launch --ips=${ips} --gpus=${gpu} ${run_train} ${set_use_gpu} ${set_save_model} ${set_pretrain} ${set_epoch} ${set_autocast} ${set_batchsize} ${set_train_params1} ${set_amp_config}"
fi
# run train
eval "unset CUDA_VISIBLE_DEVICES"
eval $cmd
status_check $? "${cmd}" "${status_log}"
set_eval_pretrain=$(func_set_params "${pretrain_model_key}" "${save_log}/${train_model_name}")
# save norm trained models to set pretrain for pact training and fpgm training
if [ ${trainer} = ${trainer_norm} ] && [ ${nodes} -le 1 ]; then
load_norm_train_model=${set_eval_pretrain}
fi
# run eval
if [ ${eval_py} != "null" ]; then
set_eval_params1=$(func_set_params "${eval_key1}" "${eval_value1}")
eval_cmd="${python} ${eval_py} ${set_eval_pretrain} ${set_use_gpu} ${set_eval_params1}"
eval $eval_cmd
status_check $? "${eval_cmd}" "${status_log}"
fi
# run export model
if [ ${run_export} != "null" ]; then
# run export model
save_infer_path="${save_log}"
set_export_weight=$(func_set_params "${export_weight}" "${save_log}/${train_model_name}")
set_save_infer_key=$(func_set_params "${save_infer_key}" "${save_infer_path}")
export_cmd="${python} ${run_export} ${set_export_weight} ${set_save_infer_key}"
eval $export_cmd
status_check $? "${export_cmd}" "${status_log}"
#run inference
eval $env
save_infer_path="${save_log}"
if [[ ${inference_dir} != "null" ]] && [[ ${inference_dir} != '##' ]]; then
infer_model_dir="${save_infer_path}/${inference_dir}"
else
infer_model_dir=${save_infer_path}
fi
func_inference "${python}" "${inference_py}" "${infer_model_dir}" "${LOG_PATH}" "${train_infer_img_dir}" "${flag_quant}"
eval "unset CUDA_VISIBLE_DEVICES"
fi
done # done with: for trainer in ${trainer_list[*]}; do
done # done with: for autocast in ${autocast_list[*]}; do
done # done with: for gpu in ${gpu_list[*]}; do
fi # end if [ ${MODE} = "infer" ]; then
# Linux GPU/CPU 基础训练推理测试开发文档
# 目录
- [1. 简介](#1)
- [2. 命令解析](#2)
- [3. 测试功能开发](#2)
- [2.1 准备数据与环境](#.21)
- [2.2 准备开发所需脚本](#2.2)
- [2.3 填写配置文件](#2.3)
- [2.4 验证配置正确性](#2.4)
- [2.5 撰写说明文档](#2.5)
- [4. 附录](#4)
- [4.1 `train_infer_python.txt`配置文件说明](#4.1)
<a name="1"></a>
## 1. 简介
本文档主要介绍飞桨模型在 Linux GPU/CPU 下服务化部署能力的测试开发过程。主要内容为
1. 在基于训练引擎预测的基础上,完成基于Paddle Inference的推理过程开发。
在此之前,您需要完成下面的内容。
1. 参考 [《模型复现指南》](../../lwfx/ArticleReproduction_CV.md),完成模型的训练与基于训练引擎的预测过程。
2. 参考 [《Linux GPU/CPU 基础训练推理开发文档》](../linux_train_infer_python/README.md),完成模型的训练和基于Paddle Inference的模型推理开发。
具体地,本文档主要关注Linux GPU/CPU 下模型的基础训练推理全流程测试,具体测试点如下:
- 模型训练方面:单机单卡/多卡训练跑通
- 飞桨模型转换:保存静态图模型
- Paddle Inference 推理过程跑通
<a name="2"></a>
## 2. 命令解析
运行模型训练、动转静、推理过程的命令差别很大,但是都可以拆解为3个部分:
```
python run_script set_configs
```
例如:
* 对于通过配置文件传参的场景来说,`python3.7 train.py -c config.yaml -o epoch_num=120`
* `python`部分为`python3.7`
* `run_script`部分为`train.py`
* `set_configs`部分为`-c config.yaml -o epoch_num=120`
* 对于通过argparse传参的场景来说,`python3.7 train.py --lr=0.1, --output=./output`
* `python`部分为`python3.7`
* `run_script`部分为`train.py`
* `set_configs`部分为`--lr=0.1, --output=./output`
其中,可修改参数`set_configs`一般通过`=`进行分隔,`=`前面的内容可以认为是key,后面的内容可以认为是value,那么通过给定配置文件模板,解析配置,得到其中的key和value,结合`python``run_script`,便可以拼凑出一条完整的命令。
<a name="3"></a>
## 3. 测试功能开发
基础训练推理测试开发过程主要分为以下5个步骤。
<div align="center">
<img src="./images/test_linux_train_infer_python_pipeline.png" width="400">
</div>
其中设置了2个核验点。下面进行详细介绍。
<a name="3.1"></a>
### 3.1 准备小数据集与环境
**【基本内容】**
1. 数据集:为方便快速验证训练/评估/推理过程,需要准备一个小数据集(训练集和验证集各8~16张图像即可,压缩后数据大小建议在`20M`以内),放在`lite_data`文件夹下。
相关文档可以参考[论文复现赛指南3.2章节](../lwfx/ArticleReproduction_CV.md),代码可以参考`基于ImageNet准备小数据集的脚本`:[prepare.py](https://github.com/littletomatodonkey/AlexNet-Prod/blob/tipc/pipeline/Step2/prepare.py)。
2. 环境:安装好PaddlePaddle即可进行基础训练推理测试开发
**【注意事项】**
* 为方便管理,建议在上传至github前,首先将lite_data文件夹压缩为tar包,直接上传tar包即可,在测试训练评估与推理过程时,可以首先对数据进行解压。
* 压缩命令: `tar -zcf lite_data.tar lite_data`
* 解压命令: `tar -xf lite_data.tar`
<a name="=3.2"></a>
### 3.2 准备开发所需脚本
**【基本内容】**
在repo中新建`test_tipc`目录,将文件 [common_func.sh](template/test/common_func.sh)[test_train_inference_python.sh](template/test/test_train_inference_python.sh) 分别拷贝到`test_tipc`目录中。
**【注意事项】**
* 上述2个脚本文件无需改动,在实际使用时,直接修改配置文件即可。
<a name="3.3"></a>
### 3.3 填写配置文件
**【基本内容】**
在repo的`test_tipc/`目录中新建`configs/model_name`,将文件 [template/test/train_infer_python.txt](template/test/train_infer_python.txt) 拷贝到该目录中,其中`model_name`需要修改为您自己的模型名称。
**【注意事项】**
**【实战】**
配置文件的含义解析可以参考 [4.1章节配置文件解析](#4.1) 部分。
AlexNet的测试开发配置文件可以参考:[train_infer_python.txt](https://github.com/littletomatodonkey/AlexNet-Prod/blob/tipc/pipeline/Step5/AlexNet_paddle/test_tipc/configs/AlexNet/train_infer_python.txt)
<a name="3.4"></a>
### 3.4 验证配置正确性
**【基本内容】**
基于修改完的配置,运行
```bash
bash test_tipc/test_train_inference_python.sh ${your_params_file} lite_train_lite_infer
```
**【注意事项】**
如果运行失败,会输出具体的报错命令,可以根据输出的报错命令排查下配置文件的问题并修改,示例报错如下所示,通过报错信息可知`pretrained`参数没有添加`.pdparams`后缀,因此直接修改后面的配置文件即可。
```
Run failed with command - python3.7 tools/export_model.py --model=alexnet --pretrained=./test_tipc/output/norm_train_gpus_0_autocast_null/latest --save-inference-dir=./test_tipc/output/norm_train_gpus_0_autocast_null!
```
**【实战】**
AlexNet中验证配置正确性的脚本:[Linux端基础训练推理功能测试文档](https://github.com/littletomatodonkey/AlexNet-Prod/blob/tipc/pipeline/Step5/AlexNet_paddle/test_tipc/docs/test_train_inference_python.md#23-%E5%8A%9F%E8%83%BD%E6%B5%8B%E8%AF%95)
**【核验】**
基于修改后的配置文件,测试通过,全部命令成功
<a name="3.5"></a>
### 3.5 撰写说明文档
**【基本内容】**
撰写TIPC功能总览和测试流程说明文档,分别为
1. TIPC功能总览文档:test_tipc/README.md
2. Linux GPU/CPU 基础训练推理测试说明文档:test_tipc/docs/test_train_infer_python.md
2个文档模板分别位于,可以直接拷贝到自己的repo中,根据自己的模型进行修改。
1. [./template/test/doc/README.md](./template/test/doc/README.md)
2. [./template/test/doc/test_train_inference_python.md](./template/test/doc/test_train_inference_python.md)
**【实战】**
AlexNet中`test_tipc`文档如下所示。
1. TIPC功能总览文档:https://github.com/littletomatodonkey/AlexNet-Prod/blob/tipc/pipeline/Step5/AlexNet_paddle/test_tipc/README.md
2. Linux GPU/CPU 基础训练推理测试说明文档:https://github.com/littletomatodonkey/AlexNet-Prod/blob/tipc/pipeline/Step5/AlexNet_paddle/test_tipc/docs/test_train_inference_python.md
**【核验】**
repo中最终目录结构如下所示。
```
test_tipc
|--configs # 配置目录
| |--model_name # 您的模型名称
| |--train_infer_python.txt # 基础训练推理测试配置文件
|--docs # 文档目录
| |--test_train_inference_python.md # 基础训练推理测试说明文档
|----README.md # TIPC说明文档
|----test_train_inference_python.sh # TIPC基础训练推理测试解析脚本,无需改动
|----common_func.sh # TIPC基础训练推理测试常用函数,无需改动
```
基于`test_train_inference_python.md`文档,跑通`Linux GPU/CPU 基础训练推理测试`流程。
<a name="4"></a>
## 4. 附录
<a name="4.1"></a>
### 4.1 `train_infer_python.txt`配置文件说明
完整的`train_infer_python.txt`配置文件共有51行,包含5个方面的内容。
* 训练参数:第1~14行
* 训练脚本配置:第15~22行
* 评估脚本和配置:第23~26行(本部分无需关注,这里不再展开介绍)
* 模型导出脚本和配置:第27~36行
* 模型Inference推理:第37~51行
具体内容见[train_infer_python.txt](template/test/train_infer_python.txt)
文本文件中主要有以下3种类型字段。
* 一行内容以冒号为分隔符:该行可以被解析为`key:value`的格式,需要根据实际的含义修改该行内容,下面进行详细说明。
* 一行内容为`======xxxxx=====`:该行内容表示,无需修改。
* 一行内容为`##`:该行内容表示段落分隔符,没有实际意义,无需修改。
#### 4.1.1 训练配置参数
在配置文件中,可以通过下面的方式配置一些常用的输出文件,如:是否使用GPU、迭代轮数、batch size、预训练模型路径等,下面给出了常用的配置以及需要修改的内容。
| 行号 | 参考内容 | 含义 | key是否需要修改 | value是否需要修改 | 修改内容 |
|----|-------------------------------------|---------------|-----------|-------------|----------------------------------|
| 2 | model_name:alexnet | 模型名字 | 否 | 是 | value修改为自己的模型名字 |
| 3 | python:python3.7 | python环境 | 否 | 是 | value修改为自己的python环境 |
| 4 | gpu_list:0 | gpu id | 否 | 是 | value修改为自己的GPU ID |
| 5 | use_gpu:True | 是否使用GPU | 是 | 是 | key修改为设置GPU使用的内容,value修改 |
| 6 | auto_cast:null | 是否使用混合精度 | 否 | 否 | - |
| 7 | epoch_num:lite_train_infer=1 | 迭代的epoch数目 | 是 | 否 | key修改为可以设置代码中epoch数量的内容 |
| 8 | output_dir:./output/ | 输出目录 | 是 | 否 | key修改为代码中可以设置输出路径的内容 |
| 9 | train_batch_size:lite_train_infer=1 | 训练的batch size | 是 | 否 | key修改为可以设置代码中batch size的内容 |
| 10 | pretrained_model:null | 预训练模型 | 是 | 是 | 如果训练时指定了预训练模型,则需要key和value需要对应修改 |
| 11 | train_model_name:latest | 训练结果的模型名字 | 否 | 是 | value需要修改为训练完成之后保存的模型名称,用于后续的动转静 |
| 12 | null:null | 预留字段 | 否 | 否 | - |
| 13 | null:null | 预留字段 | 否 | 否 | - |
#### 4.1.2 训练命令配置
| 行号 | 参考内容 | 含义 | key是否需要修改 | value是否需要修改 | 修改内容 |
|----|---------------------------------------------|-----------------|-----------|-------------|-------------------|
| 15 | trainer:norm_train | 训练方法 | 否 | 否 | - |
| 16 | norm_train:tools/train.py -c config.yaml -o | norm_train的训练脚本 | 否 | 是 | value可以修改为自己的训练命令 |
| 17 | pact_train:null | 量化训练脚本配置 | | 否 | - |
| 18 | fpgm_train:null | 裁剪训练脚本配置 | 否 | 否 | - |
| 19 | distill_train:null | 蒸馏训练脚本配置 | 否 | 否 | - |
| 20 | null:null | 预留字段 | 否 | 否 | - |
| 21 | null:null | 预留字段 | 否 | 否 | - |
#### 4.1.3 模型导出配置参数
| 行号 | 参考内容 | 含义 | key是否需要修改 | value是否需要修改 | 修改内容 |
|----|------------------|-----------|-----------|-------------|-------------------------|
| 28 | save_dir:./output/ | 输出目录 | 是 | 否 | key修改为代码中可以设置输出目录的内容 |
| 29 | pretrained_model: | 训练模型路径 | 是 | 否 | key修改为代码中可以设置预训练模型路径的内容 |
| 30 | norm_export:tools/export_model.py -c config.yaml -o | 模型 | 否 | 是 | value修改为实际的动转静导出命令 |
| 31 | quant_export:null | 量化模型动转静 | 否 | 否 | - |
| 32 | fpgm_export:null | 裁剪模型动转静 | 否 | 否 | - |
| 33 | distill_export:null | 蒸馏模型动转静脚本 | 否 | 否 | - |
| 34 | null:null | 预留字段 | 否 | 否 | - |
| 35 | null:null | 预留字段 | 否 | 否 | - |
#### 4.1.4 模型推理配置
| 行号 | 参考内容 | 含义 | key是否需要修改 | value是否需要修改 | 修改内容 |
|----|------------------|-----------------|-----------|-------------|-------------|
| 37 | infer_model:null | 推理模型保存路径 | 否 | 否 | |
| 38 | infer_export:tools/export_model.py -c config.yaml -o | 推理前是否需要导出 | 否 | 是 | value修改为和30行内容一致即可 |
| 39 | infer_quant:False | 是否量化推理 | 否 | 否 | - |
| 40 | inference:infer.py | 推理脚本 | 否 | 是 | value修改为自己的推理脚本 |
| 41 | --use_gpu:True|False | 是否使用GPU | 是 | 是 | key和value修改为GPU设置的参数和值 |
| 42 | --use_mkldnn:True|False | 是否使用MKLDNN | 是 | 是 | key和value修改为MKLNN设置的参数和值 |
| 43 | --cpu_threads:1|6 | 开启MKLDNN时使用的线程数 | 是 | 是 | key和value修改为CPU线程数设置的参数和值 |
| 44 | --batch_size:1 | 推理batch size | 是 | 否 | key修改为代码中可以修改为batch size的内容 |
| 45 | --use_tensorrt:null | 是否开启TensorRT预测 | 否 | 否 | 不对该项进行测试 |
| 46 | --precision:null | 精度范围 | 否 | 否 | 不对该项进行测试 |
| 47 | --model_dir:./infer | 模型目录 | 是 | 否 | key修改为代码中可以设置inference model目录的内容 |
| 48 | --image_dir:./lite_data/1.jpg | 图片路径或者图片文件夹路径 | 是 | 否 | key和value修改为自己的CPU线程数设置参数和值 |
| 49 | --save_log_path:null | 推理日志输出路径 | 否 | 否 | - |
| 50 | --benchmark:False | 是否使用 | 是 | 是 | key和value修改为规范化推理日志输出设置的参数和值 |
| 51 | null:null | 预留字段 | 否 | 否 | - |
# Linux GPU/CPU 服务化部署开发规范
# 目录
- [1. 简介](#1)
- [2. 服务化部署开发规范](#2)
- [2.1 开发流程](#2.1)
- [2.2 核验点](#2.2)
- [3. 服务化部署测试开发规范](#3)
- [3.1 开发流程](#3.1)
- [3.2 核验点](#3.2)
<a name="1"></a>
## 1. 简介
本文档主要介绍飞桨模型在 Linux GPU/CPU 下服务化部署能力的开发规范。主要包含三个步骤:
1. 参考[《Linux GPU/CPU 服务化部署开发文档》](./py_serving.md),在Paddle Inference的模型推理基础上,完成服务化部署能力的开发。
2. 参考[《Linux GPU/CPU 服务化部署测试开发文档》](),完成 TIPC 服务化部署测试开发
在此之前,您需要完成下面的内容(如果您已经开发完基于Paddle Inference的模型推理过程,该步骤可以跳过)。
* 参考 [《Linux GPU/CPU 基础训练推理开发文档》](../linux_train_infer_python/README.md),完成模型的训练和基于Paddle Inference的模型推理开发。
<a name="2"></a>
## 2. 服务化部署开发规范
<a name="2.1"></a>
### 2.1 开发流程
服务化部署开发流程如下图所示。
<div align="center">
<img src="./images/py_serving_deploy_pipeline.jpg" width="800">
</div>
更多内容请参考:[服务化部署开发文档](./py_serving.md)
<a name="2.2"></a>
### 2.2 核验点
在开发过程中,至少需要产出下面的内容。
#### 2.2.1 模型预测服务启动
* 可以成功启动模型预测服务,并在客户端完成访问。
#### 2.2.2 服务化部署结果正确性
* 返回结果与基于Paddle Inference的模型推理结果完全一致。
#### 2.2.3 说明文档
* 文档中给出服务化部署的数据、环境准备、启动服务、访问服务的具体命令说明。
<a name="3"></a>
## 3. 服务化部署测试开发规范
<a name="3.1"></a>
### 3.1 开发流程
服务化部署测试开发流程如下所示。
coming soon!
更多的介绍可以参考:[服务化部署测试开发文档](./test_serving.md)
<a name="3.2"></a>
### 3.2 核验点
coming soon!
...@@ -13,7 +13,9 @@ ...@@ -13,7 +13,9 @@
- [3 FAQ](#3---) - [3 FAQ](#3---)
<a name="1---"></a> <a name="1---"></a>
## 1 简介 ## 1 简介
Paddle Serving依托深度学习框架PaddlePaddle旨在帮助深度学习开发者和企业提供高性能、灵活易用的工业级在线推理服务。Paddle Serving支持RESTful、gRPC、bRPC等多种协议,提供多种异构硬件和多种操作系统环境下推理解决方案,和多种经典预训练模型示例。 Paddle Serving依托深度学习框架PaddlePaddle旨在帮助深度学习开发者和企业提供高性能、灵活易用的工业级在线推理服务。Paddle Serving支持RESTful、gRPC、bRPC等多种协议,提供多种异构硬件和多种操作系统环境下推理解决方案,和多种经典预训练模型示例。
本文档主要介绍飞桨模型在 Linux GPU/CPU 下服务化部署能力的开发。主要包含三个步骤: 本文档主要介绍飞桨模型在 Linux GPU/CPU 下服务化部署能力的开发。主要包含三个步骤:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册