提交 735f40fa 编写于 作者: L lvmingfu

update files in lite

上级 88664361
# Glossary
# Glossary
<a href="https://gitee.com/mindspore/docs/blob/master/lite/docs/source_en/glossary.md" target="_blank"><img src="./_static/logo_source.png"></a>
| Acronym and Abbreviation | Description |
| ----- | ----- |
| MindSpore Lite | MindSpore AI engine is applied to the intelligent terminal and resource constrained scenes on the edge side. |
| MindSpore Micro | MindSpore AI engine with smaller package size for IOT devices. |
| GHLO | Graph high-level optimization. |
| GLLO | Graph low-level optimization. |
| RT | Runtime. |
<a href="https://gitee.com/mindspore/docs/blob/master/lite/docs/source_en/glossary.md" target="_blank"><img src="../_static/logo_source.png"></a>
......@@ -11,4 +11,5 @@ MindSpore Lite Documentation
:maxdepth: 1
architecture
operator_list
glossary
此差异已折叠。
# 术语
# 术语
<a href="https://gitee.com/mindspore/docs/blob/master/lite/docs/source_zh_cn/glossary.md" target="_blank"><img src="../_static/logo_source.png"></a>
<a href="https://gitee.com/mindspore/docs/blob/master/lite/docs/source_zh_cn/glossary.md" target="_blank"><img src="./_static/logo_source.png"></a>
| 术语/缩略语 | 说明 |
| ----- | ----- |
......
......@@ -11,4 +11,6 @@ MindSpore端侧文档
:maxdepth: 1
architecture
roadmap
operator_list
glossary
\ No newline at end of file
此差异已折叠。
# RoadMap
<a href="https://gitee.com/mindspore/docs/blob/master/lite/docs/source_zh_cn/roadmap.md" target="_blank"><img src="./_static/logo_source.png"></a>
1. 增加更多的FP16、INT8和UINT8 CPU算子;
2. 增加更多的openCL、openGL、vulkan和metal GPU算子;
3. 增加控制流算子支持;
4. 增加NPU支持;
5. 增加部署在IoT设备的推理框架;
6. 增加图像分割、文字识别、人脸检测等预制模型;
7. 增加Lite的图像分割、文字识别、人脸检测等预置样例;
8. 增加Micro的样例;
9. 端侧训练支持;
10. pipeline数据处理丰富;
11. 模型转换工具支持windows和MAC。
\ No newline at end of file
......@@ -12,7 +12,7 @@ MindSpore端侧教程
:caption: 快速入门
deploy
quick_start/quick_start_lite
quick_start/quick_start
.. toctree::
:glob:
......@@ -20,4 +20,7 @@ MindSpore端侧教程
:caption: 使用指南
use/converter_tool
use/tools
use/runtime
use/benchmark_tool
use/timeprofiler_tool
use/post_training_quantization
# 快速入门(Lite)
<!-- TOC -->
- [快速入门(Lite)](#快速入门lite)
- [概述](#概述)
- [选择模型](#选择模型)
- [转换模型](#转换模型)
- [部署应用](#部署应用)
- [运行依赖](#运行依赖)
- [构建与运行](#构建与运行)
- [示例程序详细说明](#示例程序详细说明)
- [示例程序结构](#示例程序结构)
- [配置MindSpore Lite依赖项](#配置mindspore-lite依赖项)
- [下载及部署模型文件](#下载及部署模型文件)
- [编写端侧推理代码](#编写端侧推理代码)
<!-- /TOC -->
## 概述
我们推荐你从端侧Android图像分类demo入手,了解MindSpore Lite应用工程的构建、依赖项配置以及相关API的使用。
本教程基于MindSpore团队提供的Android“端侧图像分类”示例程序,演示了端侧部署的流程。
1. 选择图像分类模型。
2. 将模型转换成MindSpore Lite模型格式。
3. 在端侧使用MindSpore Lite推理模型。详细说明如何在端侧利用MindSpore Lite C++ API(Android JNI)和MindSpore Lite图像分类模型完成端侧推理,实现对设备摄像头捕获的内容进行分类,并在APP图像预览界面中,显示出最可能的分类结果。
> 你可以在这里找到[Android图像分类模型](https://download.mindspore.cn/model_zoo/official/lite/mobilenetv2_openimage_lite)和[示例代码](https://gitee.com/mindspore/mindspore/tree/master/model_zoo/official/lite/image_classif)。
## 选择模型
MindSpore团队提供了一系列预置终端模型,你可以在应用程序中使用这些预置的终端模型。
MindSpore Model Zoo中图像分类模型可[在此下载](#TODO)
同时,你也可以使用预置模型做迁移学习,以实现自己的图像分类任务,操作流程参见[重训练章节](https://www.mindspore.cn/tutorial/zh-CN/master/use/saving_and_loading_model_parameters.html#id6)
## 转换模型
如果你需要对MindSpore提供的模型进行重训,重训完成后,需要将模型导出为[.mindir格式](https://www.mindspore.cn/tutorial/zh-CN/master/use/saving_and_loading_model_parameters.html#mindir)。然后使用MindSpore Lite[模型转换工具](https://www.mindspore.cn/lite/tutorial/zh-CN/master/use/converter.html)将.mindir模型转换成.ms格式。
以MindSpore MobilenetV2模型为例,如下脚本将其转换为MindSpore Lite模型用于端侧推理。
```bash
./converter_lite --fmk=MS --modelFile=mobilenet_v2.mindir --outputFile=mobilenet_v2.ms
```
## 部署应用
接下来介绍如何构建和执行mindspore Lite端侧图像分类任务。
### 运行依赖
- Android Studio >= 3.2 (推荐4.0以上版本)
- NDK 21.3
- CMake
- Android SDK >= 26
- OpenCV >= 4.0.0 (本示例代码已包含)
### 构建与运行
1. 在Android Studio中加载本示例源码,并安装相应的SDK(指定SDK版本后,由Android Studio自动安装)。
![start_home](../images/lite_quick_start_home.png)
启动Android Studio后,点击`File->Settings->System Settings->Android SDK`,勾选相应的SDK。如下图所示,勾选后,点击`OK`,Android Studio即可自动安装SDK。
![start_sdk](../images/lite_quick_start_sdk.png)
(可选)若安装时出现NDK版本问题,可手动下载相应的[NDK版本](https://developer.android.com/ndk/downloads?hl=zh-cn)(本示例代码使用的NDK版本为21.3),并在`Project Structure`的`Android NDK location`设置中指定SDK的位置。
![project_structure](../images/lite_quick_start_project_structure.png)
2. 连接Android设备,运行图像分类应用程序。
通过USB连接Android设备调试,点击`Run 'app'`即可在你的设备上运行本示例项目。
![run_app](../images/lite_quick_start_run_app.PNG)
Android Studio连接设备调试操作,可参考<https://developer.android.com/studio/run/device?hl=zh-cn>。
3. 在Android设备上,点击“继续安装”,安装完即可查看到设备摄像头捕获的内容和推理结果。
![install](../images/lite_quick_start_install.jpg)
如下图所示,成功识别出图中内容是键盘和鼠标。
![result](../images/lite_quick_start_app_result.jpg)
## 示例程序详细说明
本端侧图像分类Android示例程序分为JAVA层和JNI层,其中,JAVA层主要通过Android Camera 2 API实现摄像头获取图像帧,以及相应的图像处理等功能;JNI层在[Runtime](https://www.mindspore.cn/tutorial/zh-CN/master/use/lite_runtime.html)中完成模型推理的过程。
> 此处详细说明示例程序的JNI层实现,JAVA层运用Android Camera 2 API实现开启设备摄像头以及图像帧处理等功能,需读者具备一定的Android开发基础知识。
### 示例程序结构
```
app
|
├── libs # 存放MindSpore Lite依赖的库文件
│ └── arm64-v8a
│ ├── libopencv_java4.so
│ └── libmindspore-lite.so
├── opencv # opencv 相关依赖文件
│ └── ...
|
├── src/main
│ ├── assets # 资源文件
| | └── model.ms # 存放模型文件
│ |
│ ├── cpp # 模型加载和预测主要逻辑封装类
| | ├── include # 存放MindSpore调用相关的头文件
| | | └── ...
│ | |
| | ├── MindSporeNetnative.cpp # MindSpore调用相关的JNI方法
│ | └── MindSporeNetnative.h # 头文件
│ |
│ ├── java # java层应用代码
│ │ └── com.huawei.himindsporedemo
│ │ ├── gallery.classify # 图像处理及MindSpore JNI调用相关实现
│ │ │ └── ...
│ │ └── obejctdetect # 开启摄像头及绘制相关实现
│ │ └── ...
│ │
│ ├── res # 存放Android相关的资源文件
│ └── AndroidManifest.xml # Android配置文件
├── CMakeList.txt # cmake编译入口文件
├── build.gradle # 其他Android配置文件
└── ...
```
### 配置MindSpore Lite依赖项
Android JNI层调用MindSpore C++ API时,需要相关库文件支持。可通过MindSpore Lite[源码编译](https://www.mindspore.cn/lite/docs/zh-CN/master/deploy.html)生成`libmindspore-lite.so`库文件,或直接下载MindSpore Lite提供的已编译完成的AMR64、ARM32、x86等[软件包](#TODO)
在Android Studio中将编译完成的`libmindspore-lite.so`库文件(可包含多个兼容架构),分别放置在APP工程的`app/libs/ARM64-V8a`(ARM64)或`app/libs/armeabi-v7a`(ARM32)目录下,并在应用的`build.gradle`文件中配置CMake编译支持,以及`arm64-v8a``armeabi-v7a`的编译支持。  
```
android{
defaultConfig{
externalNativeBuild{
cmake{
arguments "-DANDROID_STL=c++_shared"
}
}
ndk{
abiFilters'armeabi-v7a', 'arm64-v8a'
}
}
}
```
`app/CMakeLists.txt`文件中建立`.so``.a`库文件链接,如下所示。
```
# Set MindSpore Lite Dependencies.
include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/include/MindSpore)
add_library(mindspore-lite SHARED IMPORTED )
set_target_properties(mindspore-lite PROPERTIES
IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/libs/libmindspore-lite.so")
# Set OpenCV Dependecies.
include_directories(${CMAKE_SOURCE_DIR}/opencv/sdk/native/jni/include)
add_library(lib-opencv SHARED IMPORTED )
set_target_properties(lib-opencv PROPERTIES
IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/libs/libopencv_java4.so")
# Link target library.
target_link_libraries(
...
mindspore-lite
lib-opencv
...
)
```
### 下载及部署模型文件
从MindSpore Model Hub中下载模型文件,本示例程序中使用的终端图像分类模型文件为`mobilenet_v2.ms`,放置在`app/src/main/assets`工程目录下。
### 编写端侧推理代码
在JNI层调用MindSpore Lite C++ API实现端测推理。
推理代码流程如下,完整代码请参见`src/cpp/MindSporeNetnative.cpp`
1. 加载MindSpore Lite模型文件,构建上下文、会话以及用于推理的计算图。
- 加载模型文件:创建并配置用于模型推理的上下文
```cpp
// Buffer is the model data passed in by the Java layer
jlong bufferLen = env->GetDirectBufferCapacity(buffer);
char *modelBuffer = CreateLocalModelBuffer(env, buffer);
```
- 创建会话
```cpp
void **labelEnv = new void *;
MSNetWork *labelNet = new MSNetWork;
*labelEnv = labelNet;
// Create context.
lite::Context *context = new lite::Context;
context->cpu_bind_mode_ = lite::NO_BIND;
context->device_ctx_.type = lite::DT_CPU;
context->thread_num_ = numThread; //Specify the number of threads to run inference
// Create the mindspore session.
labelNet->CreateSessionMS(modelBuffer, bufferLen, "device label", context);
delete(context);
```
- 加载模型文件并构建用于推理的计算图
```cpp
void MSNetWork::CreateSessionMS(char* modelBuffer, size_t bufferLen, std::string name, mindspore::lite::Context* ctx)
{
CreateSession(modelBuffer, bufferLen, ctx);
session = mindspore::session::LiteSession::CreateSession(ctx);
auto model = mindspore::lite::Model::Import(modelBuffer, bufferLen);
int ret = session->CompileGraph(model); // Compile Graph
}
```
2. 将输入图片转换为传入MindSpore模型的Tensor格式。
将待检测图片数据转换为输入MindSpore模型的Tensor。
```cpp
// Convert the Bitmap image passed in from the JAVA layer to Mat for OpenCV processing
BitmapToMat(env, srcBitmap, matImageSrc);
// Processing such as zooming the picture size.
matImgPreprocessed = PreProcessImageData(matImageSrc);
ImgDims inputDims;
inputDims.channel = matImgPreprocessed.channels();
inputDims.width = matImgPreprocessed.cols;
inputDims.height = matImgPreprocessed.rows;
float *dataHWC = new float[inputDims.channel * inputDims.width * inputDims.height]
// Copy the image data to be detected to the dataHWC array.
// The dataHWC[image_size] array here is the intermediate variable of the input MindSpore model tensor.
float *ptrTmp = reinterpret_cast<float *>(matImgPreprocessed.data);
for(int i = 0; i < inputDims.channel * inputDims.width * inputDims.height; i++){
dataHWC[i] = ptrTmp[i];
}
// Assign dataHWC[image_size] to the input tensor variable.
auto msInputs = mSession->GetInputs();
auto inTensor = msInputs.front();
memcpy(inTensor->MutableData(), dataHWC,
inputDims.channel * inputDims.width * inputDims.height * sizeof(float));
delete[] (dataHWC);
```
3. 对输入Tensor按照模型进行推理,获取输出Tensor,并进行后处理。
- 图执行,端测推理。
```cpp
// After the model and image tensor data is loaded, run inference.
auto status = mSession->RunGraph();
```
- 获取输出数据。
```cpp
auto msOutputs = mSession->GetOutputs();
std::string retStr = ProcessRunnetResult(msOutputs, ret);
```
- 输出数据的后续处理。
```cpp
std::string ProcessRunnetResult(std::unordered_map<std::string,
std::vector<mindspore::tensor::MSTensor *>> msOutputs,
int runnetRet) {
// Get model output results.
std::unordered_map<std::string, std::vector<mindspore::tensor::MSTensor *>>::iterator iter;
iter = msOutputs.begin();
auto brach1_string = iter->first;
auto branch1_tensor = iter->second;
int OUTPUTS_LEN = branch1_tensor[0]->ElementsNum();
MS_PRINT("OUTPUTS_LEN:%d", OUTPUTS_LEN);
float *temp_scores = static_cast<float * >(branch1_tensor[0]->MutableData());
float scores[RET_CATEGORY_SUM];
for (int i = 0; i < RET_CATEGORY_SUM; ++i) {
if (temp_scores[i] > 0.5){
MS_PRINT("MindSpore scores[%d] : [%f]", i, temp_scores[i]);
}
scores[i] = temp_scores[i];
}
// Converted to text information that needs to be displayed in the APP.
std::string retStr = "";
if (runnetRet == 0) {
for (int i = 0; i < RET_CATEGORY_SUM; ++i) {
if (scores[i] > 0.3){
retStr += g_labels_name_map[i];
retStr += ":";
std::string score_str = std::to_string(scores[i]);
retStr += score_str;
retStr += ";";
}
}
} else {
MS_PRINT("MindSpore run net failed!");
for (int i = 0; i < RET_CATEGORY_SUM; ++i) {
retStr += " :0.0;";
}
}
return retStr;
}
```
# 快速入门(Lite)
<!-- TOC -->
- [快速入门(Lite)](#快速入门lite)
<!-- /TOC -->
<a href="https://gitee.com/mindspore/docs/blob/master/lite/tutorials/source_zh_cn/quick_start/quick_start_lite.md" target="_blank"><img src="../_static/logo_source.png"></a>
# 训练后量化
<!-- TOC -->
- [训练后量化](#训练后量化)
- [概述](#概述)
- [参数说明](#参数说明)
- [使用示例](#使用示例)
<!-- /TOC -->
<a href="https://gitee.com/mindspore/docs/blob/master/lite/tutorials/source_zh_cn/use/post_training_quantization.md" target="_blank"><img src="../_static/logo_source.png"></a>
## 概述
对于已经训练好的`float32`模型,通过训练后量化将模型转为`int8`模型,不仅能减小模型大小,而且能显著提高推理性能。在MindSpore端侧框架中,这部分功能集成在模型转换工具`conveter_lite`中,通过增加命令行参数,便能够转换得到量化后模型。
目前训练后量化属于alpha阶段(支持部分网络,不支持多输入模型),正在持续完善中。
```
./converter_lite --fmk=ModelType --modelFile=ModelFilePath --outputFile=ConvertedModelPath --quantType=PostTraining --config_file=config.cfg
```
## 参数说明
| 参数 | 属性 | 功能描述 | 参数类型 | 默认值 | 取值范围 |
| -------- | ------- | ----- | ----- |----- | ----- |
| --quantType | 必选 | 设置为PostTraining,启用训练后量化 | String | - | 必须设置为PostTraining |
| --config_file | 必选 | 校准数据集配置文件路径 | String | - | - |
为了计算激活值的量化参数,用户需要提供校准数据集。校准数据集最好来自真实推理场景,能表征模型的实际输入情况,数量在100个左右。
校准数据集配置文件采用`key=value`的方式定义相关参数,需要配置的`key`如下:
| 参数名 | 属性 | 功能描述 | 参数类型 | 默认值 | 取值范围 |
| -------- | ------- | ----- | ----- | ----- | ----- |
| image_path | 必选 | 存放校准数据集的目录 | String | - | 该目录存放可直接用于执行推理的输入数据。由于目前框架还不支持数据预处理,所有数据必须事先完成所需的转换,使得它们满足推理的输入要求。 |
| batch_count | 可选 | 使用的输入数目 | Integer | 1000 | 大于0 |
| method_x | 可选 | 网络层输入输出数据量化算法 | String | KL | KL,MAX_MIN。 KL: 基于[KL散度](http://on-demand.gputechconf.com/gtc/2017/presentation/s7310-8-bit-inference-with-tensorrt.pdf)对数据范围作量化校准; MAX_MIN:基于最大值、最小值计算数据的量化参数。 在模型以及数据集比较较简单的情况下,推荐使用MAX_MIN |
## 使用示例
1. 正确编译出`converter_lite`可执行文件。
2. 准备校准数据集,假设存放在`/dir/images`目录,编写配置文件`config.cfg`,内容如下:
```
image_path=/dir/images
batch_count=100
method_x=MAX_MIN
```
校准数据集可以选择测试数据集的子集,要求`/dir/images`目录下存放的每个文件均是预处理好的输入数据,每个文件都可以直接用于推理的输入。
3. 以TensorFlow Lite模型mnist.tflite为例,执行带训练后量化的模型转换命令:
```
./converter_lite --fmk=TFLITE --modelFile=mnist.tflite --outputFile=mnist_quant --quantType=PostTraining --config_file=config.cfg
```
4. 上述命令执行成功后,便可得到量化后的模型mnist_quant.ms,通常量化后的模型大小会下降到FP32模型的1/4。
## 部分模型精度结果
| 模型 | 测试数据集 | method_x | FP32模型精度 | 训练后量化精度 | 说明 |
| -------- | ------- | ----- | ----- | ----- | ----- |
| mnist.tflite | [MNIST](http://yann.lecun.com/exdb/mnist/) | MAX_MIN | 97.61% | 97.83% | 校准数据集选择MNIST Test数据集的前100张 |
| mobilenet_v1.tflite | [MNIST](http://yann.lecun.com/exdb/mnist/) | MAX_MIN | 98.36% | 98.40% | 校准数据集选择MNIST Test数据集的前100张 |
其他工具
==========
.. toctree::
:maxdepth: 1
benchmark_tool
timeprofiler_tool
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册