推理结果处理
基本原理
关于模型执行的输出数据,如需进行进一步的处理,可由用户自行管理实现逻辑。
示例代码(直接处理内存中的数据)
以图片分类网络为例,模型执行结束后,需处理每一张图片的模型推理结果,直接输出top5置信度的类别编号。您可以从样例介绍中获取完整样例代码。
调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝编译运行,仅供参考。
//处理模型推理的输出数据,输出top5置信度的类别编号 //output_表示模型执行的输出 for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(output_); ++i) { //获取每个输出的内存地址和内存大小 aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i); void* data = aclGetDataBufferAddr(dataBuffer); size_t len = aclGetDataBufferSizeV2(dataBuffer); //将内存中的数据转换为float类型 float *outData = NULL; outData = reinterpret_cast<float*>(data); //屏显每张图片的top5置信度的类别编号 map<float, int, greater<float> > resultMap; for (int j = 0; j < len / sizeof(float); ++j) { resultMap[*outData] = j; outData++; } int cnt = 0; for (auto it = resultMap.begin(); it != resultMap.end(); ++it) { // print top 5 if (++cnt > 5) { break; } INFO_LOG("top %d: index[%d] value[%lf]", cnt, it->second, it->first); }
示例代码(调用单算子处理推理结果)
以图片分类网络为例,模型执行结束后,需处理每一张图片的模型推理结果,直接输出最大置信度的类别编号。您可以从样例介绍中获取完整样例代码。
当前示例中,使用Cast算子(将推理结果的数据类型从float32转成float16)和ArgMaxD算子(从推理结果中查找最大置信度的类别标识)实现数据后处理。单算子调用的流程请参见算子调用,详细描述请参见单算子调用。
- Cast算子被封装成AscendCL接口,因此在使用时,将算子的输入输出Tensor描述、算子输入输出数据的内存等信息作为aclopCast的入参,直接调用aclopCast接口加载并执行算子。
- ArgMaxD算子没有被封装成AscendCL接口,因此在使用时,必须自行构造算子描述信息(输入输出Tensor描述、算子属性等)、申请存放算子输入输出数据的内存、明确算子类型名称、调用aclopExecuteV2接口加载并执行算子。
调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝编译运行,仅供参考。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
//提前将Cast和ArgMaxD两个单算子的定义文件*.json编译成适配昇腾AI处理器的离线模型(*.om文件),用于验证单算子的运行 //设置单算子模型文件所在的目录,加载单算子模型 //该目录相对可执行文件所在的目录,例如,编译出来的可执行文件存放在out目录下,此处就表示out/op_models目录 aclError ret1 = aclopSetModelDir("op_models"); //...... //以下步骤需针对每一张图片的模型推理结果进行处理 //1. 在数据后处理前,先获取模型推理的输出,modelOutput表示模型推理的输出 aclDataBuffer inputBuffer_[0] = aclmdlGetDatasetBuffer(modelOutput, 0); //2. 自定义函数RunSigleOpCast,构造Cast算子的输入输出Tensor描述、申请存放算子输出数据的内存devBufferCast_、调用aclopCast接口加载并执行算子 Result ret = RunSigleOpCast(); //3. 自定义函数RunSigleOpArgMaxD,构造ArgMaxD算子的输入输出Tensor、输入输出Tensor描述、算子属性、申请存放算子输出数据的内存devBufferArgMaxD_、调用aclopExecuteV2接口加载并执行算子 ret = RunSigleOpArgMaxD(); //4.传输ArgMaxD算子的输出数据 //4.1 根据ArgMaxD算子输出数据的大小,申请内存 void* hostBuffer = nullptr; aclError ret = aclrtMallocHost(&hostBuffer, tensorSizeArgMaxD_); //4.2 将ArgMaxD算子的输出数据从Device复制到Host ret = aclrtMemcpy(hostBuffer, tensorSizeArgMaxD_, devBufferArgMaxD_, tensorSizeArgMaxD_, ACL_MEMCPY_DEVICE_TO_HOST); //4.3 在终端窗口显示最大置信度的类别编号 int32_t* index = static_cast<int32_t*>(hostBuffer); INFO_LOG("---> index of classification result is %d", *index); //5 释放资源 //5.1 释放内存 aclrtFreeHost(hostBuffer); //5.2 释放Device上存放算子输出数据的内存 (void)aclrtFree(devBufferCast_); (void)aclrtFree(devBufferArgMaxD_); //5.3 释放aclDataBuffer类型数据(用于描述算子输出数据) (void)aclDestroyDataBuffer(outputBufferCast_[0]); (void)aclDestroyDataBuffer(outputBufferArgMaxD_[0]); //...... |
父主题: 模型推理基本场景