C++ 完整示例¶
概述¶
本教程提供了 Paddle Lite 执行推理的示例程序,通过输入、执行推理、打印推理结果的方式,演示了基于 C++ API 接口的推理基本流程,用户能够快速了解 Paddle Lite 执行推理相关 API 的使用。
本教程以 mobile_light demo 为案例,介绍 C++ API 推理流程,相关代码放置在demo/c++/mobile_light目录。
使用 Paddle Lite 执行推理主要包括以下步骤:
配置 Config 信息:创建 MobileConfig ,用于配置模型路径、运行设备环境等相关信息
模型加载:通过
set_model_from_file
接口配置模型路径。创建 Predictor 对像:通过
CreatePaddlePredictor
接口创建 Predictor 对像,完成模型解析和环境初始化。输入数据:推理之前需要向输入 Tensor 中填充数据。即通过
predictor->GetInput(num)
接口获取第num
个输入 tensor ,先做Resize
处理,给 tensor 分配相应的空间;然后通过获取input_tensor->mutable_data<Dtype>()
输入数据地址进行赋值处理。(如果输入数据是图片,则需要进行预处理,再将预处理后的数据赋值给输入 tensor )执行推理:使用 Predictor 对像的成员函数
Run
进行模型推理输出数据:推理执行结束后,通过
predictor->GetOutput(num)
接口获取第num
个输出 tensor。
其流程图如下:
C++ 应用开发说明¶
C++代码调用 Paddle Lite 执行预测库仅需以下五步:
(1) 引用头文件和命名空间
#include "paddle_api.h"
using namespace paddle::lite_api;
(2) 指定模型文件,创建 Predictor
// 1. Set MobileConfig
MobileConfig config;
// 2. Set the path to the model generated by opt tools
config.set_model_from_file(model_file_path);
// 3. Create PaddlePredictor by MobileConfig
std::shared_ptr<PaddlePredictor> predictor =
CreatePaddlePredictor<MobileConfig>(config);
(3) 设置模型输入 (下面以全一输入为例)
std::unique_ptr<Tensor> input_tensor(std::move(predictor->GetInput(0)));
input_tensor->Resize({1, 3, 224, 224});
auto* data = input_tensor->mutable_data<float>();
for (int i = 0; i < ShapeProduction(input_tensor->shape()); ++i) {
data[i] = 1;
}
如果模型有多个输入,每一个模型输入都需要准确设置 shape 和 data。
(4) 执行预测
predictor->Run();
(5) 获得预测结果
std::unique_ptr<const Tensor> output_tensor(
std::move(predictor->GetOutput(0)));
// 转化为数据
auto output_data=output_tensor->data<float>();
备注:
详细的 C++ API 说明文档位于 C++ API。 更多 C++ 应用预测开发可以参考位于位于 Paddle-Lite-Demo的工程示例代码。
C++ 轻量级 mobilenet_light Demo介绍¶
以轻量级 mobilenet_light demo 为例,详细介绍如何在手机 android 端 shell 环境下,跑通模型分类案例。
1. 环境准备¶
编译和运行 Android C++ 示例程序,你需要准备:
一台可以编译 Paddle Lite 的电脑,具体环境配置,请参考 编译文档,推荐使用 docker。
一台安卓手机,并在电脑上安装 adb 工具 ,以确保电脑和手机可以通过 adb 连接。
2. 下载或者编译预测库¶
(1) 下载预测库 在预测库 Lite 预编译库下载下载界面,可根据您的手机型号和运行需求选择合适版本。
以Android-ARMv8 架构为例,可以下载以下版本:
Arch | with_extra | arm_stl | with_cv | 下载 |
---|---|---|---|---|
armv8 | OFF | c++_static | OFF | 2.10-rc |
解压后内容结构如下:
inference_lite_lib.android.armv8 Paddle Lite 预测库
├── cxx C++ 预测库
│ ├── include C++ 预测库头文件
│ └── lib C++ 预测库文件
│ ├── libpaddle_api_light_bundled.a 静态预测库
│ └── libpaddle_light_api_shared.so 动态预测库
├── demo 示例 Demo
│ ├── cxx C++ 示例 Demo
│ ├── mobilenet_light mobilenet_light Demo 文件夹
│ ├── MakeFile MakeFile 文件,用于编译可执行文件
│ └── mobilenetv1_light_api.cc C++ 接口的推理源文件
│ └── java Java 示例 Demo
└── java Java 预测库
(2)预测库编译 预测库编译方法请参考编译文档完成 Paddle Lite 预测库编译,获取可执行的 C++ Demo。
3. 准备预测部署模型¶
(1) 模型下载:下载 mobilenet_v1 模型后解压,得到 Paddle 非 combined 形式的模型,位于文件夹 mobilenet_v1
下。可通过模型可视化工具 Netron 打开文件夹下的__model__
文件,查看模型结构。
wget http://paddle-inference-dist.bj.bcebos.com/mobilenet_v1.tar.gz
tar zxf mobilenet_v1.tar.gz
(2) 模型转换:Paddle 的原生模型需要经过 opt 工具转化为 Paddle Lite 可以支持的 naive_buffer 格式。
方式一: 下载 opt 工具,放入与 mobilenet_v1
文件夹同级目录,终端输入以下命令转化模型
# Linux
wget https://github.com/PaddlePaddle/Paddle-Lite/releases/download/v2.9.1/opt
chmod +x opt
./opt --model_dir=./mobilenet_v1 \
--optimize_out_type=naive_buffer \
--optimize_out=./mobilenet_v1_opt
# Mac
wget https://github.com/PaddlePaddle/Paddle-Lite/releases/download/v2.9.1/opt_mac
chmod +x opt_mac
./opt_mac --model_dir=./mobilenet_v1 \
--optimize_out_type=naive_buffer \
--optimize_out=./mobilenet_v1_opt
方式二: 通过 pip 安装 Paddle Lite,终端输入命令转化模型
python -m pip install paddlelite
paddle_lite_opt --model_dir=./mobilenet_v1 \
--optimize_out_type=naive_buffer \
--optimize_out=./mobilenet_v1_opt
以上命令执行成功之后将在同级目录生成名为 mobilenet_v1_opt.nb
的优化后模型文件。
更多的 OPT 工具使用信息,请见 OPT 工具使用文档
4. 编译预测示例程序¶
准备好预测库和模型,就可以直接编译随着预测库一起发布的 C++ Demo ,位于在第二步中下载的预测库文件目录下 inference_lite_lib.android.armv8/demo/cxx
。以 mobilenet_v1 为例,目录下的 mobile_light
为 mobilenet_v1 预测示例,完成可执行文件的编译。
cd inference_lite_lib.android.armv8/demo/cxx/mobile_light
make
会在同级目录下生成名为 mobilenetv1_light_api
的可执行文件。
5. 预测部署和执行¶
(1) 设置手机:手机 USB 连接电脑,打开设置 -> 开发者模式 -> USB调试 -> 允许(授权)当前电脑调试手机
。保证当前电脑已经安装 adb 工具,运行以下命令,确认当前手机设备已被识别:
adb devices
# 如果手机设备已经被正确识别,将输出如下信息
List of devices attached
017QXM19C1000664 device
(2) 预测部署:将第二步中的 C++ 动态预测库文件 libpaddle_light_api_shared.so
、第三步中生成的优化后模型文件 mobilenet_v1_opt.nb
和第四步中编译得到的预测示例程序 mobilenetv1_light_api
放入同一文件夹,并将这三个文件推送到手机:
chmod +x mobile_classify
adb push mobilenet_v1_opt.nb /data/local/tmp
adb push libpaddle_light_api_shared.so /data/local/tmp
adb push mobilenetv1_light_api /data/local/tmp
# 如果推送成功,将显示如下信息
adb shell 'ls -l /data/local/tmp'
total 24168
-rwxrwxrwx 1 root root 1624280 2020-09-01 13:47 libpaddle_light_api_shared.so
-rw-rw-rw- 1 root root 17018243 2020-09-01 12:28 mobilenet_v1_opt.nb
-rwxrwxrwx 1 root root 6076144 2020-09-01 13:47 mobilenetv1_light_api
(3) 执行预测,以下输出为 mobilenet_v1 模型在全1输入时,得到的预测结果。
adb shell 'cd /data/local/tmp && export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/data/local/tmp && ./mobile_classify mobilenet_v1_opt.nb'
# 如果正确运行,将输出如下信息
run_idx:1 / 10: 33.821 ms
run_idx:2 / 10: 33.8 ms
run_idx:3 / 10: 33.867 ms
run_idx:4 / 10: 34.009 ms
run_idx:5 / 10: 33.699 ms
run_idx:6 / 10: 33.644 ms
run_idx:7 / 10: 33.611 ms
run_idx:8 / 10: 33.783 ms
run_idx:9 / 10: 33.731 ms
run_idx:10 / 10: 33.423 ms
======= benchmark summary =======
input_shape(NCHW):1 3 224 224
model_dir:mobilenet_v1_opt.nb
warmup:10
repeats:10
max_duration:34.009
min_duration:33.423
avg_duration:33.7388
====== output summary ======
output tensor num:1
--- output tensor 0 ---
output shape(NCHW):1 1000
output tensor 0 elem num:1000
output tensor 0 standard deviation:0.00219646
output tensor 0 mean value:0.001
更多C++示例¶
更多 C++ 示例,请参考 demo/c++ 的详细说明。
图像分类示例¶
使用 OpenCV 读取处理输入图片,使用 Paddle Lite 执行预测。
cd inference_lite_lib.android.armv8/demo/cxx/mobile_classify
# 下载模型
wget http://paddle-inference-dist.bj.bcebos.com/mobilenet_v1.tar.gz
tar zxvf mobilenet_v1.tar.gz
# 转化模型
paddle_lite_opt --model_dir=./mobilenet_v1 \
--optimize_out_type=naive_buffer \
--optimize_out=./mobilenet_v1_opt
# 编译预测程序
make
# 预测部署
adb push mobile_classify /data/local/tmp/
adb push mobilenet_v1_opt.nb /data/local/tmp/
adb push mobilenet_v1/test.jpg /data/local/tmp/
adb push mobilenet_v1/labels.txt /data/local/tmp/
adb push ../../../cxx/lib/libpaddle_light_api_shared.so /data/local/tmp/
adb shell 'chmod +x /data/local/tmp/mobile_classify'
# 执行预测
adb shell 'cd /data/local/tmp && export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/data/local/tmp && ./mobile_classify mobilenet_v1_opt.nb test.jpg labels.txt'
# 运行成功后 ,将在控制台输出预测结果的前5个类别的类型索引、名字和预测概率
parameter: model_file, image_path and label_file are necessary
parameter: topk, input_width, input_height, are optional
i: 0, index: 287, name: lynx, catamount, score: 0.317595
i: 1, index: 285, name: Egyptian cat, score: 0.308135
i: 2, index: 281, name: tabby, tabby cat, score: 0.161924
i: 3, index: 282, name: tiger cat, score: 0.093659
i: 4, index: 283, name: Persian cat, score: 0.060198
目标检测示例¶
cd inference_lite_lib.android.armv8/demo/cxx/ssd_detection
# 下载模型
wget https://paddlelite-data.bj.bcebos.com/doc_models/ssd_mobilenet_v1.tar.gz
tar zxvf ssd_mobilenet_v1.tar.gz
# 转化模型
paddle_lite_opt --model_dir=./ssd_mobilenet_v1 \
--optimize_out_type=naive_buffer \
--optimize_out=./ssd_mobilenet_v1_opt
# 编译预测程序
make
# 预测部署
adb push ssd_detection /data/local/tmp/
adb push ssd_mobilenet_v1_opt.nb /data/local/tmp/
adb push test.jpg /data/local/tmp/
adb push ../../../cxx/lib/libpaddle_light_api_shared.so /data/local/tmp/
adb shell 'chmod +x /data/local/tmp/ssd_detection'
# 执行预测
adb shell 'cd /data/local/tmp && export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/data/local/tmp && ./ssd_detection ssd_mobilenet_v1_opt.nb test.jpg'
# 运行成功后 ,将在控制台输出检测目标的类型、预测概率和坐标
detection, image size: 935, 1241, detect object: person, score: 0.995543, location: x=187, y=43, width=540, height=591
detection, image size: 935, 1241, detect object: person, score: 0.929626, location: x=125, y=639, width=577, height=597
# 获得目标检测结果图片,并查看
adb pull /data/local/tmp/test_ssd_detection_result.jpg ./