diff --git a/tutorials/source_zh_cn/advanced_use/images/on_device_inference_frame.jpg b/tutorials/source_zh_cn/advanced_use/images/on_device_inference_frame.jpg deleted file mode 100644 index 6006c845e8002831ef79b39ce9d68b8afd85e0f2..0000000000000000000000000000000000000000 Binary files a/tutorials/source_zh_cn/advanced_use/images/on_device_inference_frame.jpg and /dev/null differ diff --git a/tutorials/source_zh_cn/advanced_use/images/side_infer_process.eddx b/tutorials/source_zh_cn/advanced_use/images/side_infer_process.eddx deleted file mode 100644 index a1f3e1ad5aa3041bbea7c72ffed3d2ad94bcac40..0000000000000000000000000000000000000000 Binary files a/tutorials/source_zh_cn/advanced_use/images/side_infer_process.eddx and /dev/null differ diff --git a/tutorials/source_zh_cn/advanced_use/images/side_infer_process.jpg b/tutorials/source_zh_cn/advanced_use/images/side_infer_process.jpg deleted file mode 100644 index c860810b3efd4d34fb570c38ed2470cc8670ee32..0000000000000000000000000000000000000000 Binary files a/tutorials/source_zh_cn/advanced_use/images/side_infer_process.jpg and /dev/null differ diff --git a/tutorials/source_zh_cn/advanced_use/on_device_inference.md b/tutorials/source_zh_cn/advanced_use/on_device_inference.md deleted file mode 100644 index 77c4b1b1c71d2e8aed932ac1bc5bde5de01b3847..0000000000000000000000000000000000000000 --- a/tutorials/source_zh_cn/advanced_use/on_device_inference.md +++ /dev/null @@ -1,359 +0,0 @@ -# 端侧推理 - - - -- [端侧推理](#端侧推理) - - [概述](#概述) - - [编译方法](#编译方法) - - [端侧推理使用](#端侧推理使用) - - [生成端侧模型文件](#生成端侧模型文件) - - [在端侧实现推理](#在端侧实现推理) - - - - - -## 概述 - -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 -b r0.7 - ``` - -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 - #include - #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 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(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; - } - ``` diff --git a/tutorials/source_zh_cn/use/multi_platform_inference.md b/tutorials/source_zh_cn/use/multi_platform_inference.md index 4a978eab5cfa5a2ee1da13d7f4e7e2b7a5fc750a..77698182e542f89bc8270c7b3d5ba298c31453a1 100644 --- a/tutorials/source_zh_cn/use/multi_platform_inference.md +++ b/tutorials/source_zh_cn/use/multi_platform_inference.md @@ -20,7 +20,7 @@ - + ## 概述 @@ -76,8 +76,8 @@ CPU | ONNX格式 | 支持ONNX推理的runtime/SDK,如TensorRT。 print("============== {} ==============".format(acc)) ``` 其中, - `model.eval`为模型验证接口,对应接口说明:。 - > 推理样例代码:。 + `model.eval`为模型验证接口,对应接口说明:。 + > 推理样例代码:。 1.2 模型保存在华为云 @@ -98,14 +98,14 @@ CPU | ONNX格式 | 支持ONNX推理的runtime/SDK,如TensorRT。 print("============== {} ==============".format(acc)) ``` 其中, - `hub.load_weights`为加载模型参数接口,对应接口说明:。 + `hub.load_weights`为加载模型参数接口,对应接口说明:。 2. 使用`model.predict`接口来进行推理操作。 ```python model.predict(input_data) ``` 其中, - `model.predict`为推理接口,对应接口说明:。 + `model.predict`为推理接口,对应接口说明:。 ## Ascend 310 AI处理器上推理 @@ -113,7 +113,7 @@ CPU | ONNX格式 | 支持ONNX推理的runtime/SDK,如TensorRT。 Ascend 310 AI处理器上搭载了ACL框架,他支持OM格式,而OM格式需要从ONNX或者AIR模型进行转换。所以在Ascend 310 AI处理器上推理,需要下述两个步骤: -1. 在训练平台上生成ONNX或AIR格式模型,具体步骤请参考[导出AIR格式文件](https://www.mindspore.cn/tutorial/zh-CN/r0.7/use/saving_and_loading_model_parameters.html#air)和[导出ONNX格式文件](https://www.mindspore.cn/tutorial/zh-CN/r0.7/use/saving_and_loading_model_parameters.html#onnx)。 +1. 在训练平台上生成ONNX或AIR格式模型,具体步骤请参考[导出AIR格式文件](https://www.mindspore.cn/tutorial/zh-CN/master/use/saving_and_loading_model_parameters.html#air)和[导出ONNX格式文件](https://www.mindspore.cn/tutorial/zh-CN/master/use/saving_and_loading_model_parameters.html#onnx)。 2. 将ONNX/AIR格式模型文件,转化为OM格式模型,并进行推理。 - 云上(ModelArt环境),请参考[Ascend910训练和Ascend310推理的样例](https://support.huaweicloud.com/bestpractice-modelarts/modelarts_10_0026.html)完成推理操作。 @@ -127,7 +127,7 @@ Ascend 310 AI处理器上搭载了ACL框架,他支持OM格式,而OM格式需 ### 使用ONNX格式文件推理 -1. 在训练平台上生成ONNX格式模型,具体步骤请参考[导出ONNX格式文件](https://www.mindspore.cn/tutorial/zh-CN/r0.7/use/saving_and_loading_model_parameters.html#onnx)。 +1. 在训练平台上生成ONNX格式模型,具体步骤请参考[导出ONNX格式文件](https://www.mindspore.cn/tutorial/zh-CN/master/use/saving_and_loading_model_parameters.html#onnx)。 2. 在GPU上进行推理,具体可以参考推理使用runtime/SDK的文档。如在Nvidia GPU上进行推理,使用常用的TensorRT,可参考[TensorRT backend for ONNX](https://github.com/onnx/onnx-tensorrt)。 @@ -139,10 +139,10 @@ Ascend 310 AI处理器上搭载了ACL框架,他支持OM格式,而OM格式需 ### 使用ONNX格式文件推理 与在GPU上进行推理类似,需要以下几个步骤: -1. 在训练平台上生成ONNX格式模型,具体步骤请参考[导出ONNX格式文件](https://www.mindspore.cn/tutorial/zh-CN/r0.7/use/saving_and_loading_model_parameters.html#onnx)。 +1. 在训练平台上生成ONNX格式模型,具体步骤请参考[导出ONNX格式文件](https://www.mindspore.cn/tutorial/zh-CN/master/use/saving_and_loading_model_parameters.html#onnx)。 2. 在CPU上进行推理,具体可以参考推理使用runtime/SDK的文档。如使用ONNX Runtime,可以参考[ONNX Runtime说明文档](https://github.com/microsoft/onnxruntime)。 ## 端侧推理 -端侧推理需使用MindSpore Lite推理引擎,详细操作请参考[导出MINDIR格式文件](https://www.mindspore.cn/tutorial/zh-CN/r0.7/use/saving_and_loading_model_parameters.html#mindir)和[端侧推理教程](https://www.mindspore.cn/tutorial/zh-CN/r0.7/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)。