转:移动开发的未来,端上计算的一次尝试-MNN

简述

AI已经侵入我们的生活,人脸识别、语言识别、智能音响等等无处不在,但很早之前的AI数据的处理、模型推理等都在云端,随着时间和需求的变化,聪明的研究者开始把AI的推理训练放到终端(手机设备、IoT设备等)来做,MNN框架是阿里推出的端侧推理引擎

本文主要目的在于介绍下端上计算的过程,了解什么是端上计算,为移动开发者入门学习提供思路,下面我们来一起探讨学习下吧,如果对你有用记得点赞鼓励❤

为什么要进行端上计算

传统智能计算的过程

简述下基本流程

  1. 终端收集数据到服务端
  2. 服务端根据收集的数据使用算法进行模型训练,最终产生可以商用的模型,然后部署
  3. 这一步就是推理阶段了,终端把用户的数据传送给服务端,服务端利用模型进行推理计算,然后返回结果给终端
  4. 终端根据结果做相应的操作

由上面的流程可知,存在几个问题

  1. 数据隐私性,需要把数据上报给服务端,而且如果用户不授权的话则收取不到
  2. 网络延迟,终端必须等待网络请求完成才能做出响应,这不适合实时操作强的任务
  3. 算力集中,完全依赖服务器的算力

端上计算优势

端上计算其实是把推理和训练过程放在终端进行,这样做有如下优势

  1. 响应速度快,不依赖云端服务的请求,可快速做出决策,目前很多应用已经在使用,如淘宝、咸鱼、抖音等
  2. 数据隐私安全,政策对数据隐私的管控越来越严格,想把数据上传到服务端越来越难
  3. 节省服务器资源
  4. 发挥联合计算的优势,虽然一台手机/IoT设备的算力有限,但是如果把所有的设备算力集合在一起,将远远超越云服务的算力,不过这个方向还在发展中

安装

本文以iOS平台为例进行安装,相比于其他库,MNN的安装略微有点复杂,官方文档也不是特别健全(根据个人爱好可以参照官网的教程),总之遇到问题就解决吧

下载MNN源码

git clone https://github.com/alibaba/MNN.git
复制代码

安装操作

第一步

进入仓库的主目录:MNN

第二步:

基础依赖项的检查:cmakeprotobufC++编译器(gcc\clang),如果没有安装自行查找安装

官方对依赖的版本要求及检查命令如下表:

依赖项 建议版本 检查是否安装的命令
cmake 理论依赖3.0以上即可,但建议版本以及测试环境中的版本都为3.10+ cmake -v
protobuf version >= 3.0 is required protoc --version
C++编译器 GCCClang皆可,version >= 4.9,对于macOS已经默认安装Clang clang -v 或者 gcc -v

第三步:

编译模型转化器:MNNConvert,整个编译过程需要几分钟

MNNConvert的主要作用是什么?模型训练可以通过不同的框架进行如:TensorFlow、Caffe等,它们产生的模型格式都不一样,要放在MNN中运行,就需要转化成MNN支持的格式

1\. cd MNN/
2\. ./schema/generate.sh
3\. mkdir build
4\. cd build
5\. cmake .. -DMNN_BUILD_CONVERTER=true && make -j4
复制代码

第四步:(可选)

下载demo需要的模型然后转换成MNN支持的模型,主要用于demo工程使用,可以跳过

特别注意: 这一步会经常遇到两个问题:

  1. 忘记先编译好模型转化器:MNNConvert(第三步)
  2. 下载demo模型时,容易下载失败,可能是被墙或其他原因,如果一直失败的话可以把模型手动下载下来,然后进行转换(大致操作就是修改./tools/script/get_model.sh脚本,注释掉下载逻辑,然后手动下载完成之后,再执行下面的命令,操作不成功的可以评论或者加微信交流)

MNN主目录下执行如下命令

./tools/script/get_model.sh
复制代码

第五步:

Xcode打开project/ios/MNN.xcodeproj,点击编译即可,这样就把完整的MNN库编译出来了

总结:

其实这个安装过程做了三件事

  1. 编译模型转换器MNNConvert,主要用来把其他框架产生的模型(如:tf、caffemodel)转换成MNN可用的模型
  2. 下载demo模型,并利用MNNConvert转换成MNN模型,这一步是为了demo工程提供模型的,所以可选步骤
  3. 编译MNN

总体看来,如果你是用来开发和调试源码的话,那么MNNConvert肯定要编译好,MNN库也要编译好,如果只是想看下demo工程,那么上面的那些都不用做,直接下载下面的demo工程跑起来看下

demo工程

学习一个框架直接的方式就是看它的demo如何使用,上面的安装步骤提到,由于demo用到了第三方开源的模型,所以必须要先完成上面安装操作的第四步, 然后找到路径MNN/demo下的demo工程,打开直接run即可

在demo工程可以进行源码调试、api用法等,赶快去学习吧!

执行推理的过程

不考虑技术细节站在更高的角度看MNN,其实MNN主要做的事情就是推理(之后可能还会增加训练),那么猜测下需要做哪些事情如:加载模型、输入数据、输出结果等。我们以demo工程为例来研究下推理的过程

模型加载:Interpreter & Session

整个过程我们把它比喻成浏览器加载网页

Interpreter:模型解释器,就像浏览器的引擎则用来解释网页、分析网页结构等进行渲染

Session: 会话,网页渲染完成,总要进行会话操作的,比如请求个图片、点击button等,就是一次通信过程,而在MNN中,Session就是一次推理的过程,持有推理数据

所以Interpreter加载模型,Session负责推理数据,Session通过Interpreter创建,一个Interpreter可以创建多个Session,下面看下源码解析

Interpreter解释器和Session对象

声明

@interface Model : NSObject {
    std::shared_ptr<MNN::Interpreter> _net; // 解释器,用来持有模型数据的
    MNN::Session *_session; // 会话,推理数据的持有者
}
复制代码

Model类中,声明了解释器对象_net和会话对象_session,这是个基类,因为不同类型的模型会创建自己的Model,并继承Model

创建Interpreter

// 获取模型所在的路径
NSString *model = [[NSBundle mainBundle] pathForResource:@"mobilenet_v2.caffe" ofType:@"mnn"];
// 从磁盘加载模型,当然也是支持从内存读取的
_net = std::shared_ptr<MNN::Interpreter>(MNN::Interpreter::createFromFile(model.UTF8String));

复制代码

创建会话

- (void)setType:(MNNForwardType)type threads:(NSUInteger)threads {
    MNN::ScheduleConfig config; // 一些配置,暂时忽略
    config.type      = type;
    config.numThread = (int)threads;
    if (_session) { // 释放旧的session
        _net->releaseSession(_session);
    }
    // 创建新session
    _session = _net->createSession(config);
}
复制代码

到此模型加载和准备工作就完成了,下面介绍下如何输入数据

输入和运行数据

模型加载完成,就要开始推理了,其实不要想太复杂,就几个接口而已,作为入门先看懂骨架再看细节吧

数据容器

输入数据,自然需要容器承载这些数据,在MNN中设计了Tensor类用来作为数据的容器,看下面的解释

/**
 * data container. 这个注释已经说明,这个类是数据的容器
 * data for host tensor is saved in `host` field. its memory is allocated malloc directly.
 * data for device tensor is saved in `deviceId` field. its memory is allocated by session's backend.
 * usually, device tensors are created by engine (like net, session).
 * meanwhile, host tensors could be created by engine or user.
 */
class MNN_PUBLIC Tensor {
public:
    struct InsideDescribe;

    /** dimension type used to create tensor */
    enum DimensionType {
        /** for tensorflow net type. uses NHWC as data format. */
        TENSORFLOW,
        /** for caffe net type. uses NCHW as data format. */
        CAFFE,
        /** for caffe net type. uses NC4HW4 as data format. */
        CAFFE_C4
    };

    /** handle type */
    enum HandleDataType {
        /** default handle type */
        HANDLE_NONE = 0,
        /** string handle type */
        HANDLE_STRING = 1
    };
  ....
}
复制代码

输入数据&运行

数据输入返回的就是Tensor对象,核心代码就一句(多种输入方式不多介绍,本文以入门为主)

  • 输入数据函数getSessionInput 的定义
Tensor* Interpreter::getSessionInput(const Session* session, const char* name){}
复制代码
  • demo工程的示例代码
// 输入数据,返回Tensor对象input
auto input = _net->getSessionInput(_session, nullptr);
MNN::Tensor tensorCache(input);
input->copyToHostTensor(&tensorCache);
for (int i = 0; i < cycles; i++) {
    input->copyFromHostTensor(&tensorCache);
    // 开始run
    _net->runSession(_session);
}
...
复制代码

获取结果

即在推理run完成之后,我们需要获取结果,返回的也是Tensor对象

  • 获取结果的函数getSessionOutput定义
Tensor* Interpreter::getSessionOutput(const Session* session, const char* name) {}
复制代码
  • demo工程示例代码
// 获取结果对象output
MNN::Tensor *output = _net->getSessionOutput(_session, nullptr);
MNN::Tensor copy(output);
output->copyToHostTensor(&copy);
float *data = copy.host<float>();
...
复制代码

小结

这个过程旨在介绍整个框架的使用过程,结合demo工程理解更快,并没有过多深入,希望能快速入门

MNNKit

有时候会思考一些问题:其实进行智能计算,我们只需要一个合适的模型然后利用它进行推理计算,那么模型就是可以复用的,没必要每个人都要重新训练一套模型

对于这个问题,阿里就把超级成熟的模型放出来给大家用了,这些模型已经在淘宝等app上实践过,它就是MNNKit, 基于端上推理引擎MNN提供的系列应用层解决方案,目前开放了三个模型,有需要的开发者可以直接拿来玩了

Kit SDK 功能
FaceDetection 人脸识别
HandGestureDetection 手势识别
PortraitSegmentation 人像分割

MNNKit的组织结构

(直接引用了GitHub库的描述)

image

<figcaption></figcaption>

MNN层: 最核心层,提供了模型加载和推理

MNNKit Core: 主要针对MNN的C++接口的封装和抽象,转化成更高级别的OC或Java实现的API,方便调用者使用

业务层: 主要针对具体的算法模型的封装,主要给业务使用的

总结

端上计算需要做什么?对于移动开发者来说初次接触AI开发很是陌生,该怎么入手AI开发呢,个人目前也在学习中,有一些深刻又吐血的经验分享:

如果你对数学有一定的熟悉的话,千万别one by one的从头开始学数学,这真的太低效了,建议先从开发者最熟悉的代码层面入手,了解AI的基本工作流程,如学学MNN怎么用的,你就会知道原来就是拿模型去推理然后得到结果反馈给用户

然后在学会怎么训练模型,建议从简单的机器学习算法入手,根据算法需要用的数学公式,然后查这些公式的用法,边学边用更好理解

作者:Monkery
链接:https://juejin.im/post/5e295664e51d45305a03c0a9

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容

  • 一. Java基础部分.................................................
    wy_sure阅读 3,731评论 0 11
  • 解析URL 输入URL后,会进行解析(URL的本质就是统一资源定位符) URL一般包括几大部分: protocol...
    小超人的前端之路阅读 723评论 0 1
  • 体验入 杰克19电来输液,来的时候很虚弱,考虑到狗狗年纪大了,而且也很虚弱,输液的速度不能太快,输液量又不小,可能...
    93650345d0d1阅读 112评论 0 2
  • 感恩心想生老师分享的自我毁灭一课,自在大学就是来唤醒本自具足的你。这堂课程你需要好好理解。 信愿行证,相信、愿望、...
    实现幸福的人生阅读 375评论 0 0
  • 人生,能有几回?生命,能有几次? 哪有什么永远? 更别说来日方长了, 生而为人我们都只有一次, 常常因为自己的忙碌...
    漠洋阅读 313评论 0 2