提交 d4811e2b 编写于 作者: C Channingss

add lite&slim doc

上级 c29a78df
# Android平台 # Android平台
PaddleX的安卓端部署由PaddleLite实现,部署的流程如下,首先将训练好的模型导出为inference model,然后使用PaddleLite的python接口对模型进行优化,最后使用PaddleLite的预测库进行部署, PaddleX的安卓端部署由PaddleLite实现,部署的流程如下,首先将训练好的模型导出为inference model,然后对模型进行优化,最后使用PaddleLite的预测库进行部署,PaddleLite的详细介绍和使用可参考:[PaddleLite文档](https://paddle-lite.readthedocs.io/zh/latest/)
PaddleLite的详细介绍和使用可参考:[PaddleLite文档](https://paddle-lite.readthedocs.io/zh/latest/)
> PaddleX --> Inference Model --> PaddleLite Opt --> PaddleLite Inference > PaddleX --> Inference Model --> PaddleLite Opt --> PaddleLite Inference
以下介绍如何将PaddleX导出为inference model,然后使用PaddleLite的OPT模块对模型进行优化: 文章简介:
- step1: 介绍如何将PaddleX导出为inference model
- step2: 使用PaddleLite的OPT模块对模型进行优化
- step3: 介绍了基于MobileNetv2的安卓demo,以及PaddleX Android SDK
## step 1. 安装PaddleLite ## step 1. 将PaddleX模型导出为inference模型
```
pip install paddlelite
```
## step 2. 将PaddleX模型导出为inference模型
参考[导出inference模型](../export_model.html)将模型导出为inference格式模型。 参考[导出inference模型](../export_model.html)将模型导出为inference格式模型。
**注意:由于PaddleX代码的持续更新,版本低于1.0.0的模型暂时无法直接用于预测部署,参考[模型版本升级](./upgrade_version.md)对模型版本进行升级。** **注意:由于PaddleX代码的持续更新,版本低于1.0.0的模型暂时无法直接用于预测部署,参考[模型版本升级](./upgrade_version.md)对模型版本进行升级。**
## step 3. 将inference模型转换成PaddleLite模型 ## step 2. 将inference模型优化为PaddleLite模型
``` 目前提供了两种方法将Paddle模型优化为PaddleLite模型:
python /path/to/PaddleX/deploy/lite/export_lite.py --model_dir /path/to/inference_model --save_file /path/to/lite_model_name --place place/to/run
- 1.python脚本优化模型,简单上手,目前支持最新的PaddleLite 2.6.1版本
- 2.bin文件优化模型(linux),支持develop版本(Commit Id:11cbd50e),适用于部署`DeepLab模型`的用户。
### 2.1 使用python脚本优化模型
```bash
pip install paddlelite
python /PaddleX/deploy/lite/export_lite.py --model_dir /path/to/inference_model --save_file /path/to/lite_model_name --place place/to/run
``` ```
| 参数 | 说明 | | 参数 | 说明 |
...@@ -31,42 +34,56 @@ python /path/to/PaddleX/deploy/lite/export_lite.py --model_dir /path/to/inferenc ...@@ -31,42 +34,56 @@ python /path/to/PaddleX/deploy/lite/export_lite.py --model_dir /path/to/inferenc
| --save_file | 模型输出的名称,假设为/path/to/lite_model_name, 则输出为路径为/path/to/lite_model_name.nb | | --save_file | 模型输出的名称,假设为/path/to/lite_model_name, 则输出为路径为/path/to/lite_model_name.nb |
| --place | 运行的平台,可选:arm\|opencl\|x86\|npu\|xpu\|rknpu\|apu,安卓部署请选择`arm`| | --place | 运行的平台,可选:arm\|opencl\|x86\|npu\|xpu\|rknpu\|apu,安卓部署请选择`arm`|
## step 4. 移动端(Android)预测 ### 2.3 使用bin文件优化模型(linux)
首先下载并解压: [模型优化工具opt](https://bj.bcebos.com/paddlex/deploy/lite/model_optimize_tool_11cbd50e.tar.gz)
``` bash
./opt --model_file=<model_path> \
--param_file=<param_path> \
--valid_targets=arm \
--optimize_out_type=naive_buffer \
--optimize_out=model_output_name
```
详细的使用方法和参数含义请参考: [使用opt转化模型](https://paddle-lite.readthedocs.io/zh/latest/user_guides/opt/opt_bin.html)
### 4.1 要求 ## step 3. 移动端(Android)预测
### 3.1 要求
- Android Studio 3.4 - Android Studio 3.4
- Android手机或开发版,NPU的功能暂时只在nova5、mate30和mate30 5G上进行了测试,用户可自行尝试其它搭载了麒麟810和990芯片的华为手机(如nova5i pro、mate30 pro、荣耀v30,mate40或p40,且需要将系统更新到最新版); - Android手机或开发
### 4.2 分类Demo ### 3.2 分类Demo
#### 4.2.1 使用 #### 3.2.1 导入工程
- 打开Android Studio,在"Welcome to Android Studio"窗口点击"Open an existing Android Studio project",在弹出的路径选择窗口中进入""目录,然后点击右下角的"Open"按钮,导入工程`/PaddleX/deploy/lite/android/demo` - 打开Android Studio,在"Welcome to Android Studio"窗口点击"Open an existing Android Studio project",在弹出的路径选择窗口中进入`/PaddleX/deploy/lite/android/demo`目录,然后点击右下角的"Open"按钮,导入工程;
- 通过USB连接Android手机或开发板; - 通过USB连接Android手机或开发板;
- 载入工程后,点击菜单栏的Run->Run 'App'按钮,在弹出的"Select Deployment Target"窗口选择已经连接的Android设备,然后点击"OK"按钮; - 载入工程后,点击菜单栏的Run->Run 'App'按钮,在弹出的"Select Deployment Target"窗口选择已经连接的Android设备,然后点击"OK"按钮;
#### 4.2.2 自定义模型 #### 3.2.2 自定义模型
首先根据step1~step3描述,导出Lite模型(.nb)和yml配置文件(注意:导出Lite模型时需指定--place=arm),然后在Android Studio的project视图中: 首先根据step1~step2描述,准备好Lite模型(.nb文件)和yml配置文件(注意:导出Lite模型时需指定--place=arm),然后在Android Studio的project视图中:
- 将paddlex.nb文件拷贝到`/src/main/assets/model/`目录下。 - 将paddlex.nb文件拷贝到`/src/main/assets/model/`目录下。
- 将model.yml文件拷贝到`/src/main/assets/config/`目录下。 - 将model.yml文件拷贝到`/src/main/assets/config/`目录下。
- 根据需要,修改文件`/src/main/res/values/strings.xml`中的`MODEL_PATH_DEFAULT``YAML_PATH_DEFAULT`指定的路径。 - 根据需要,修改文件`/src/main/res/values/strings.xml`中的`MODEL_PATH_DEFAULT``YAML_PATH_DEFAULT`指定的路径。
### 4.3 PaddleX Android SDK介绍 ### 3.3 PaddleX Android SDK介绍
PaddleX Android SDK是PaddleX基于Paddle-Lite开发的安卓端AI推理工具,以PaddleX导出的Yaml配置文件为接口,针对不同的模型实现图片的预处理,后处理,并进行可视化,同时方便开发者集成到业务中。 PaddleX Android SDK是PaddleX基于Paddle-Lite开发的安卓端AI推理工具,以PaddleX导出的Yaml配置文件为接口,针对不同的模型实现图片的预处理,后处理,并进行可视化,开发者可集成到业务中。
该SDK自底向上主要包括:Paddle-Lite推理引擎层,Paddle-Lite接口层以及PaddleX业务层。 该SDK自底向上主要包括:Paddle-Lite推理引擎层,Paddle-Lite接口层以及PaddleX业务层。
- Paddle-Lite推理引擎层,是在Android上编译好的二进制包,只涉及到Kernel 的执行,且可以单独部署,以支持极致的轻量级部署。 - Paddle-Lite推理引擎层,是在Android上编译好的二进制包,只涉及到Kernel 的执行,且可以单独部署,以支持极致的轻量级部署。
- Paddle-Lite接口层,以Java接口封装了底层c++推理库。 - Paddle-Lite接口层,以Java接口封装了底层c++推理库。
- PaddleX业务层,封装了PaddleX导出模型的预处理,推理和后处理,以及可视化,支持PaddleX导出的检测、分割、分类模型。 - PaddleX业务层,封装了PaddleX导出模型的预处理,推理和后处理,以及可视化,支持PaddleX导出的检测、分割、分类模型。
<img width="600" src="./images/paddlex_android_sdk_framework.jpg"/>
#### 4.3.1 SDK安装 <img width="600" src="../images/paddlex_android_sdk_framework.jpg"/>
#### 3.3.1 SDK安装
首先下载[PaddleX Android SDK](https://bj.bcebos.com/paddlex/deploy/lite/paddlex_lite_11cbd50e.tar.gz),并拷贝到android工程目录app/libs/下面,然后为app的build.gradle添加依赖: 首先下载并解压[PaddleX Android SDK](https://bj.bcebos.com/paddlex/deploy/lite/paddlex_lite_11cbd50e.tar.gz),得到paddlex.aar文件,将拷贝到android工程目录app/libs/下面,然后为app的build.gradle添加依赖:
``` ```
dependencies { dependencies {
...@@ -75,7 +92,7 @@ dependencies { ...@@ -75,7 +92,7 @@ dependencies {
``` ```
#### 4.3.2 SDK使用用例 #### 3.3.2 SDK使用用例
``` ```
import com.baidu.paddlex.Predictor; import com.baidu.paddlex.Predictor;
import com.baidu.paddlex.config.ConfigParser; import com.baidu.paddlex.config.ConfigParser;
...@@ -91,7 +108,7 @@ ConfigParser configParser = new ConfigParser(); ...@@ -91,7 +108,7 @@ ConfigParser configParser = new ConfigParser();
// Visualize // Visualize
Visualize visualize = new Visualize(); Visualize visualize = new Visualize();
// image to predict // image to predict
Bitmap predictImage; Mat predictMat;
// initialize // initialize
configParser.init(context, model_path, yaml_path, cpu_thread_num, cpu_power_mode); configParser.init(context, model_path, yaml_path, cpu_thread_num, cpu_power_mode);
...@@ -100,22 +117,22 @@ predictor.init(context, configParser) ...@@ -100,22 +117,22 @@ predictor.init(context, configParser)
// run model // run model
if (predictImage != null && predictor.isLoaded()) { if (predictImage != null && predictor.isLoaded()) {
predictor.setInputImage(predictImage); predictor.setInputMat(predictMat);
runModel(); runModel();
} }
// get result & visualize // get result & visualize
if (configParser.getModelType().equalsIgnoreCase("segmenter")) { if (configParser.getModelType().equalsIgnoreCase("segmenter")) {
SegResult segResult = predictor.getSegResult(); SegResult segResult = predictor.getSegResult();
outputImage = visualize.draw(segResult, predictor.getInputImage(), predictor.getImageBlob()); Mat visualizeMat = visualize.draw(segResult, predictMat, predictor.getImageBlob());
} else if (configParser.getModelType().equalsIgnoreCase("detector")) { } else if (configParser.getModelType().equalsIgnoreCase("detector")) {
DetResult detResult = predictor.getDetResult(); DetResult detResult = predictor.getDetResult();
outputImage = visualize.draw(detResult, predictor.getInputImage()); Mat visualizeMat = visualize.draw(detResult, predictMat);
} else if (configParser.getModelType().equalsIgnoreCase("classifier")) { } else if (configParser.getModelType().equalsIgnoreCase("classifier")) {
ClsResult clsResult = predictor.getClsResult(); ClsResult clsResult = predictor.getClsResult();
} }
``` ```
#### 4.3.3 Result成员变量 #### 3.3.3 Result成员变量
**注意**:Result所有的成员变量以java bean的方式获取。 **注意**:Result所有的成员变量以java bean的方式获取。
...@@ -167,7 +184,7 @@ com.baidu.paddlex.postprocess.SegResult.Mask ...@@ -167,7 +184,7 @@ com.baidu.paddlex.postprocess.SegResult.Mask
> * **labelData** (long[]): 模型预测置信度最高的label,长度为`H$\times\$W$\times\$1 > * **labelData** (long[]): 模型预测置信度最高的label,长度为`H$\times\$W$\times\$1
> * **labelShape** (long[4]): labelData的shape信息,[1,H,W,1] > * **labelShape** (long[4]): labelData的shape信息,[1,H,W,1]
#### 4.3.4 SDK二次开发 #### 3.3.4 SDK二次开发
- 打开Android Studio新建项目(或加载已有项目)。点击菜单File->New->Import Module,导入工程`/PaddleX/deploy/lite/android/sdk`, Project视图会新增名为sdk的module - 打开Android Studio新建项目(或加载已有项目)。点击菜单File->New->Import Module,导入工程`/PaddleX/deploy/lite/android/sdk`, Project视图会新增名为sdk的module
- 在app的build.grade里面添加依赖: - 在app的build.grade里面添加依赖:
...@@ -176,9 +193,5 @@ com.baidu.paddlex.postprocess.SegResult.Mask ...@@ -176,9 +193,5 @@ com.baidu.paddlex.postprocess.SegResult.Mask
implementation project(':sdk') implementation project(':sdk')
} }
``` ```
- 源代码位于/sdk/main/java/下,可进行二次开发。
- SDK和Paddle-Lite是解耦的关系,如有需求,可手动升级Paddle-Lite的预测库版本: - 源代码位于sdk/main/java/下,修改源码进行二次开发后,点击菜单栏的Build->Run 'sdk'按钮可编译生成aar,文件位于sdk/build/outputs/aar/路径下。
> - 参考[Paddle-Lite文档](https://paddle-lite.readthedocs.io/zh/latest/index.html),编译Android预测库,编译最终产物位于 build.lite.xxx.xxx.xxx 下的 inference_lite_lib.xxx.xxx
> - 替换jar文件:将生成的build.lite.android.xxx.gcc/inference_lite_lib.android.xxx/java/jar/PaddlePredictor.jar替换sdk中的sdk/libs/PaddlePredictor.jar
> - 替换arm64-v8a jni库文件:将生成build.lite.android.armv8.gcc/inference_lite_lib.android.armv8/java/so/libpaddle_lite_jni.so库替换sdk中的sdk/src/main/jniLibs/arm64-v8a/libpaddle_lite_jni.so
> - 替换armeabi-v7a jni库文件:将生成的build.lite.android.armv7.gcc/inference_lite_lib.android.armv7/java/so/libpaddle_lite_jni.so库替换sdk中的sdk/src/main/jniLibs/armeabi-v7a/libpaddle_lite_jni.so
## 模型量化 # 模型压缩
为了更好地满足端侧部署场景下,低内存带宽、低功耗、低计算资源占用以及低模型存储等需求,PaddleX通过集成PaddleSlim实现模型量化和裁剪,可提升PaddleLite端侧部署性能。
## 模型量化
### 原理介绍 ### 原理介绍
为了满足低内存带宽、低功耗、低计算资源占用以及低模型存储等需求,定点量化被提出。为此我们提供了训练后量化,该量化使用KL散度确定量化比例因子,将FP32模型转成INT8模型,且不需要重新训练,可以快速得到量化模型。 定点量化使用更少的比特数(如8-bit、3-bit、2-bit等)表示神经网络的权重和激活值,从而加速模型推理速度。PaddleX提供了训练后量化技术,其原理可参见[训练后量化原理](https://paddlepaddle.github.io/PaddleSlim/algo/algo.html#id14),该量化使用KL散度确定量化比例因子,将FP32模型转成INT8模型,且不需要重新训练,可以快速得到量化模型。
### 使用PaddleX量化模型 ### 使用PaddleX量化模型
PaddleX提供了`export_quant_model`接口,让用户以接口的形式完成模型以post_quantization方式量化并导出。点击查看[量化接口使用文档](../apis/slim.md) PaddleX提供了`export_quant_model`接口,让用户以接口的形式完成模型以post_quantization方式量化并导出。点击查看[量化接口使用文档](../../apis/slim.md)
### 量化性能对比 ### 量化性能对比
模型量化后的性能对比指标请查阅[PaddleSlim模型库](https://paddlepaddle.github.io/PaddleSlim/model_zoo.html) 模型量化后的性能对比指标请查阅[PaddleSlim模型库](https://paddlepaddle.github.io/PaddleSlim/model_zoo.html)
## 模型裁剪 ## 模型裁剪
### 原理介绍 ### 原理介绍
模型裁剪用于减小模型的计算量和体积,可以加快模型部署后的预测速度,是一种减小模型大小和降低模型计算复杂度的常用方式,通过裁剪卷积层中Kernel输出通道的大小及其关联层参数大小来实现,其关联裁剪的原理可参见[PaddleSlim相关文档](https://paddlepaddle.github.io/PaddleSlim/algo/algo.html#id16)**一般而言,在同等模型精度前提下,数据复杂度越低,模型可以被裁剪的比例就越高** 模型裁剪通过裁剪卷积层中Kernel输出通道的大小及其关联层参数大小,来减小模型大小和降低模型计算复杂度,可以加快模型部署后的预测速度,其关联裁剪的原理可参见[PaddleSlim相关文档](https://paddlepaddle.github.io/PaddleSlim/algo/algo.html#id16)**一般而言,在同等模型精度前提下,数据复杂度越低,模型可以被裁剪的比例就越高**
### 裁剪方法 ### 裁剪方法
PaddleX提供了两种方式: PaddleX提供了两种方式:
...@@ -34,10 +35,10 @@ PaddleX提供了两种方式: ...@@ -34,10 +35,10 @@ PaddleX提供了两种方式:
> 注:各模型内置的裁剪方案分别依据的数据集为: 图像分类——ImageNet数据集、目标检测——PascalVOC数据集、语义分割——CityScape数据集 > 注:各模型内置的裁剪方案分别依据的数据集为: 图像分类——ImageNet数据集、目标检测——PascalVOC数据集、语义分割——CityScape数据集
### 裁剪实验 ### 裁剪实验
基于上述两种方案,我们在PaddleX上使用样例数据进行了实验,在Tesla P40上实验指标如下所示, 基于上述两种方案,我们在PaddleX上使用样例数据进行了实验,在Tesla P40上实验指标如下所示,使用方法见[使用教程-模型压缩](../../../../tutorials/compress/README.md)
#### 图像分类 #### 图像分类
实验背景:使用MobileNetV2模型,数据集为蔬菜分类示例数据,见[使用教程-模型压缩-图像分类](../../../../tutorials/compress/classification.md) 实验背景:使用MobileNetV2模型,数据集为蔬菜分类示例数据
| 模型 | 裁剪情况 | 模型大小 | Top1准确率(%) |GPU预测速度 | CPU预测速度 | | 模型 | 裁剪情况 | 模型大小 | Top1准确率(%) |GPU预测速度 | CPU预测速度 |
| :-----| :--------| :-------- | :---------- |:---------- |:----------| | :-----| :--------| :-------- | :---------- |:---------- |:----------|
...@@ -46,8 +47,7 @@ PaddleX提供了两种方式: ...@@ -46,8 +47,7 @@ PaddleX提供了两种方式:
|MobileNetV2 | 方案二(eval_metric_loss=0.10) | 6.0M | 99.58 |5.42ms |29.06ms | |MobileNetV2 | 方案二(eval_metric_loss=0.10) | 6.0M | 99.58 |5.42ms |29.06ms |
#### 目标检测 #### 目标检测
实验背景:使用YOLOv3-MobileNetV1模型,数据集为昆虫检测示例数据,见[使用教程-模型压缩-目标检测](../../../../tutorials/compress/detection.md) 实验背景:使用YOLOv3-MobileNetV1模型,数据集为昆虫检测示例数据
| 模型 | 裁剪情况 | 模型大小 | MAP(%) |GPU预测速度 | CPU预测速度 | | 模型 | 裁剪情况 | 模型大小 | MAP(%) |GPU预测速度 | CPU预测速度 |
| :-----| :--------| :-------- | :---------- |:---------- | :---------| | :-----| :--------| :-------- | :---------- |:---------- | :---------|
...@@ -56,7 +56,7 @@ PaddleX提供了两种方式: ...@@ -56,7 +56,7 @@ PaddleX提供了两种方式:
|YOLOv3-MobileNetV1 | 方案二(eval_metric_loss=0.05) | 29M | 50.27| 9.43ms |360.46ms | |YOLOv3-MobileNetV1 | 方案二(eval_metric_loss=0.05) | 29M | 50.27| 9.43ms |360.46ms |
#### 语义分割 #### 语义分割
实验背景:使用UNet模型,数据集为视盘分割示例数据, 见[使用教程-模型压缩-语义分割](../../../../tutorials/compress/segmentation.md) 实验背景:使用UNet模型,数据集为视盘分割示例数据
| 模型 | 裁剪情况 | 模型大小 | mIOU(%) |GPU预测速度 | CPU预测速度 | | 模型 | 裁剪情况 | 模型大小 | mIOU(%) |GPU预测速度 | CPU预测速度 |
| :-----| :--------| :-------- | :---------- |:---------- | :---------| | :-----| :--------| :-------- | :---------- |:---------- | :---------|
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册