<一>总览

MindSpore支持保存两种类型的数据:训练参数和网络模型(模型中包含参数信息)。

  • 训练参数指的是Checkpoint格式文件。

  • 网络模型包括MindIR、AIR和ONNX三种格式文件。

下面介绍一下这几种格式的基本概念及其应用场景。

  • Checkpoint

    • 采用了Protocol Buffers格式,存储了网络中所有的参数值。

    • 一般用于训练任务中断后恢复训练,或训练后的微调(Fine Tune)任务。

  • MindIR

    • 全称MindSpore IR,是MindSpore的一种基于图表示的函数式IR,定义了可扩展的图结构以及算子的IR表示。

    • 它消除了不同后端的模型差异,一般用于跨硬件平台执行推理任务。

  • ONNX

    • 全称Open Neural Network Exchange,是一种针对机器学习模型的通用表达。

    • 一般用于不同框架间的模型迁移或在推理引擎(TensorRT)上使用

  • AIR

    • 全称Ascend Intermediate Representation,是华为定义的针对机器学习所设计的开放式文件格式。

    • 它能更好地适应华为AI处理器,一般用于Ascend 310上执行推理任务。

<二> 推理

总体步骤:

  1. 开发环境准备,Python3.7.5 ,ubuntu 18.04.5   x86_64,配套开发软件包 CNN、mindx_sdk等。

  2. 导出AIR模型文件

  3. 使用ATC工具将AIR模型文件转成OM模型。

  4. 编译推理代码,生成可执行main文件。

  5. 加载保存的OM模型,执行推理并查看结果。

(1)离线模型转换

总体流程:Checkpoint---->lenet.air----->om

使用ATC工具将air文件转换为om文件

model_path=$1
output_model_name=$2/usr/local/Ascend/atc/bin/atc \
--model=$model_path \
--mode=0 \
--framework=1 \
--output=$output_model_name \
--input_format=NCHW \
--soc_version=Ascend310 \

参数说明:

--mode=0                  0表示转为离线om模型
--model                     待转文件路径与文件名。
 --framework=1        原始框架类型,1为mindspore
--output                    存放转换后的离线模型的路径以及文件名
--soc_version           模型转换时指定芯片版本(一定要指名,刚开始没填写,一直报错)

命令运行脚本        bash air2om.sh ./ww.air ../mxbase/models/lenet

最终结果:得到om模型文件

其他Caffe、Tensorflow等框架的转换方式以及配置参数,见昇腾CANN社区版

(2)MxBase推理过程

      大致目录结构:不同模型有所不同

├── data├── config                          # 模型配置信息├── coco.names                    # 数据集类别├── infer.txt                     # 保存推理图片路径├── images                          # 推理图片├── 1.jpg├── 2.jpg├── 3.jpg......├── model                           # 保存模型文件├── model_tf_aipp.om
├── mxbase├── main.cpp                        # 推理启动脚本├── modelDetection.h                # 模型推理.h文件├── modelDetection.cpp              # 模型推理脚本├── CMakeLists.txt                  # Cmake编译文件├── build.sh                        # 编译脚本

2.1、build.sh编译脚本:设置编译环境,需要根据本地机子实际环境做修改

#!/bin/bash# Copyright 2020 Huawei Technologies Co., Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License atpath_cur=$(dirname $0)
echo "now_path:${path_cur}"
echo "ASCEND_VERSION:${ASCEND_VERSION}"
function check_env()
{# set ASCEND_VERSION to ascend-toolkit/latest when it was not specified by userif [ ! "${ASCEND_VERSION}" ]; thenexport ASCEND_VERSION=nnrt/latestecho "Set ASCEND_VERSION to the default value: ${ASCEND_VERSION}"elseecho "ASCEND_VERSION is set to ${ASCEND_VERSION} by user"fiif [ ! "${ARCH_PATTERN}" ]; then# set ARCH_PATTERN to ./ when it was not specified by userexport ARCH_PATTERN=./echo "ARCH_PATTERN is set to the default value: ${ARCH_PATTERN}"elseecho "ARCH_PATTERN is set to ${ARCH_PATTERN} by user"fi
}function build_lenet()
{cd $path_currm -rf buildmkdir -p buildcd buildcmake ..makeret=$?if [ ${ret} -ne 0 ]; thenecho "Failed to build lenet."exit ${ret}fimake install
}check_env
build_lenet

2.2、 CMakeLists.txt编译文件:根据实际情况做修改

cmake_minimum_required(VERSION 3.14.1)
project(lenet)
set(TARGET lenet)
add_definitions(-DENABLE_DVPP_INTERFACE)
add_compile_options(-std=c++11 -fPIE -fstack-protector-all -fPIC -Wall)
add_link_options(-Wl,-z,relro,-z,now,-z,noexecstack -pie)# 检查环境变量
if(NOT DEFINED ENV{ASCEND_HOME})message(FATAL_ERROR "please define environment variable:ASCEND_HOME")
endif()
if(NOT DEFINED ENV{ASCEND_VERSION})message(WARNING "please define environment variable:ASCEND_VERSION")
endif()
if(NOT DEFINED ENV{ARCH_PATTERN})message(WARNING "please define environment variable:ARCH_PATTERN")
endif()
set(ACL_INC_DIR $ENV{ASCEND_HOME}/$ENV{ASCEND_VERSION}/acllib/include)
set(ACL_LIB_DIR $ENV{ASCEND_HOME}/$ENV{ASCEND_VERSION}/acllib/lib64)set(MXBASE_ROOT_DIR $ENV{MX_SDK_HOME})
set(MXBASE_INC ${MXBASE_ROOT_DIR}/include)
set(MXBASE_LIB_DIR ${MXBASE_ROOT_DIR}/lib)set(MXBASE_POST_LIB_DIR ${MXBASE_ROOT_DIR}/lib/modelpostprocessors)
set(MXBASE_POST_PROCESS_DIR ${MXBASE_INC}/MxBase/postprocess/include)
if(DEFINED ENV{MXSDK_OPENSOURCE_DIR})set(OPENSOURCE_DIR $ENV{MXSDK_OPENSOURCE_DIR})
else()set(OPENSOURCE_DIR ${MXBASE_ROOT_DIR}/opensource)
endif()#包含编译需要用到的目录
include_directories(${ACL_INC_DIR})
include_directories(${OPENSOURCE_DIR}/include)
include_directories(${OPENSOURCE_DIR}/include/opencv4)include_directories(${MXBASE_INC})
include_directories(${MXBASE_POST_PROCESS_DIR})link_directories(${ACL_LIB_DIR})
link_directories(${OPENSOURCE_DIR}/lib)
link_directories(${MXBASE_LIB_DIR})
link_directories(${MXBASE_POST_LIB_DIR})#设置主执行文件
add_executable(${TARGET} main.cpp)#target_link_libraries(${TARGET} glog cpprest mxbase opencv_world)install(TARGETS ${TARGET} RUNTIME DESTINATION ${PROJECT_SOURCE_DIR}/)

2.3、推理脚本

        2.3.1    主函数启动脚本 main_opencv.cpp

        作用:初始化模型配置所需参数,加载图片供后续推理

#include "MxBase/Log/Log.h"
#include <dirent.h>
#include "LenetOpencv.h"namespace {
const uint32_t CLASS_NUM = 10;
} // namespaceAPP_ERROR ScanImages(const std::string &path, std::vector<std::string> &imgFiles)
{DIR *dirPtr = opendir(path.c_str());if (dirPtr == nullptr) {LogError << "opendir failed. dir:" << path;return APP_ERR_INTERNAL_ERROR;}dirent *direntPtr = nullptr;while ((direntPtr = readdir(dirPtr)) != nullptr) {std::string fileName = direntPtr->d_name;if (fileName == "." || fileName == "..") {continue;}imgFiles.emplace_back(path + "/" + fileName);}closedir(dirPtr);return APP_ERR_OK;
}int main(int argc, char* argv[]){if (argc <= 1) {LogError << "Please input image path, such as './lenet image_dir'.";return APP_ERR_OK;}InitParam initParam = {};initParam.deviceId = 0;initParam.classNum = CLASS_NUM;initParam.checkTensor = true;initParam.modelPath = "../models/lenet.om";auto lenet = std::make_shared<LenetOpencv>();APP_ERROR ret = lenet->Init(initParam);if (ret != APP_ERR_OK) {LogError << "Lenet init failed, ret=" << ret << ".";return ret;}else{LogError<<"Lenet init success";}std::string imgPath = argv[1];std::vector<std::string> imgFilePaths;ret = ScanImages(imgPath, imgFilePaths);auto startTime = std::chrono::high_resolution_clock::now();for (auto &imgFile : imgFilePaths) {ret = lenet->Process(imgFile);if (ret != APP_ERR_OK) {LogError << "lenet process failed, ret=" << ret << ".";lenet->DeInit();return ret;}}auto endTime = std::chrono::high_resolution_clock::now();lenet->DeInit();double costMilliSecs = std::chrono::duration<double, std::milli>(endTime - startTime).count();double fps = 1000.0 * imgFilePaths.size() / lenet->GetInferCostMilliSec();LogInfo << "[Process Delay] cost: " << costMilliSecs << " ms\tfps: " << fps << " imgs/sec";return APP_ERR_OK;}

2.3.2    模型推理脚本和 .h文件

            作用:模型推理具体实现代码

#LenetOpencv.cpp文件#include "LenetOpencv.h"
#include "MxBase/DeviceManager/DeviceManager.h"
#include "MxBase/Log/Log.h"
#include "MxBase/ConfigUtil/ConfigUtil.h"using namespace MxBase;namespace {const uint32_t YUV_BYTE_NU = 3;const uint32_t YUV_BYTE_DE = 2;const uint32_t VPC_H_ALIGN = 2;
}APP_ERROR LenetOpencv::Init(const InitParam &initParam)
{deviceId_ = initParam.deviceId;APP_ERROR ret = MxBase::DeviceManager::GetInstance()->InitDevices();if (ret != APP_ERR_OK) {LogError << "Init devices failed, ret=" << ret << ".";return ret;}ret = MxBase::TensorContext::GetInstance()->SetContext(initParam.deviceId);if (ret != APP_ERR_OK) {LogError << "Set context failed, ret=" << ret << ".";return ret;}dvppWrapper_ = std::make_shared<MxBase::DvppWrapper>();ret = dvppWrapper_->Init();if (ret != APP_ERR_OK) {LogError << "DvppWrapper init failed, ret=" << ret << ".";return ret;}model_ = std::make_shared<MxBase::ModelInferenceProcessor>();ret = model_->Init(initParam.modelPath, modelDesc_);if (ret != APP_ERR_OK) {LogError << "ModelInferenceProcessor init failed, ret=" << ret << ".";return ret;}MxBase::ConfigData configData;const std::string checkTensor = initParam.checkTensor ? "true" : "false";configData.SetJsonValue("CLASS_NUM", std::to_string(initParam.classNum));configData.SetJsonValue("CHECK_MODEL", checkTensor);auto jsonStr = configData.GetCfgJson().serialize();std::map<std::string, std::shared_ptr<void>> config;return APP_ERR_OK;
}APP_ERROR LenetOpencv::DeInit()
{dvppWrapper_->DeInit();model_->DeInit();MxBase::DeviceManager::GetInstance()->DestroyDevices();return APP_ERR_OK;
}APP_ERROR LenetOpencv::ReadImage(const std::string &imgPath, cv::Mat &imageMat)
{imageMat = cv::imread(imgPath, cv::IMREAD_COLOR);return APP_ERR_OK;
}APP_ERROR LenetOpencv::CVMatToTensorBase(const cv::Mat &imageMat, MxBase::TensorBase &tensorBase)
{const uint32_t dataSize =  imageMat.cols *  imageMat.rows * YUV444_RGB_WIDTH_NU;LogInfo << "image size " << imageMat.cols << " " << imageMat.rows;MemoryData memoryDataDst(dataSize, MemoryData::MEMORY_DEVICE, deviceId_);MemoryData memoryDataSrc(imageMat.data, dataSize, MemoryData::MEMORY_HOST_MALLOC);APP_ERROR ret = MemoryHelper::MxbsMallocAndCopy(memoryDataDst, memoryDataSrc);if (ret != APP_ERR_OK) {LogError << GetError(ret) << "Memory malloc failed.";return ret;}std::vector<uint32_t> shape = {imageMat.rows * YUV444_RGB_WIDTH_NU, static_cast<uint32_t>(imageMat.cols)};tensorBase = TensorBase(memoryDataDst, false, shape, TENSOR_DTYPE_UINT8);return APP_ERR_OK;
}APP_ERROR LenetOpencv::Inference(const std::vector<MxBase::TensorBase> &inputs,std::vector<MxBase::TensorBase> &outputs)
{//model_  is  <MxBase::ModelInferenceProcessor>  object, modelDesc_ is an object which save the model_infoauto dtypes = model_->GetOutputDataType();for (size_t i = 0; i < modelDesc_.outputTensors.size(); ++i) {std::vector<uint32_t> shape = {};for (size_t j = 0; j < modelDesc_.outputTensors[i].tensorDims.size(); ++j) {shape.push_back((uint32_t)modelDesc_.outputTensors[i].tensorDims[j]);}TensorBase tensor(shape, dtypes[i], MemoryData::MemoryType::MEMORY_DEVICE, deviceId_);APP_ERROR ret = TensorBase::TensorBaseMalloc(tensor);if (ret != APP_ERR_OK) {LogError << "TensorBaseMalloc failed, ret=" << ret << ".";return ret;}outputs.push_back(tensor);}DynamicInfo dynamicInfo = {};dynamicInfo.dynamicType = DynamicType::STATIC_BATCH;auto startTime = std::chrono::high_resolution_clock::now();APP_ERROR ret = model_->ModelInference(inputs, outputs, dynamicInfo);auto endTime = std::chrono::high_resolution_clock::now();double costMs = std::chrono::duration<double, std::milli>(endTime - startTime).count();// save timeinferCostTimeMilliSec += costMs;if (ret != APP_ERR_OK) {LogError << "ModelInference failed, ret=" << ret << ".";return ret;}return APP_ERR_OK;
}//image process
APP_ERROR LenetOpencv::Process(const std::string &imgPath)
{cv::Mat imageMat;APP_ERROR ret = ReadImage(imgPath, imageMat);if (ret != APP_ERR_OK) {LogError << "ReadImage failed, ret=" << ret << ".";return ret;}std::vector<MxBase::TensorBase> inputs = {};std::vector<MxBase::TensorBase> outputs = {};TensorBase tensorBase;//image ==>tensorBaseret = CVMatToTensorBase(imageMat, tensorBase);if (ret != APP_ERR_OK) {LogError << "CVMatToTensorBase failed, ret=" << ret << ".";return ret;}//put tensorBase to inputsinputs.push_back(tensorBase);auto startTime = std::chrono::high_resolution_clock::now();//start inference for each imageret = Inference(inputs, outputs);auto endTime = std::chrono::high_resolution_clock::now();double costMs = std::chrono::duration<double, std::milli>(endTime - startTime).count();// save timeinferCostTimeMilliSec += costMs;if (ret != APP_ERR_OK) {LogError << "Inference failed, ret=" << ret << ".";return ret;}/*//post processstd::vector<std::vector<MxBase::ClassInfo>> BatchClsInfos = {};ret = PostProcess(outputs, BatchClsInfos);if (ret != APP_ERR_OK) {LogError << "PostProcess failed, ret=" << ret << ".";return ret;}ret = SaveResult(imgPath, batchClsInfos);if (ret != APP_ERR_OK) {LogError << "Save infer results into file failed. ret = " << ret << ".";return ret;}*/return APP_ERR_OK;
}
#LenetOpencv.h头文件#ifndef MXBASE_LENETOPENCV_H
#define MXBASE_LENETOPENCV_H
#include <opencv2/opencv.hpp>#include "MxBase/DvppWrapper/DvppWrapper.h"
#include "MxBase/ModelInfer/ModelInferenceProcessor.h"
#include "MxBase/Tensor/TensorContext/TensorContext.h"struct InitParam {uint32_t deviceId;uint32_t classNum;bool checkTensor;std::string modelPath;
};
class LenetOpencv{public:APP_ERROR Init(const InitParam &initParam);APP_ERROR DeInit();APP_ERROR ReadImage(const std::string &imgPath, cv::Mat &imageMat);APP_ERROR CVMatToTensorBase(const cv::Mat &imageMat, MxBase::TensorBase &tensorBase);APP_ERROR Inference(const std::vector<MxBase::TensorBase> &inputs, std::vector<MxBase::TensorBase> &outputs);APP_ERROR Process(const std::string &imgPath);// get infer timedouble GetInferCostMilliSec() const {return inferCostTimeMilliSec;}private:std::shared_ptr<MxBase::DvppWrapper> dvppWrapper_;std::shared_ptr<MxBase::ModelInferenceProcessor> model_;MxBase::ModelDesc modelDesc_;uint32_t deviceId_ = 0;// infer timedouble inferCostTimeMilliSec = 0.0;};#endif

2.4、编译

上述所有步骤完成就可以进行编译,执行bash build.sh

就会生成绿色字体的可执行文件。

2.5、MNIST数据集预处理,转为jpg图片

可以看我的另一篇博文

python 将MNIST数据集转为jpg图片格式_白白白-CSDN博客

2.6、运行推理服务。

./lenet image_path (参数解释:image_path 代表待推理图片的路径)。

在 “mxbase/lenet” 目录下执行推理命令,如

./lenet ../../infer_data/pre_process_image/

结果

如果结果和上图一致,表明推理运行成功,所有推理结果会保存在同级目录下的 result_Files 文件夹中。

2.7、后处理与观察结果。

接着,需要对推理的结果做后处理,计算精度。

python postprocess.py result_path infer_data (参数解释:result_path 表示推理后结果存储的路径,infer_data 表示上一步中推理所用到的图片路径)。

在 “mxbase/lenet”目录下 执行后处理命令:

python postprocess.py ./result_Files/ ../../infer_data/pre_process_image/

结果:如上图所示,可以看到精度的计算结果,为0.9838 。精度结果也会存于acc.log 文件夹中。

MindX SDK推理

  1. 修改配置文件。

    1. 修改pipeline文件。(默认位置 ascend310_infer --> sdk --> pipeline --> lenet.pipeline)

      进入pipeline目录:

      cd /home/data/hdk_mindx/lenet_code/ascend310_infer/sdk/pipeline/

      由于之前步骤中,om模型位置为 : ascend310_infer --> lenet_model --> lenet.om ,因此根据实际做修改,其他都不用改。

    2. sdk --> python_lenet --> main.py 推理文件需要注意的参数

    3. sdk --> python_lenet --> run.sh 推理启动脚本需要注意的环境变量配置

      1. 确保上述${MX_SDK_HOME}等系统环境变量设置正确。

  2. 运行推理服务。

    1. 执行推理。

      bash run.sh infer_image_path output_result_path (参数解释:infer_image_path : 待推理图片的路径 output_result_path : 结果保存路径)

      如:

      bash run.sh ../../infer_data/pre_process_image/ ./result

      前面步骤,推理图片路径为: ascend310_infer -->infer_data --> pre_process_image

      结果保存于 同级目录下result文件夹中。

      出现上图结果表示推理完成!

    2. 查看推理结果。(main.py 推理脚本 已包含 后处理、计算精度步骤,只需运行run.sh ,结束后 即可看到精度)

      可以看到此处的精度和mxbase推理的精度保持一致。

mindspore| lenet模型 推理过程记录相关推荐

  1. Copy攻城狮辛酸史:含泪“一分钟”跑通MindSpore的LeNet模型

    摘要:一个Cope 攻城狮用切身实例告诉你: Cope代码体验一时爽,BUG修改花半天. 前言:此文为r0.7-beta的操作实践,为什么我的眼里常含泪水,因为我对踩坑这件事爱得深沉.谨以此文献给和我 ...

  2. python与机器学习(七)上——PyTorch搭建LeNet模型进行MNIST分类

    任务要求:利用PyTorch框架搭建一个LeNet模型,并针对MNIST数据集进行训练和测试. 数据集:MNIST 导入: import torch from torch import nn, opt ...

  3. MindSpore图像分类模型支持(Lite)

    MindSpore图像分类模型支持(Lite) 图像分类介绍 图像分类模型可以预测图片中出现哪些物体,识别出图片中出现物体列表及其概率. 比如下图经过模型推理的分类结果为下表: 使用MindSpore ...

  4. [Django]模型学习记录篇--基础

    模型学习记录篇,仅仅自己学习时做的记录!!! 实现模型变更的三个步骤: 修改你的模型(在models.py文件中). 运行python manage.py makemigrations ,为这些修改创 ...

  5. 动手学深度学习(PyTorch实现)(七)--LeNet模型

    LeNet模型 1. LeNet模型 2. PyTorch实现 2.1 模型实现 2.2 获取数据与训练 1. LeNet模型 LeNet分为卷积层块和全连接层块两个部分.下面我们分别介绍这两个模块. ...

  6. sql表格模型获取记录内容_SQL Server和BI –如何使用Excel记录表格模型

    sql表格模型获取记录内容 介绍 (Introduction) A few weeks back I had been working on an interesting proof of conce ...

  7. sql表格模型获取记录内容_SQL Server和BI –如何使用Reporting Services 2016记录表格模型

    sql表格模型获取记录内容 介绍 (Introduction) A few weeks back I had been working on an interesting proof of conce ...

  8. 深度学习CTR模型粗略记录

    深度学习CTR模型粗略记录 RoadMap FM:Factorization Machines DNN:Embedding+MLP WND:Wide & Deep Learning for R ...

  9. 【从零开始学习深度学习】25.卷积神经网络之LeNet模型介绍及其Pytorch实现【含完整代码】

    目录 1. LeNet模型介绍与实现 2. 输入为Fashion-MNIST时各层输出形状 3. 获取Fashion-MNIST数据和并使用LeNet模型进行训练 4.完整代码 之前我们对Fashio ...

  10. 空间计量模型学习记录

    空间计量模型学习记录 空间计量模型模型分类 OSL模型 空间滞后模型 空间误差模型 自变量空间滞后模型 空间杜宾模型 空间杜宾误差模型 操作方式参考 参考文章 空间自回归模型-OLS.SLM.SEM理 ...

最新文章

  1. Linux内核编译与管理
  2. Ansible管理节点过多导致的超时问题解决方法
  3. Pytorch:上采样、下采样
  4. 信贷ABS资产静态池与动态池里的数据分析内容都有啥
  5. codevs1068 乌龟棋 题解
  6. 基于AWS的电子商务网站架构——营销与推荐服务
  7. Shiro 常用标签
  8. MySQL索引性能测试
  9. OGG-01433 Oracle GoldenGate Capture for Oracle, EXXX.prm: Failed to validate table <SCHEMANAME.TABLE
  10. 刚刚提取了金山毒霸的[垃圾清理] 和 [隐私清理], 分享方法,大家可以自己试一下
  11. mysql数据库建表的作用_浅谈(SQL Server)数据库中系统表的作用
  12. mysql数据库的单引号用法_[数据库]mysql单引号和双引号的用法
  13. 微表情识别的图片预处理(python版)
  14. 辐射照度、辐射强度、光照度、发光强度(差异以及如何相互转换)(易懂讲解)
  15. 2018第五届“云鼎奖”申报启动
  16. 涂涂乐的详细实现之三--文件IO操作
  17. schmidt正交化
  18. windows下安装配置mycat
  19. AcWing 125. 耍杂技的牛 (推公式)
  20. JavaScript的前生今世

热门文章

  1. 智能眼镜的两种显示方式
  2. coursera “the media could not be loaded either because the server or network falled...“解决办法
  3. 手机梦幻模拟战更新服务器正在维护,梦幻模拟战手游9月13日更新了什么 梦幻模拟战更新维护公告...
  4. 高校成绩管理数据库系统的设计与实现
  5. C. Annoying Present(思维+数学)
  6. ubuntu系统调节显卡GPU风扇转速
  7. 如何通过JS调用快递单号查询接口,完成物流轨迹查询
  8. 机器学习中的数学基础--特征函数与中心极限定理,统计学基本概念,极大似然估计,最大后验估计
  9. 大学计算机文件管理实验步骤,大学计算机实验报告
  10. 【爬虫BUG】‘list‘ object has no attribute ‘text‘