TNN iOS非图像模型入门
注:本文同步发布于微信公众号:stringwu的互联网杂谈TNN iOS 非图像模型入门指南
1 背景
TNN是腾讯优图实验室开源的高性能、轻量级神经网络推理框架TNN,github上也有比较详细的例子来说明如何在端上运行图像类的模型,但demo 更多是图像类相关的示例,而且里面做了一层层的封装,很难让一个初学者直接上手一步步构建出可推理的结果,
本文主要从初学者的角度出发,按照TNN的API文档一步步构建出非图像模型的入门文档。(本文不再详述如何编译和集成TNN工程,有需要的同学可直接参考Demo文档);
2 构建
TNN的推理流程主要包括模型的解析,网络构建,输入设定,输出获取
2.1 模型解析
模型文件包括两个部分:
- *.tnnmodel
- *.tnnproto
模型解析的步骤包括:
- 获取模型文件的路径
- 解析文件内容
- 初始化模型
// 获取模型文件 (提前把对应的模型文件集成到工程中)
auto model_path = [[NSBundle mainBundle] pathForResource:@"model/recommend/recommend.tnnmodel"
ofType:nil];
auto proto_path = [[NSBundle mainBundle] pathForResource:@"model/recommend/recommend.tnnproto" ofType:nil];
//解析文件内容
string proto_content = [NSString stringWithContentsOfFile:proto_path encoding:NSUTF8StringEncoding error:nil].UTF8String;
string model_content = [data_mode length] > 0 ? string((const char *)[data_mode bytes], [data_mode length]) : "";
//模型的配置
TNN_NS::ModelConfig model_config;
model_config.model_type = TNN_NS::MODEL_TYPE_TNN; // 指定模型的类型为TNN
model_config.params.push_back(proto_content);
model_config.params.push_back(model_content);
auto tnn = std::make_shared<TNN_NS::TNN>(); //实例化TNN 的实例
//初始化模型
Status ret = tnn->Init(model_config);
//结果为TNN_OK时才为模型初始化成功
if (ret != TNN_OK) {
return;
}
2.2 网络构建
网络的构建需要配置TNN_NS::NetworkConfig,这个配置需要指定device_type和library_path,在iOS中的device_type正常是使用TNN_NS::DEVICE_ARM和 TNN_NS::DEVICE_METAL就可以了,但笔者在实际尝试时,发现device_type指定这两个类型都没有办法正常跑通,后与TNN相关同学咨询请教后,使用了TNN_NS::DEVICE_NAIVE才正常跑通,具体的原因TNN的同学还在帮忙定位中。(如果发现数据正常时,流程没有办法跑通的话,可以多换几个device_type看看)
auto library_path = [[NSBundle mainBundle] pathForResource:@"tnn.metallib" ofType:nil];
//shape数据
auto shape_path = [[NSBundle mainBundle] pathForResource:@"model/recommend/tnn_input.json" ofType:nil];
//将shape数据转成NSDictionary
NSData *data_shape = [NSData dataWithContentsOfFile:shape_path];
NSDictionary * dictionary_shape = [NSJSONSerialization JSONObjectWithData:data_shape options:NSJSONReadingMutableLeaves error:nil];
//构造出TNN可识别的shape数据
InputShapesMap sdkInputShape = {};
for (NSString *key in dictionary_shape) {
NSDictionary*tmpValue = dictionary_shape[key];
NSLog(@"InputShapesMap: println key %@****",key);
NSInteger int1 = [tmpValue[@"dim1"]intValue];
NSInteger int2 = [tmpValue[@"dim2"]intValue];
NSLog(@"InputShapesMap222: println key %ld,%ld****",int1,int2);
TNN_NS::DimsVector nc = {(int)int1,(int)int2};
sdkInputShape.insert(std::pair<std::string, TNN_NS::DimsVector>(std::string(key.UTF8String),nc));
}
// 构造出net_config
TNN_NS::NetworkConfig net_config;
net_config.device_type = TNN_NS::DEVICE_NAIVE; // 指定device_type,如果跑不成功,可以多换几个type试试
net_config.library_path = {library_path.UTF8String};
TNN_NS::Status error;
//构造出TNN网络对象
auto net_instace = tnn->CreateInst(net_config, error,sdkOptions->input_shapes);
//结果为TNN_OK时才为网络构建成功
if (error != TNN_OK) {
return;
}
2.3 输入设定
输入设定主要是通过TNN的方法 SetInputMat 来完成的;
//从文件获取模型的输入
auto mock_input_path = [[NSBundle mainBundle] pathForResource:@"model/recommend/mock_input.json" ofType:nil];
//将数据转换成NSDictionary
NSData *data_mock = [NSData dataWithContentsOfFile:mock_input_path];
NSDictionary * dictionary_mock = [NSJSONSerialization JSONObjectWithData:data_mock options:NSJSONReadingMutableLeaves error:nil];
//将数据转换成TNN的输入格式
std:map<std::string,std::vector<float>> inputDatas = {};
for (NSString *key in dictionary_mock) {
NSArray *valueArray = dictionary_mock[key];
__block std::vector<float> valueVector ={};
valueVector.reserve([valueArray count]);
[valueArray enumerateObjectsUsingBlock:^( id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
valueVector.push_back([obj floatValue]);
}];
inputDatas[[key UTF8String]] = valueVector;
}
BlobMap blob_map;
net_instace ->GetAllInputBlobs(blob_map);
//遍历所有的输入key
for (const auto&item : blob_map) {
//获取对应的key
std::string name = item.first;
//获取key对应的输入数据
std::vector<float> tmpItem = inputDatas.at(name);
//获取key对应的shape数据
DimsVector shape = sdkOptions->input_shapes[name];
//构造出input_mat
auto input_mat = std::make_shared<TNN_NS::Mat>(net_config.device_type,TNN_NS::NCHW_FLOAT,shape,tmpItem.data());
MatConvertParam input_convert_params = TNN_NS::MatConvertParam();
//把输入数据通过SetInputMat方法给到TNN引擎
auto status = net_instace->SetInputMat(input_mat,input_convert_params,name);
//结果为TNN_OK时才为设置输入成功
if (status != TNN_OK) {
NSLog(@"setInputmat error ");
return;
}
}
//执行推理
auto forwardStatus = net_instace->Forward();
if (forwardStatus != TNN_OK) {
NSLog(@"forwardStatus error ");
return;
}
2.4 输出获取
获取推理的结果,是通过TNN的GetAllOutputBlobs接口来完成
BlobMap out_blob_map;
//获取所有的输出key
net_instace ->GetAllOutputBlobs(out_blob_map);
//所有的结果都输出放在 mat_map里面
std::map<std::string, std::shared_ptr<TNN_NS::Mat> > mat_map = {};
//遍历所有输出key
for (const auto&item: out_blob_map) {
auto name = item.first;
MatConvertParam output_convert_params = TNN_NS::MatConvertParam();
std::shared_ptr<TNN_NS::Mat> output_mat = nullptr;
auto status = net_instace->GetOutputMat(output_mat,output_convert_params,name,net_config.device_type);
if (status != TNN_OK) {
NSLog(@"outPutError error ");
return;
}
mat_map[name] = output_mat;
NSLog(@"outPutname %@",[NSString stringWithFormat:@"%s", name.c_str()]);
}
在得到输出结果的map后mat_map后,就可以根据业务的情况进行结果的解析,本文使用的模型最终的结果是一个float值
//推荐模型的推理结果是存在在pred字段里面;
auto scores = mat_map["pred"];
auto dims = scores ->GetDims();
if (dims.size() <= 0) {
NSLog(@"scores dims error ");
return;
}
//获取当前的推理结果
float *score_data = static_cast<float*>(scores->GetData());
NSLog(@"scores is %f ",score_data[0]);
TNN iOS非图像模型入门的更多相关文章
- iOS 非ARC基本内存管理系列 -手把手教你ARC——iOS/Mac开发ARC入门和使用(转)
手把手教你ARC——iOS/Mac开发ARC入门和使用 Revolution of Objective-c 本文部分实例取自iOS 5 Toturail一书中关于ARC的教程和公开内容,仅用于技术交流 ...
- 转 iOS Core Animation 动画 入门学习(一)基础
iOS Core Animation 动画 入门学习(一)基础 reference:https://developer.apple.com/library/ios/documentation/Coco ...
- GAN实战笔记——第二章自编码器生成模型入门
自编码器生成模型入门 之所以讲解本章内容,原因有三. 生成模型对大多数人来说是一个全新的领域.大多数人一开始接触到的往往都是机器学习中的分类任务--也许因为它们更为直观:而生成模型试图生成看起来很逼真 ...
- iOS开发-UI 从入门到精通(三)
iOS开发-UI 从入门到精通(三)是对 iOS开发-UI 从入门到精通(一)知识点的综合练习,搭建一个简单地登陆界面,增强实战经验,为以后做开发打下坚实的基础! ※在这里我们还要强调一下,开发环境和 ...
- iOS开发-UI 从入门到精通(二)
iOS开发-UI 从入门到精通(二)是对 iOS开发-UI 从入门到精通(一)知识点的巩固,主要以习题练习为主,增强实战经验,为以后做开发打下坚实的基础! ※开发环境和注意事项: 1.前期iOS-UI ...
- iOS实现图像的反色,怀旧,色彩直方图效果
反色是与原色叠加可以变为白色的颜色,即用白色(RGB:1.0,1.0,1.0)减去原色的颜色.比如说红色(RGB:1.0,0,0)的反色是青色(0,1.0,1.0).在OPENGL ES中为1. 通过 ...
- Python的异步编程[0] -> 协程[1] -> 使用协程建立自己的异步非阻塞模型
使用协程建立自己的异步非阻塞模型 接下来例子中,将使用纯粹的Python编码搭建一个异步模型,相当于自己构建的一个asyncio模块,这也许能对asyncio模块底层实现的理解有更大的帮助.主要参考为 ...
- IO阻塞模型、IO非阻塞模型、多路复用IO模型
IO操作主要包括两类: 本地IO 网络IO 本地IO:本地IO是指本地的文件读取等操作,本地IO的优化主要是在操作系统中进行,我们对于本地IO的优化作用十分有限 网络IO:网络IO指的是在进行网络操作 ...
- JVM内存模型入门
JVM内存模型入门 本文是学习笔记,原文地址在:https://www.bilibili.com/video/av62009886 综述 其实没有太多新东西 JVM主要分为五个区域:栈区.堆区.本地方 ...
随机推荐
- SpringBoot总结之Spring Data Jpa
一.Spring Data Jpa简介 JPA(Java Persistence API)定义了一系列对象持久化的标准,目前实现这一规范的产品有Hibernate.TopLink等. Spring D ...
- Python (paramiko) 连接Linux服务器
目录 参考资料 Paramiko 安装 连接Linux 文件上传/下载 文件封装 其他 参考资料 https://www.liujiangblog.com/blog/15/ https://blog. ...
- 微信小程序云开发-云存储-获取带图片的商品列表
一.将商品图片上传至云存储 如下图,已准备5张商品图片,并且已经将商品图片上传至云存储 二.数据库表添加图片字段 在数据库表goods添加字段image,该字段用来存储图片的url信息 image在 ...
- 选择排序(selection_sort)——Python实现
# 选择排序 # 作用:对给出的n个顺序不定的数进行排序 # 输入:任意数组A # 输出:按顺序排列的数组A # 时间复杂度 (n(n-1))/2 # 选择排序 # 第一趟:选择第一个元素,依次与 ...
- jvm源码解读--01 jvm加载java/lang/object过程
现在做一下记录,这个看了两天,看的过程发现了很多c++的高级特性,没接触过,还得慢慢撸,禁止很慢 那么现在开始 吧 先打两个断点 java.c:351 JavaMain(void * _args) { ...
- 如何临时发布部署Cocos小游戏到Linux服务器,让别人能在微信打开
两个星期前,我们发布了第一个小游戏教程: 教程:制作一个小游戏送给喜欢的TA(不会编程也能学会哦) 上周有好几位小伙伴在b站催更,呃,作为小透明,收到催更信息后还是很激动的!竟然有同学在看我们的小教程 ...
- pwnable.kr之simple Login
pwnable.kr之simple Login 懒了几天,一边看malloc.c的源码,一边看华庭的PDF.今天佛系做题,到pwnable.kr上打开了simple Login这道题,但是这道题个人觉 ...
- 电脑常用快捷键及常用的DOS命令
电脑常用快捷键 Ctrl+C:复制 Ctrl+V:粘贴 Ctrl+A:全选 Ctrl+X:剪切 Ctrl+Z:撤销 Ctrl+S:保存 Alt+F4:关闭窗口 Shift+delete:永久删除 Wi ...
- configmap使用方法
说明: kubernetes统一配置管理方案configmap,实现将配置文件从容器镜像中解耦,增强应用的可移植性.数据可直接注入pod对象中,为容器所使用,注入方式有挂载为存储卷和传递为环境变量两种 ...
- STM32启动文件详解及SystemInit函数分析(转)
;先在RAM中分配系统使用的栈,RAM的起始地址为0x2000_0000 ;然后在RAM中分配变量使用的堆 ;然后在CODE区(flash)分配中断向量表,flash的起始地址为0x0800_0000 ...