查看原文
其他

阿里巴巴重磅开源MNNKit:基于MNN的移动端深度学习SDK,支持安卓和iOS

机器之心 开发者技术前线 2020-10-08
机器之心报

  点击上方“开发者技术前线”,选择“星标”

13:21 在看|留言|真爱


来自:机器之心   参与:一鸣、Jamin

近来,有越来越多的深度学习框架开始面向移动端进行发展。近日,阿里也基于其 MNN 推理引擎开源了最新的 MNNKit 深度学习 SDK,安卓和 iOS 开发者都可以方便地进行调用。

近年来,很多企业都在研发面向移动端的深度学习框架。在国内有 小米的 Mace、腾讯的 FeatherCNN(腾讯 AI)和 ncnn(腾讯优图)、百度的 Paddle-moblie 等。而阿里也开发了自己的移动端深度学习框架 MNN。

近日,阿里开源了基于 MNN 引擎的项目 MNNKit,面向安卓和 iOS,以 SDK 的方式提供 AI 端侧推理能力。开发者不需要了解算法细节就可以直接使用。

项目地址:https://github.com/alibaba/MNNKit

目前,MNNKit 已经有人脸检测、手势识别、人像分割等,后续可能有更多 API 接入。

MNNKit:基于 MNN 的深度学习工具

MNN 是基于阿里的 MNN 端上推理引擎所开发的应用解决方案,主要面向安卓和 iOS 系统,帮助将 AI 能力应用在实际的移动端场景中。

MNNKit 架构

MNNKit 提供了一个 SDK 供开发者使用,以下为 SDK 的架构。


从图中可以看出,MNNKit 可以分为三层结构,从底向上分别为:

  1. MNN 引擎层,是 MNN (https://github.com/alibaba/MNN) 库在 Android/iOS 上编译好的包的二进制 Release 版本,提供端侧运行环境。

  2. Core 基础层,这主要抽象和封装与 MNN c++接口调用粒度基本一致的上层 API,iOS 通过 OC 接口提供,Android 通过 Java 接口提供(TODO)。这一层同时也为上层 SDK 提供一些公共服务类或结构定义。

  3. 业务 Kit 层,包括了人脸检测、手势识别封装的 API。据项目介绍,之后的业务 Kit 层会不断扩展。


内部原理

因为 MNNKit 主要提供阿里的端侧 AI 能力,因此封装了很多相关应用的 API。调用如下:


例如,当用户需要调用 API 的时候,需要首先创建实例,然后将图像、视频或其他结构化数据输入,进行 AI 模型的推理工作。工作完成后释放实例即可。

目前 MNNKit 已支持的 API 有:

  • 人脸检测 API 

  • 手势识别 API 

  • 人像分割 API 


以人脸检测为例,检测内容主要分为三大板块:

  • 人脸基本信息


  • 人脸位置的矩形坐标

  • 106 个关键点坐标(区分被遮挡的和未被遮挡的)

  • 置信度


106 个关键点的分布(来自官方开源 github)

人脸各区域关键点分布对应表

  • 欧拉角度


摇头(Yaw)、点头(Pitch)、歪头(Roll)三个角度值

  • 脸动作(包含 5 个人脸的动作)

  •  眨眼

  •  张嘴

  •  摇头

  •  点头

  •  扬眉


处理过程

我们知道了人脸检测需要检测的数据后,接下来看看处理过程:


如图所示,该流程是 iOS 和安卓设备后置摄像头正向拍摄后,在移动端上的整体处理过程。

首先,系统从摄像头获取数据,作为 SDK 的输入。接着,SDK 会进行如下操作:

  1. 在 MNN 引擎执行推理之前,对原始的输入进行预处理,保证输入数据中的人脸为正向

  2. 使用 AI 模型进行推理;

  3. 推理后,产生基于输入图像(预处理之后的)坐标系的关键点结果;。

  4. 把关键点坐标变换到和屏幕渲染坐标系相同的方向,方便渲染。


程应用中,最后的结果关键点要显示在用户屏幕上,前端会使用一个用来渲染的"画布"。画布的坐标系被称为渲染坐标系,

在 SDK 检测的最后一步,我们将关键点变换到和渲染坐标系相同的方向,然后等比例映射关键点坐标到渲染坐标系的坐标即可。映射后可以直接渲染到画布上

代码示例

MNNKit 提供了包括人脸检测、手势识别等方面的示例代码。接下来我们以人脸检测为例,看看怎样可以在安卓或 iOS 中调用 API 进行推理工作。

安卓代码

前文提到,调用 API 需要首先创建一个实例,以下为异步创建 FaceDetector 实例,主线程中回调的代码。

public static void createInstanceAsync (Context context, FaceDetectorCreateConfig createConfig, InstanceCreatedListener<FaceDetector> listener)

在这里,人脸检测 API 会进行检测和跟踪两个动作。检测会遭到人脸位置和关键点,而跟踪是在人脸移动时重新定位关键点的位置。

在视频模式下,系统默认每 20 帧检测一次,其余帧只跟踪。图片模式下则每一次调用都检测。

创建实例后,可以将数据输入模型进行推理。MNNKit 现在已支持多种数据格式输入。在视频流检测场景中,我们可以使用摄像头的回调数据作为接口的输入。输入数据的代码如下:

public synchronized FaceDetectionReport[] inference(byte[] data, int width, int height, MNNCVImageFormat format, long detectConfig, int inAngle, int outAngle,  MNNFlipType outputFlip)

使用输入数据为 bitmap 的推理代码如下:

public synchronized FaceDetectionReport[] inference(Bitmap bitmap, long detectConfig, int inAngle, int outAngle, MNNFlipType outputFlip)

当 FaceDetector 实例用完之后,我们需要手动释放实例,否则会产生 native 的内存泄露。

public synchronized void release()

iOS 代码

和安卓代码类似,首先需要创建人脸检测实例:

+ (void)createInstanceAsync:(MNNFaceDetectorCreateConfig*)config Callback:(void(^)(NSError *error, MNNFaceDetector *faceDetector))block CallbackQueue:(dispatch_queue_t)callbackQueue;

默认主线程回调:

+ (void)createInstanceAsync:(MNNFaceDetectorCreateConfig*)config Callback:(void(^)(NSError *error, MNNFaceDetector *faceDetector))block;

PixelBuffer 输入进行推理的代码如下:

- (NSArray<MNNFaceDetectionReport *> *)inference:(CVPixelBufferRef)pixelBuffer Config:(MNNFaceDetectConfig)detectConfig Angle:(float)inAngle OutAngle:(float)outAngle FlipType:(MNNFlipType)flipType error:(NSError *__autoreleasing *)error;

UIImage 输入进行推理的代码如下:

- (NSArray<MNNFaceDetectionReport *> *)inferenceImage:(UIImage*)image Config:(MNNFaceDetectConfig)detectConfig Angle:(float)inAngle OutAngle:(float)outAngle FlipType:(MNNFlipType)flipType error:(NSError *__autoreleasing *)error;

使用通用 buffer 数组输入的代码如下:

- (NSArray<MNNFaceDetectionReport *> *)inference:(unsigned char*)data Width:(float)w Height:(float)h Format:(MNNCVImageFormat)format Config:(MNNFaceDetectConfig)detectConfig Angle:(float)inAngle OutAngle:(float)outAngle FlipType:(MNNFlipType)flipType error:(NSError *__autoreleasing *)error;

实例生命周期结束后,会自动触发相关内存的释放,无需调用方手动释放。

据悉,MNNKit 是 MNN 团队在阿里系应用大规模业务实践后的成熟解决方案,历经双十一等项目考验,在不依赖于后端的情况下进行高性能推理,使用起来稳定方便。

前段时间,来自SAP(全球第一大商业软件公司)的梁劲(Jim Liang)公开了自己所写的一份 520 页的学习教程(英文版),详细、明了地介绍了机器学习中的相关概念、数学知识和各种经典算法。编者看到后,也迫不及待的推广给更多的读者。完整的 PDF 请从文后在下面的公众号回复“机器学习”获取。

其他机器学习干货,请后台回复“机器学习”获取。


极 高 的 学 习 曲 线


  • 首当其冲就是数学,涉及统计学、微积分、概率、线性代数等,大家虽然都学过高等数学,但如果你还记得里面的细节,算你牛。更可能的情况是,多数人都对高等数学忘记了,面对各种算法里的大量公式,感到厌恶,甚至恐惧。

  • 其次因为机器学习本身是一个综合性学科,而且是一个快速发展的学科,知识点散乱,缺乏系统性。

  • 市面上的机器学习/深度学习书籍、文章、教程,遍地开花,但能以清晰的方式表达、循序渐进地讲解的教程,其实不多,大量的教程没有考虑到学习者的基础,使得初学者感到挫败和困惑。


图 解 机 器 学 习


正是对机器学习的过程中的痛苦有切身体会,我希望能做一份教程,以浅显易懂的方式去讲解它,降低大家的学习门槛。我为此花费了数月时间,经常做到深夜,把自己的学习笔记整理成了这份教程。


从结构来看,全部教程包含两部分:



Part 1 介绍了基本概念,包括:


  • 机器学习的流程

  • 数据处理

  • 建模

  • 评估指标(如 MSE、ROC 曲线)

  • 模型部署

  • 过度拟合

  • 正则化等


在第一部分,作者先介绍了如今应用普遍的机器学习:从自动驾驶、语音助手到机器人。其中有些思想,也是众多读者们了解过的,例如:为何机器学习在这个时候会火(大数据、计算力、更好的算法);机器学习、人工智能、深度学习三者的关系等。


除了这些基础概念,这份教程也对机器学习模型的开发流程做了图像化展示(如下图),即使对此不太了解的读者,也能通过这种流程展示有所学习。


建立机器学习解决方案的步骤


在 Part1 的其他小节,作者以类似的图像展示,对数据、建模、模型部署等内容做了详细介绍,这里就不一一列举,可以从原报告查看。


在 Part2,作者介绍了 常用的算法,包括:


  • 线性回归

  • 逻辑回归

  • 神经网络

  • SVM

  • Knn

  • K-Means

  • 决策树

  • 随机森林

  • AdaBoost

  • 朴素贝叶斯

  • 梯度下降

  • 主成分分析


这部分包含了大量的数学公式,但作者尽力注解了其中的每个公式,从而充分、清晰地表达了众多数学概念。


例如在「神经网络」部分,作者整理了 59 页的笔记(从 311 页到 369 页)。作者从人脑中的神经元架构说起,介绍了人工神经网络(ANN)、人工神经元工作的原理。这份笔记非常注重图像化的概念解释,理解起来非常直观。


例如,下图中的概念解释很形象地展现了生物神经元和人工神经元工作方式的相似性。


生物神经元的树突输入-轴突输出模式和人工神经元的输入输出模式对比。


过拟合的解释。


人工神经元的基础结构。


在涉及到数学公式时,作者会在旁边有详细的注解,如下图所示:



对于并列的可选项(如激活函数、常用神经网络架构等),也会有全面的列表:


常用的激活函数。


然后会有每个激活函数的单独介绍:



Sigmoid 激活函数。


用神经网络分类手写数字的前向传播示例(softmax 激活函数)。


对于神经网络中较为复杂的概念(如求导、反向传播),几张图就能解释清楚:



关于神经网络的完整训练过程,作者用简略流程图+计算细节展开的方式呈现:


反向传播算法完整流程。


前向传播部分的计算细节。


就像前面提到的,这部分除了「神经网络」的介绍,还包括随机森林、梯度下降等概念的介绍,读者们可查看原教程。


520页机器学习干货笔记,请在下面公众号后台回复“机器学习”获取。


总结


看完这份教程之后,小编觉得这是一份包罗万象的学习笔记,既适合非专业人士了解有关机器学习的基础概念,又适合有专业背景的学生进一步学习。


写教程是为了自己持续学习,分享教程是为了帮助更多人学习。就像作者所说,「Learning by doing/teaching, 写这个教程主要是强迫自己持续学习,另外,也想分享给他人,希望能帮助到更多想学习 Machine Learning 的人,降低大家的学习痛苦。




END

好文点个在看吧!

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存