HarmonyOS:使用 MindSpore Lite 引擎进行模型推理

2023-12-14 17:28:54

场景介绍

MindSpore?Lite 是一款 AI 引擎,它提供了面向不同硬件设备 AI 模型推理的功能,目前已经在图像分类、目标识别、人脸识别、文字识别等应用中广泛使用。

本文介绍使用 MindSpore?Lite 推理引擎进行模型推理的通用开发流程。

基本概念

在进行开发前,请先了解以下概念。

张量:它与数组和矩阵非常相似,是 MindSpore?Lite 网络运算中的基本数据结构。

Float16 推理模式:?Float16 又称半精度,它使用 16 比特表示一个数。Float16 推理模式表示推理的时候用半精度进行推理。

接口说明

这里给出 MindSpore?Lite 推理的通用开发流程中涉及的一些接口,具体请见下列表格。

Context?相关接口

Model?相关接口

Tensor?相关接口

开发步骤

使用 MindSpore?Lite 进行模型推理的开发流程如下图所示。图 1?使用 MindSpore?Lite 进行模型推理的开发流程

进入主要流程之前需要先引用相关的头文件,并编写函数生成随机的输入,具体如下:

#include?<stdlib.h>#include?<stdio.h>#include?"mindspore/model.h"
//生成随机的输入int GenerateInputDataWithRandom(OH_AI_TensorHandleArray?inputs) {  for (size_t?i?= 0;?i?<?inputs.handle_num; ++i) {    float *input_data?= (float *)OH_AI_TensorGetMutableData(inputs.handle_list[i]);    if (input_data?== NULL) {      printf("MSTensorGetMutableData?failed.\n");      return?OH_AI_STATUS_LITE_ERROR;    }    int64_t?num?= OH_AI_TensorGetElementNum(inputs.handle_list[i]);    const int?divisor?= 10;    for (size_t?j?= 0;?j?<?num;?j++) {??????input_data[j] = (float)(rand() %?divisor) /?divisor;  //?0--0.9f    }  }  return?OH_AI_STATUS_SUCCESS;}

然后进入主要的开发步骤,具括包括模型的准备、读取、编译、推理和释放,具体开发过程及细节请见下文的开发步骤及示例。

1.? 模型准备。

需要的模型可以直接下载,也可以通过模型转换工具获得。

a.? 下载模型的格式若为.ms,则可以直接使用。本文以 mobilenetv2.ms 为例。

b.? 如果是第三方框架的模型,比如?TensorFlow、TensorFlow?Lite、Caffe、ONNX 等,可以使用模型转换工具转换为.ms 格式的模型文件。

2.? 创建上下文,设置线程数、设备类型等参数。

//?创建并配置上下文,设置运行时的线程数量为2,绑核策略为大核优先
OH_AI_ContextHandle?context?= OH_AI_ContextCreate();
if (context?== NULL) {
  printf("OH_AI_ContextCreate?failed.\n");
  return?OH_AI_STATUS_LITE_ERROR;
}
const int?thread_num?= 2;
OH_AI_ContextSetThreadNum(context,?thread_num);
OH_AI_ContextSetThreadAffinityMode(context, 1);
//设置运行设备为CPU,不使用Float16推理
OH_AI_DeviceInfoHandle?cpu_device_info?= OH_AI_DeviceInfoCreate(OH_AI_DEVICETYPE_CPU);
if (cpu_device_info?== NULL) {
  printf("OH_AI_DeviceInfoCreate?failed.\n");
  OH_AI_ContextDestroy(&context);
  return?OH_AI_STATUS_LITE_ERROR;
}
OH_AI_DeviceInfoSetEnableFP16(cpu_device_info, false);
OH_AI_ContextAddDeviceInfo(context,?cpu_device_info);

3.? 创建、加载与编译模型。

调用 OH_AI_ModelBuildFromFile 加载并编译模型。

本例中传入 OH_AI_ModelBuildFromFile 的 argv[1]参数是从控制台中输入的模型文件路径。

//?创建模型OH_AI_ModelHandle?model?= OH_AI_ModelCreate();if (model?== NULL) {  printf("OH_AI_ModelCreate?failed.\n");  OH_AI_ContextDestroy(&context);  return?OH_AI_STATUS_LITE_ERROR;}
//?加载与编译模型,模型的类型为OH_AI_MODELTYPE_MINDIRint?ret?= OH_AI_ModelBuildFromFile(model,?argv[1],?OH_AI_MODELTYPE_MINDIR,?context);if (ret?!=?OH_AI_STATUS_SUCCESS) {  printf("OH_AI_ModelBuildFromFile?failed,?ret:?%d.\n",?ret);  OH_AI_ModelDestroy(&model);  return?ret;}

4.? 输入数据。

模型执行之前需要向输入的张量中填充数据。本例使用随机的数据对模型进行填充。

//?获得输入张量OH_AI_TensorHandleArray?inputs?= OH_AI_ModelGetInputs(model);if (inputs.handle_list?== NULL) {  printf("OH_AI_ModelGetInputs?failed,?ret:?%d.\n",?ret);  OH_AI_ModelDestroy(&model);  return?ret;}//?使用随机数据填充张量ret?= GenerateInputDataWithRandom(inputs);if (ret?!=?OH_AI_STATUS_SUCCESS) {  printf("GenerateInputDataWithRandom?failed,?ret:?%d.\n",?ret);  OH_AI_ModelDestroy(&model);  return?ret;}

5.? 执行推理。

使用 OH_AI_ModelPredict 接口进行模型推理。

//?执行模型推理OH_AI_TensorHandleArray?outputs;ret?= OH_AI_ModelPredict(model,?inputs, &outputs, NULL, NULL);if (ret?!=?OH_AI_STATUS_SUCCESS) {  printf("OH_AI_ModelPredict?failed,?ret:?%d.\n",?ret);  OH_AI_ModelDestroy(&model);  return?ret;}

6.? 获取输出。

模型推理结束之后,可以通过输出张量得到推理结果。

//?获取模型的输出张量,并打印
for (size_t?i?= 0;?i?<?outputs.handle_num; ++i) {
??OH_AI_TensorHandle?tensor?=?outputs.handle_list[i];
  int64_t?element_num?= OH_AI_TensorGetElementNum(tensor);
  printf("Tensor?name:?%s,?tensor?size?is?%zu?,elements?num:?%lld.\n", OH_AI_TensorGetName(tensor),
        OH_AI_TensorGetDataSize(tensor),?element_num);
  const float *data?= (const float *)OH_AI_TensorGetData(tensor);
  printf("output?data?is:\n");
  const int?max_print_num?= 50;
  for (int?j?= 0;?j?<?element_num?&&?j?<=?max_print_num; ++j) {
    printf("%f?",?data[j]);
  }
  printf("\n");
}

7.? 释放模型。

不再使用 MindSpore?Lite 推理框架时,需要释放已经创建的模型。

//?释放模型OH_AI_ModelDestroy(&model);

调测验证

1.? 编写 CMakeLists.txt。

cmake_minimum_required(VERSION?3.14)project(Demo)
add_executable(demo?main.c)
target_link_libraries(????????demo????????mindspore-lite.huawei????????pthread????????dl)

●?使用 ohos-sdk 交叉编译,需要对 CMake 设置 native 工具链路径,即:-DCMAKE_TOOLCHAIN_FILE="/xxx/native/build/cmake/ohos.toolchain.camke"。

●?工具链默认编译 64 位的程序,如果要编译 32 位,需要添加:-DOHOS_ARCH="armeabi-v7a"。

2.? 运行。

●?使用 hdc_std 连接设备,并将 demo 和 mobilenetv2.ms 推送到设备中的相同目录。

●?使用 hdc_std?shell 进入设备,并进入 demo 所在的目录执行如下命令,即可得到结果。

./demo?mobilenetv2.ms

得到如下输出:

#?./QuickStart?./mobilenetv2.ms????????????????????????????????????????????
Tensor?name:?Softmax-65,?tensor?size?is?4004 ,elements?num: 1001.
output?data?is:
0.000018 0.000012 0.000026 0.000194 0.000156 0.001501 0.000240 0.000825 0.000016 0.000006 0.000007 0.000004 0.000004 0.000004 0.000015 0.000099 0.000011 0.000013 0.000005 0.000023 0.000004 0.000008 0.000003 0.000003 0.000008 0.000014 0.000012 0.000006 0.000019 0.000006 0.000018 0.000024 0.000010 0.000002 0.000028 0.000372 0.000010 0.000017 0.000008 0.000004 0.000007 0.000010 0.000007 0.000012 0.000005 0.000015 0.000007 0.000040 0.000004 0.000085 0.000023 

文章来源:https://blog.csdn.net/HarmonyOSDev/article/details/134999000
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。