Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
MindSpore
docs
提交
c31c44d7
D
docs
项目概览
MindSpore
/
docs
通知
4
Star
2
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
docs
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
c31c44d7
编写于
8月 29, 2020
作者:
L
lvmingfu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
modify on_device_inference link in files
上级
8da73d3d
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
1 addition
and
360 deletion
+1
-360
tutorials/source_zh_cn/advanced_use/images/on_device_inference_frame.jpg
...e_zh_cn/advanced_use/images/on_device_inference_frame.jpg
+0
-0
tutorials/source_zh_cn/advanced_use/images/side_infer_process.eddx
.../source_zh_cn/advanced_use/images/side_infer_process.eddx
+0
-0
tutorials/source_zh_cn/advanced_use/images/side_infer_process.jpg
...s/source_zh_cn/advanced_use/images/side_infer_process.jpg
+0
-0
tutorials/source_zh_cn/advanced_use/on_device_inference.md
tutorials/source_zh_cn/advanced_use/on_device_inference.md
+0
-359
tutorials/source_zh_cn/use/multi_platform_inference.md
tutorials/source_zh_cn/use/multi_platform_inference.md
+1
-1
未找到文件。
tutorials/source_zh_cn/advanced_use/images/on_device_inference_frame.jpg
已删除
100644 → 0
浏览文件 @
8da73d3d
235.9 KB
tutorials/source_zh_cn/advanced_use/images/side_infer_process.eddx
已删除
100644 → 0
浏览文件 @
8da73d3d
文件已删除
tutorials/source_zh_cn/advanced_use/images/side_infer_process.jpg
已删除
100644 → 0
浏览文件 @
8da73d3d
96.4 KB
tutorials/source_zh_cn/advanced_use/on_device_inference.md
已删除
100644 → 0
浏览文件 @
8da73d3d
# 端侧推理
<!-- TOC -->
-
[
端侧推理
](
#端侧推理
)
-
[
概述
](
#概述
)
-
[
编译方法
](
#编译方法
)
-
[
端侧推理使用
](
#端侧推理使用
)
-
[
生成端侧模型文件
](
#生成端侧模型文件
)
-
[
在端侧实现推理
](
#在端侧实现推理
)
<!-- /TOC -->
<a
href=
"https://gitee.com/mindspore/docs/blob/master/tutorials/source_zh_cn/advanced_use/on_device_inference.md"
target=
"_blank"
><img
src=
"../_static/logo_source.png"
></a>
## 概述
MindSpore Lite是一个轻量级的深度神经网络推理引擎,提供了将MindSpore训练出的模型或第三方模型TensorFlow Lite、ONNX、Caffe在端侧进行推理的功能。本教程介绍MindSpore Lite的编译方法和对MindSpore训练出的模型进行推理的使用指南。
![](
./images/on_device_inference_frame.jpg
)
图1:端侧推理架构图
MindSpore Lite的框架主要由Frontend、IR、Backend、Lite RT、Micro构成。
-
Frontend:用于模型的生成,用户可以使用模型构建接口构建模型,或者将第三方模型转化为MindSpore模型。
-
IR:包含MindSpore的Tensor定义、算子原型定义、图定义,后端优化基于IR进行。
-
Backend:包含图优化,量化等功能。图优化分为两部分:high-level优化与硬件无关,如算子融合、常量折叠等,low-level优化与硬件相关;量化,包括权重量化、激活值量化等多种训练后量化手段。
-
Lite RT:推理运行时,由session提供对外接口,kernel registry为算子注册器,scheduler为算子异构调度器,executor为算子执行器。Lite RT与Micro共享底层的算子库、内存分配、运行时线程池、并行原语等基础设施层。
-
Micro:Code-Gen根据模型生成.c文件,底层算子库等基础设施与Lite RT共用。
## 编译方法
用户需要自行编译,这里介绍在Ubuntu环境下进行交叉编译的具体步骤。
环境要求如下:
-
硬件要求
-
内存1GB以上
-
硬盘空间10GB以上
-
系统要求
-
系统环境支持Linux: Ubuntu = 18.04.02LTS
-
软件依赖
-
[
cmake
](
https://cmake.org/download/
)
>= 3.14.1
-
[
GCC
](
https://gcc.gnu.org/releases.html
)
>= 5.4
-
[
Android_NDK r20b
](
https://dl.google.com/android/repository/android-ndk-r20b-linux-x86_64.zip
)
使用MindSpore Lite转换工具,需要添加更多的依赖项:
-
[
autoconf
](
http://ftp.gnu.org/gnu/autoconf/
)
>= 2.69
-
[
libtool
](
https://www.gnu.org/software/libtool/
)
>= 2.4.6
-
[
libressl
](
http://www.libressl.org/
)
>= 3.1.3
-
[
automake
](
https://www.gnu.org/software/automake/
)
>= 1.11.6
-
[
libevent
](
https://libevent.org
)
>= 2.0
-
[
m4
](
https://www.gnu.org/software/m4/m4.html
)
>= 1.4.18
-
[
openssl
](
https://www.openssl.org/
)
>= 1.1.1
编译步骤如下:
1.
从代码仓下载源码。
```
bash
git clone https://gitee.com/mindspore/mindspore.git
```
2.
在源码根目录下,执行如下命令编译MindSpore Lite。
-
编译转换工具:
```
bash
bash build.sh
-I
x86_64
```
-
编译推理框架:
设定ANDROID_NDK路径:
```
bash
export
ANDROID_NDK
={
$NDK_PATH
}
/android-ndk-r20b
```
用户需根据设备情况,可选择
`arm64`
:
```
bash
bash build.sh
-I
arm64
```
或
`arm32`
:
```
bash
bash build.sh
-I
arm32
```
3.
进入源码的
`mindspore/output`
目录,获取编译结果
`mindspore-lite-0.7.0-converter-ubuntu.tar.gz`
。执行解压缩命令,获得编译后的工具包
`mindspore-lite-0.7.0`
:
```
bash
tar
-xvf
mindspore-lite-0.7.0-converter-ubuntu.tar.gz
```
## 端侧推理使用
在APP的APK工程中使用MindSpore进行模型推理前,需要对输入进行必要的前处理,比如将图片转换成MindSpore推理要求的
`tensor`
格式、对图片进行
`resize`
等处理。在MindSpore完成模型推理后,对模型推理的结果进行后处理,并将处理的输出发送给APP应用。
本章主要描述用户如何使用MindSpore进行模型推理,APK工程的搭建和模型推理的前后处理,不在此列举。
MindSpore进行端侧模型推理的步骤如下。
### 生成端侧模型文件
1.
加载训练完毕所生成的CheckPoint文件至定义好的网络中。
```
python
param_dict
=
load_checkpoint
(
ckpt_file_name
=
ckpt_file_path
)
load_param_into_net
(
net
,
param_dict
)
```
2.
调用
`export`
接口,导出模型文件(
`.mindir`
)。
```
python
export
(
net
,
input_data
,
file_name
=
"./lenet.mindir"
,
file_format
=
'MINDIR'
)
```
以LeNet网络为例,生成的端侧模型文件为`lenet.mindir`,完整示例代码`lenet.py`如下。
```python
import os
import numpy as np
import mindspore.nn as nn
import mindspore.ops.operations as P
import mindspore.context as context
from mindspore.common.tensor import Tensor
from mindspore.train.serialization import export, load_checkpoint, load_param_into_net
class LeNet(nn.Cell):
def __init__(self):
super(LeNet, self).__init__()
self.relu = P.ReLU()
self.batch_size = 32
self.conv1 = nn.Conv2d(1, 6, kernel_size=5, stride=1, padding=0, has_bias=False, pad_mode='valid')
self.conv2 = nn.Conv2d(6, 16, kernel_size=5, stride=1, padding=0, has_bias=False, pad_mode='valid')
self.pool = nn.MaxPool2d(kernel_size=2, stride=2)
self.reshape = P.Reshape()
self.fc1 = nn.Dense(400, 120)
self.fc2 = nn.Dense(120, 84)
self.fc3 = nn.Dense(84, 10)
def construct(self, input_x):
output = self.conv1(input_x)
output = self.relu(output)
output = self.pool(output)
output = self.conv2(output)
output = self.relu(output)
output = self.pool(output)
output = self.reshape(output, (self.batch_size, -1))
output = self.fc1(output)
output = self.relu(output)
output = self.fc2(output)
output = self.relu(output)
output = self.fc3(output)
return output
if __name__ == '__main__':
context.set_context(mode=context.GRAPH_MODE, device_target="Ascend")
seed = 0
np.random.seed(seed)
origin_data = np.random.uniform(low=0, high=255, size=(32, 1, 32, 32)).astype(np.float32)
origin_data.tofile("lenet.bin")
input_data = Tensor(origin_data)
net = LeNet()
ckpt_file_path = "path_to/lenet.ckpt"
is_ckpt_exist = os.path.exists(ckpt_file_path)
if is_ckpt_exist:
param_dict = load_checkpoint(ckpt_file_name=ckpt_file_path)
load_param_into_net(net, param_dict)
export(net, input_data, file_name="./lenet.mindir", file_format='MINDIR')
print("export model success.")
else:
print("checkpoint file does not exist.")
```
3.
在
`mindspore/output/mindspore-lite-0.7.0/converter`
路径下,调用MindSpore端侧转换工具
`converter_lite`
,将模型文件(
`.mindir`
)转换为端侧模型文件(
`.ms`
)。
```
./converter_lite --fmk=MS --modelFile=./lenet.mindir --outputFile=lenet
```
结果显示为:
```
INFO [converter/converter.cc:146] Runconverter] CONVERTER RESULT: SUCCESS!
```
这表示已经成功将模型转化为MindSpore端侧模型。
### 在端侧实现推理
将
`.ms`
模型文件和图片数据作为输入,创建
`session`
在端侧实现推理。
![](
./images/side_infer_process.jpg
)
图2:端侧推理时序图
对上一步生成的端侧模型文件
`lenet.ms`
执行推理,步骤如下:
1.
读取MindSpore端侧模型文件信息。
2.
调用
`CreateSession`
接口创建
`Session`
。
3.
调用
`Session`
中的
`CompileGraph`
方法,传入模型。
4.
调用
`Session`
中的
`GetInputs`
方法,获取输入
`Tensor`
,获取图片信息设置为
`data`
,
`data`
即为用于推理的输入数据。
5.
调用
`Session`
中的
`RunGraph`
接口执行推理。
6.
调用
`GetOutputs`
接口获取输出。
推理环节的完整示例代码如下:
```
CPP
#include <iostream>
#include <fstream>
#include "schema/model_generated.h"
#include "include/model.h"
#include "include/lite_session.h"
#include "include/errorcode.h"
#include "ir/dtype/type_id.h"
char *ReadFile(const char *file, size_t *size) {
if (file == nullptr) {
std::cerr << "file is nullptr" << std::endl;
return nullptr;
}
if (size == nullptr) {
std::cerr << "size is nullptr" << std::endl;
return nullptr;
}
std::ifstream ifs(file);
if (!ifs.good()) {
std::cerr << "file: " << file << " is not exist" << std::endl;
return nullptr;
}
if (!ifs.is_open()) {
std::cerr << "file: " << file << " open failed" << std::endl;
return nullptr;
}
ifs.seekg(0, std::ios::end);
*size = ifs.tellg();
std::unique_ptr<char> buf(new char[*size]);
ifs.seekg(0, std::ios::beg);
ifs.read(buf.get(), *size);
ifs.close();
return buf.release();
}
int main(int argc, const char **argv) {
size_t model_size;
std::string model_path = "./lenet.ms";
// 1. Read File
auto model_buf = ReadFile(model_path.c_str(), &model_size);
if (model_buf == nullptr) {
std::cerr << "ReadFile return nullptr" << std::endl;
return -1;
}
// 2. Import Model
auto model = mindspore::lite::Model::Import(model_buf, model_size);
if (model == nullptr) {
std::cerr << "Import model failed" << std::endl;
delete[](model_buf);
return -1;
}
delete[](model_buf);
auto context = new mindspore::lite::Context;
context->cpuBindMode = mindspore::lite::NO_BIND;
context->deviceCtx.type = mindspore::lite::DT_CPU;
context->threadNum = 4;
// 3. Create Session
auto session = mindspore::session::LiteSession::CreateSession(context);
if (session == nullptr) {
std::cerr << "CreateSession failed" << std::endl;
return -1;
}
delete context;
auto ret = session->CompileGraph(model.get());
if (ret != mindspore::lite::RET_OK) {
std::cerr << "CompileGraph failed" << std::endl;
delete session;
return -1;
}
// 4. Get Inputs
auto inputs = session->GetInputs();
if (inputs.size() != 1) {
std::cerr << "Lenet should has only one input" << std::endl;
delete session;
return -1;
}
auto in_tensor = inputs.front();
if (in_tensor == nullptr) {
std::cerr << "in_tensor is nullptr" << std::endl;
delete session;
return -1;
}
size_t data_size;
std::string data_path = "./data.bin";
auto input_buf = ReadFile(data_path.c_str(), &data_size);
if (input_buf == nullptr) {
std::cerr << "ReadFile return nullptr" << std::endl;
delete session;
return -1;
}
if (in_tensor->Size()!=data_size) {
std::cerr << "Input data size is not suit for model input" << std::endl;
delete[](input_buf);
delete session;
return -1;
}
auto *in_data = in_tensor->MutableData();
if (in_data == nullptr) {
std::cerr << "Data of in_tensor is nullptr" << std::endl;
delete[](input_buf);
delete session;
return -1;
}
memcpy(in_data, input_buf, data_size);
delete[](input_buf);
// 5. Run Graph
ret = session->RunGraph();
if (ret != mindspore::lite::RET_OK) {
std::cerr << "RunGraph failed" << std::endl;
delete session;
return -1;
}
// 6. Get Outputs
auto outputs = session->GetOutputs();
if (outputs.size()!= 1) {
std::cerr << "Lenet should has only one output" << std::endl;
delete session;
return -1;
}
auto out_tensor = outputs.front();
if (out_tensor == nullptr) {
std::cerr << "out_tensor is nullptr" << std::endl;
delete session;
return -1;
}
if (out_tensor->data_type()!=mindspore::TypeId::kNumberTypeFloat32) {
std::cerr << "Output of lenet should in float32" << std::endl;
delete session;
return -1;
}
auto *out_data = reinterpret_cast<float *>(out_tensor->MutableData());
if (out_data == nullptr) {
std::cerr << "Data of out_tensor is nullptr" << std::endl;
delete session;
return -1;
}
std::cout << "Output data: ";
for (size_t i = 0; i < 10 & i < out_tensor->ElementsNum(); i++) {
std::cout << " " << out_data[i];
}
std::cout << std::endl;
delete session;
return 0;
}
```
tutorials/source_zh_cn/use/multi_platform_inference.md
浏览文件 @
c31c44d7
...
...
@@ -145,4 +145,4 @@ Ascend 310 AI处理器上搭载了ACL框架,他支持OM格式,而OM格式需
## 端侧推理
端侧推理需使用MindSpore Lite推理引擎,详细操作请参考
[
导出MINDIR格式文件
](
https://www.mindspore.cn/tutorial/zh-CN/master/use/saving_and_loading_model_parameters.html#mindir
)
和
[
端侧推理教程
](
https://www.mindspore.cn/
tutorial/zh-CN/master/advanced_use/on_device_inference.html
)
。
端侧推理需使用MindSpore Lite推理引擎,详细操作请参考
[
导出MINDIR格式文件
](
https://www.mindspore.cn/tutorial/zh-CN/master/use/saving_and_loading_model_parameters.html#mindir
)
和
[
端侧推理教程
](
https://www.mindspore.cn/
lite
)
。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录