【进阶篇】C-API 使用流程

原创
2018/02/09 22:24
阅读数 230


导语

本周起将推送【使用指南—进阶篇】推文。在进阶篇,我们将向您介绍PaddlePaddle的使用说明、开发标准、模型配置等内容。在使用进阶篇推文之前,请参考安装与编译部分推文完成PaddlePaddle的安装


本周推文目录如下:


周一:【进阶篇】命令行参数细节描述

周二:【进阶篇】命令行参数使用案例

周三:【进阶篇】在不同的集群框架下完成分布式训练

周四:【进阶篇】安装与编译C-API预测库

周五:【进阶篇】C-API 使用流程



编写PaddlePaddle

排版|wangp


这篇推文介绍 PaddlePaddle C-API 整体使用流程


 1 

使用流程


使用 C-API 的工作流程如图1所示,分为(1)准备预测模型和(2)预测程序开发两大部分

640?wx_fmt=png 640?wx_fmt=png


C-API使用流程示意图


准备预测模型


1.只将神经网络结构进行序列化

  • 只对神经网络结构进行序列化,加载模型需同时指定:网络结构的序列化结果和模型参数存储目录

2.将网络结构定义和训练结束存储下来的模型参数文件(多个)合并入一个文件

  • 神经网络模型结构和训练好的模型将被序列化合并入一个文件

  • 预测时只需加载一个文件便于发布

注意:以上两种方式只需选择其一即可


调用 C-API 开发预测序


1.初始化PaddlePaddle运行环境

2.加载预测模型

3.创建神经网络输入,组织输入数据

4.进行前向计算,获得计算结果

5.清理和结束



 2 

准备预测模型


准备预测模型部分,我们以手写数字识别任务为例进行介绍。手写数字识别任务定义了一个含有两个隐层的简单全连接网络(链接:https://github.com/PaddlePaddle

/book/blob/develop/02.recognize_digits/README.cn.md#softmax%E5%9B%9E%E5%BD%92softmax-regression),网络接受一幅图片作为输入,将图片分类到 0 ~ 9 类别标签之一。完整代码可以查看此目录(链接:https://github.com/PaddlePaddle/Paddle/tree/

develop/paddle/capi/examples/model_inference/dense)中的相关脚本


调用C-API开发预测程序需要一个训练好的模型,运行MNIST手写数字识别目录下的mnist_v2.py脚本(连接:https://github.com/PaddlePaddle/Paddle/blob/

develop/paddle/capi/examples/model_inference/dense/mnist_v2.py),在终端执行python mnist_v2.py,会使用 PaddlePaddle 内置的 MNIST 数据(链接:http://yann.lecun.com/exdb/mnist/)集进行训练。训练好的模型默认保存在当前运行目录下的models目录中


下面,我们将训练结束后存储下来的模型转换成预测模型


A.序列化神经网络模型配置


PaddlePaddle 使用 protobuf 来传输网络配置文件中定义的网络结构和相关参数,使用 C-API 进行预测时,需要将网络结构使用 protobuf 进行序列化,写入文件中


调用paddle.utils.dump_v2_config中的dump_v2_config函数能够将使用 PaddlePaddle V2 API 定义的神经网络结构 dump 到指定文件中,示例代码如下:

from paddle.utils.dump_v2_config import dump_v2_config

from mnist_v2 import network


predict = network(is_infer=True)

dump_v2_config(predict, "trainer_config.bin", True)


对手写数字识别这个示例,mnist_v2.py脚本集成了序列化神经网络结构的过程,可以直接运行 python mnist_v2.py --task dump_config 对神经网络结构进行序列化,结果会写入当前运行目录下的trainer_config.bin文件中


使用这种方式,需要在运行时将神经网络的多个可学习参数放在同一个目录中,C-API可以通过分别指定序列化后的网络结构文件和参数目录来加载训练好的模型


B.合并模型文件(可选)


一些情况为了便于发布,希望能够将序列化后的神经网络结构和训练好的模型参数打包进一个文件。对于这样的需求,可以使用paddle.utils.merge_model中的merge_v2_model接口对神经网络结构和训练好的参数进行序列化,将序列化结果写入一个文件内。

代码示例如下:

from paddle.utils.merge_model import merge_v2_modelss

from mnist_v2 import network


net = network(is_infer=True)

param_file = "models/params_pass_4.tar"

output_file = "output.paddle.model"

merge_v2_model(net, param_file, output_file)


对手写数字识别这个示例,可直接运行 python merge_v2_model.py(链接:https://github.com/

PaddlePaddle/Paddle/blob/develop/paddle/capi/examples/model_inference/dense/merge_v2_model.py)。序列化结果会写入当前运行目录下的output.paddle.model文件中。使用这种方式,运行时C-API可以通过指定output.paddle.model文件的路径来加载预测模型


注意事项


  • 为使用C-API,在调用dump_v2_config序列化神经网络结构时,参数binary必须指定为True

  • 预测使用的网络结构往往不同于训练,通常需要去掉网络中的:(1)类别标签层;(2)损失函数层;(3)evaluator等,只留下核心计算层,请注意是否需要修改网络结构

  • 预测时,可以获取网络中定义的任意多个(大于等于一个)层前向计算的结果,需要哪些层的计算结果作为输出,就将这些层加入一个Python list中,作为调用dump_v2_config的第一个参数



 3 

编写预测代码


预测代码更多详细示例代码请参考C-API使用示例(链接https://github.com/PaddlePaddle/Paddle/tree/

develop/paddle/capi/examples/model_inference)目录下的代码示例。这一节对图中预测代码编写的5个步骤进行介绍和说明


step 1. 初始化PaddlePaddle运行环境


第一步需调用paddle_init 初始化PaddlePaddle运行环境,该接口接受两个参数:参数的个数和参数列表


step2. 加载模型


这里介绍C-API使用中的一个重要概念:Gradient Machine


概念上,在 PaddlePaddle 内部,一个GradientMachine类的对象管理着一组计算层(PaddlePaddle Layers)来完成前向和反向计算,并处理与之相关的所有细节。在调用C-API预测时,只需进行前向计算而无需调用反向计算。这篇文档之后部分会使用gradient machine来特指调用PaddlePaddle C-API创建的GradientMachine类的对象。每一个 gradient machine 都会管理维护一份训练好的模型,下面是C-API提供的,两种常用的模型加载方式:


A.调用paddle_gradient_machine_load_parameter_

from_disk接口,从磁盘加载预测模型。这时gradient machine会独立拥有一份训练好的模型


B.调用paddle_gradient_machine_create_shared_

param接口,与其它gradient machine的共享已经加载的预测模型。这种情况多出现在使用多线程预测时,通过多个线程共享同一个模型来减少内存开销。可参考此示例(链接:https://github.com/PaddlePaddle/Paddle

/blob/develop/paddle/capi/examples/model_inference/multi_thread/main.c)


注意事项


  • 使用PaddlePaddle V2 API训练,模型中所有可学习参数会被存为一个压缩文件,需要手动进行解压,将它们放在同一目录中,C-API不会直接加载 V2 API 存储的压缩文件

  • 如果使用merge model方式将神经网络结构和训练好的参数序列化到一个文件,请参考此示例(连接:https://github.com/PaddlePaddle/Mobile/blob/develop/Demo/linux/paddle_image_recognizer.cpp#L59)

  • 通过灵活使用以上两个接口,加载模型可其它多种方式,例如也可在程序运行过程中再加载另外一个模型


step 3. 创建神经网络输入,组织输入数据


基本使用概念:

  • 在PaddlePaddle内部,神经网络中一个计算层的输入输出被组织为一个 Argument 结构体,如果神经网络有多个输入或者多个输出,每一个输入/输出都会对应有自己的Argument

  • Argument 并不真正“存储”数据,而是将输入/输出数据有机地组织在一起

  • Argument内部由:1. Matrix(二维矩阵,存储浮点类型输入/输出);2. IVector(一维数组,仅用于存储整型值,多用于自然语言处理任务)来实际存储数据


C-API支持的所有输入数据类型和他们的组织方式,请参考“输入/输出数据组织”一节


这篇文档的之后部分会使用argument来特指PaddlePaddle C-API中神经网络的一个输入/输出,使用paddle_matrix特指argument中用于存储数据的Matrix类的对象


在组织神经网络输入,获取输出时,需要思考完成以下工作:


  • 为每一个输入/输出创建argument

  • 为每一个argument创建paddle_matrix来存储数据


与输入不同的是,不需在使用C-API时为输出argumentpaddle_matrix对象分配空间。前向计算之后PaddlePaddle内部已经分配/管理了每个计算层输出的存储空间。


step 4. 前向计算


完成上述准备之后,通过调用 paddle_gradient_machine_forward 接口完成神经网络的前向计算


step 5. 清理


结束预测之后,对使用的中间变量和资源进行清理和释放


640?wx_fmt=png


*原创贴,版权所有,未经许可,禁止转载

*值班小Paddle:wangp

*欢迎在留言区分享您的观点

640?wx_fmt=png


640?wx_fmt=gif

本文分享 CSDN - 飞桨PaddlePaddle。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

展开阅读全文
加载中

作者的其它热门文章

打赏
0
0 收藏
分享
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部