Paddle Inference Support

当前的PaddleTS已完成了绝大多数模型对Paddle Inference功能的支持, Paddle Inference相关介绍以及功能可以参考: Paddle Inference . PaddleTS 支持了原生paddle network模型的导出, 可用于Paddle Inference进行推理部署, 同时为了简化用户使用流程, 提供了python的前序数据构建的工具,可以让用户轻松完成Paddle Inference的输入数据构建.

1. 模型准备以及训练

from paddlets.datasets.repository import get_dataset
from paddlets.models.forecasting.dl.rnn import RNNBlockRegressor

# prepare data
dataset = get_dataset("WTH")

rnn = RNNBlockRegressor(
    in_chunk_len=4,
    out_chunk_len=2,
    max_epochs=10
)

#fit
rnn.fit(dataset)

#predict
rnn.predict(dataset)

#                      WetBulbCelsius
# 2014-01-01 00:00:00       -1.436116
# 2014-01-01 01:00:00       -2.057547

2 模型保存

PaddleTS所有时序预测以及异常检测模型的save接口都新增了 network_model 以及 dygraph_to_static 的参数设置;其中, network_model默认是False, 表示仅导出只支持PaddleTS.predict推理的模型文件, 当network_model设置为True的时候, 在此基础上,会新增对paddle 原始network 的模型以及参数的导出, 可用于 Paddle Inference进行推理; dygraph_to_static参数仅当当network_model为True的时候起作用,表示将导出的模型从动态图转换成静态图, 参考 动转静.

rnn.save("./rnn", network_model=True, dygraph_to_static=True)

# dump file names
# ./rnn.pdmodel
# ./rnn.pdiparams
# ./rnn_model_meta

上述代码展示了save后的模型文件, 其中rnn.pdmodel以及rnn.pdiparams作为paddle 原生模型以及模型参数, 可用于Paddle Inference的应用;同时PaddleTS生成了rnn_model_meta文件用于模型的描述, 里面包含了模型的输入数据类型以及shape的各种元信息, 便于用户对模型进行正确的部署应用.

3. Paddle Inference

有了第二步导出的模型, 用户即可利用Paddle Inference 进行模型推理部署了,下面给出了简单的示例

3.1 模型导入

import paddle.inference as paddle_infer
config = paddle_infer.Config("./rnn.pdmodel", "./rnn.pdiparams")
predictor = paddle_infer.create_predictor(config)
input_names = predictor.get_input_names()
print(f"input_name: f{input_names}")

# input_name: f['observed_cov_numeric', 'past_target']

import json
with open("./rnn_model_meta") as f:
    json_data = json.load(f)
    print(json_data)

# {'model_type': 'forecasting', 'ancestor_classname_set': ['RNNBlockRegressor', 'PaddleBaseModelImpl', 'PaddleBaseModel', 'BaseModel', 'Trainable', 'ABC', 'object'], 'modulename': 'paddlets.models.forecasting.dl.rnn', 'size': {'in_chunk_len': 4, 'out_chunk_len': 2, 'skip_chunk_len': 0}, 'input_data': {'past_target': [None, 4, 1], 'observed_cov_numeric': [None, 4, 11]}}

通过上述代码我们可以看到, 我们可以基于input_name去构建我们的输入, 同时input_name本身也包含了数据的属性(target、known_cov、observed_cov), 并且rnn_model_meta文件中除了保函input_name之外, 还包含了其输入类型、数据的shape格式、原始的in_chunk_len、out_chunk_len等信息; 基于这些信息,用户可以轻松的完成输入数据构建。

3.2 构建输入的tensor

当然, 为了简化用户的使用, PaddleTS也内置了基于TSDataset自动构建Paddle Inference输入的功能

from paddlets.utils.utils import build_ts_infer_input

input_data = build_ts_infer_input(dataset, "./rnn_model_meta")

for key, value in json_data['input_data'].items():
    input_handle1 = predictor.get_input_handle(key)
    #set batch_size=1
    value[0] = 1
    input_handle1.reshape(value)
    input_handle1.copy_from_cpu(input_data[key])

3.3 推理

predictor.run()
output_names = predictor.get_output_names()
output_handle = predictor.get_output_handle(output_names[0])
output_data = output_handle.copy_to_cpu()
print(output_data)

# [[[-1.436116 ]
#   [-2.0575469]]]

我们可以看到, 上述程序输出的结果和章节1中predict的结果基本一致