- 原文地址:iOS 11: Machine Learning for everyone
- 原文做者:Matthijs Hollemans
- 译文出自:掘金翻译计划
- 译者:Changkun Ou
- 校对者:wilsonandusa atuooo
WWDC 2017 使一件事情变得很是清楚,那就是:Apple 正在尽心尽力地支持「设备上的机器学习」了。前端
他们但愿 App 的开发者们可以尽量的简单的加入他们的行列中。python
Apple 去年发布了能够用于建立基本的卷积神经网的 Metal CNN 和 BNNS 框架。今年,Metal 获得了进一步扩展,增长了一个全新的计算机视觉框架,以及 Core ML:一个可以轻松地将机器学习集成到 App 中的工具包。react
在这片文章中,我将就 iOS 11 和 macOS 10.13 中这些新推出的机器学习的内容,分享我本身的一些想法和经验。android
Core ML 在 WWDC 上得到了极大的关注度,缘由很简单:大部分开发者但愿可以在他们的 App 中使用这个框架。ios
Core ML 的 API 很是简单。你只能用它作这些事情:git
这看起来好像颇有限,但实际上你通常只会在 App 中加载模型和作出预测这两件事。github
在 Core ML 以前,加载训练好的模型是很是困难的 —— 实际上,我写过一个框架来减轻这种痛苦。因此如今我对这一个简单的两步过程感到很是高兴。编程
模型被包含在了一个 .mlmodel 的文件中。这是一种新的开源文件格式,用于描述模型中的 layer、输入输出、标签,以及须要在数据上产生的任何预处理过程。它还包括了全部的学习参数(权重和偏置)。swift
使用模型所需的一切都在这一个文件里面了。后端
你只须要将 mlmodel 文件放入你的项目中,Xcode 将会自动生成一个 Swift 或 Objective-C 的包装类,使你能简单的使用这个模型。
举个例子,若是你把文件 ResNet50.mlmodel 添加到你的 Xcode 项目中,那么你就能够这么写来实例化这个模型:
let model = ResNet50()复制代码
而后作出预测:
let pixelBuffer: CVPixelBuffer = /* your image */if let prediction = try? model.prediction(image: pixelBuffer) {
print(prediction.classLabel)
}复制代码
这差很少就是全部要写的东西了。你不须要编写任何代码来加载模型,或者将其输出转换成能够从 Swift 直接使用的内容 —— 这一切都将由 Core ML 和 Xcode 来处理。
注意: 要了解背后发生了什么,能够在 Project Navigator 里选择 mlmodel 文件,而后点击 Swift generated source 右边的箭头按钮,就可以查看生成的帮助代码了。
Core ML 将决定本身究竟是在 CPU 上运行仍是 GPU 上运行。这使得它可以充分的利用能够用的资源。Core ML 甚至能够将模型分割成仅在 GPU 上执行的部分(须要大量计算的任务)以及 CPU 上的其余部分(须要大量内存的任务)。
Core ML 使用 CPU 的能力对于咱们开发者来讲另外一个很大的好处是:你能够从 iOS 模拟器运行它,从而运行那些对于 Metal 来讲作不到,同时在单元测试中也不太好的任务。
上面的 ResNet50 例子展现的是一个图像分类器,可是 Core ML 能够处理几种不一样类型的模型,如:
全部这些模型均可以用于回归问题和分类问题。此外,你的模型能够包含这些典型的机器学习预处理操做,例如独热编码(one-hot encoding)、特征缩放(feature scaling)、缺失值处理等等。
Apple 提供了不少已经训练好的模型可供下载,例如 Inception v三、ResNet50 和 VGG16 等,但你也可使用 Core ML Tools 这个 Python 库来转换本身的模型。
目前,你能够转换使用 Keras、Caffe、scikit-learn、XGBoost 和 libSVM 训练的模型。转换工具只会支持具体指定的版本,好比 Keras 支持 1.2.2 但不支持 2.0。辛运的是,该工具是开源的,因此毫无疑问它未来会支持更多的训练工具包。
若是这些都不行,你仍是能够随时编写本身的转换器。mlmodel 文件格式是开源且能够直接使用的(由 Apple 制定发布的一种 protobuf 格式)
若是你想在你的 App 上立刻运行一个模型, Core ML 很不错。然而使用这样一个简单的 API 必定会有一些限制。
若是你可以忍受这些限制,那么 Core ML 对你来讲就是正确的选择。
不然的话,若是你想要彻底的控制权,那么你必须使用 Metal Performance Shader 或 Accelerate 框架 —— 甚至一块儿使用 —— 来驱动你的模型了!
固然,真正的黑魔法不是 Core ML,而是你的模型。若是你连模型都没有,Core ML 是没有用的。而设计和训练一个模型就是机器学习的难点所在……
我写了一个使用了 Core ML 的简单的示例项目,和往常同样,你能够在 GitHub 上找到源码。
这个示例程序使用了 MobileNet 架构来分类图片中的猫。
最初这个模型是用 Caffe 训练得出的。我花了一点时间来搞清楚如何将它转换到一个 mlmodel 文件,可是一旦我有了这个转换好的模型,便很容易集成到 App 中了(转换脚本包含在 GitHub 中)。
虽然这个 App 不是颇有趣 —— 它只输出了一张静态图片的前五个预测值 —— 但却展现了使用 Core ML 是多么的简单。几行代码就够了。
注意: 示例程序在模拟器上工做正常,可是设备上运行就会崩溃。继续阅读来看看为何会发生这种状况 ;-)
固然,我想知道发生了什么事情。事实证实 mlmodel 实际上被编译进应用程序 bundle 的 mlmodelc 文件夹中了。这个文件夹里包含了一堆不一样的文件,一些二进制文件,一些 JSON文件。因此你你能够看到 Core ML 是如何将 mlmodel 在实际部署到应用中以前进行转换的。
例如,MobileNet Caffe 模型使用了批量归一化(Batch Normalization)层,我验证了这些转换也存在于 mlmodel 文件中。可是在编译的 mlmodelc 中,这些批量归一化 layer 彷佛就被移除了。这是个好消息:Core ML 优化了该模型。
尽管如此,它彷佛能够更好的优化该模型的结构,由于 mlmodelc 仍然包含一些没必要要的 scaling layer。
固然,咱们还处在 iOS 11 beta 1 的版本,Core ML 可能还会改进。也就是说,在应用到 Core ML 以前,仍是值得对模型进一步优化的 —— 例如,经过「folding」操做对 layer 进行批量归一化(Batch Normalization) —— 但这是你必须对你的特性模型进行测量和比较的东西。
还有其余一些你必须检查的:你的模型是否在 CPU 和 GPU 上运行相同。我提到 Core ML 将选择是否在 CPU 上运行模型(使用 Accelerate 框架)或 GPU(使用 Metal )。事实证实,这两个实现可能会有所不一样 —— 因此你两个都须要测试!
例如,MobileNet 使用所谓的「depthwise」卷积层。原始模型在 Caffe 中进行训练,Caffe 经过使正常卷积的 groups
属性等于输出通道的数量来支持 depthwise 卷积。所获得的 MobileNet.mlmodel 文件也同样。这在 iOS 模拟器中工做正常,但它在设备上就会崩溃!
发生这一切的缘由是:模拟器使用的是 Accelerate 框架,可是该设备上使用的倒是 Metal Performance Shaders。因为 Metal 对数据进行编码方式的特殊性, MPSCNNConvolution
内核限制了:不能使 groups 数等于输出通道的数量。噢嚯!
我向 Apple 提交了一个 bug,可是我想说的是:模型能在模拟器上运行正常并不意味着它在设备上运行正常。必定要测试!
我没有办法测试 Core ML 的速度,由于个人全新 10.5 寸 iPad Pro 下个星期才能到(呵呵)。
我感兴趣的是我本身写的 Forge 库和 Core ML (考虑到咱们都是一个早期的测试版)之间运行 MobileNets 之间的性能差别。
敬请关注!当我有数据能够分享时,我会更新这一节内容。
下一个要讨论的事情就是全新的 Vision 框架。
你可能已经从它的名字中猜到了,Vision 可让你执行计算机视觉任务。在之前你可能会使用 OpenCV,但如今 iOS 有本身的 API 了。
Vision 能够执行的任务有如下几种:
Core Image 和 AVFoundation 已经能够实现其中的一些任务,但如今他们都集成在一个具备一致性 API 的框架内了。
若是你的应用程序须要执行这些计算机视觉任务之一,不再用跑去本身实现或使用别人的库了 - 只需使用 Vision 框架。你还能够将其与 Core Image 框架相结合,以得到更多的图像处理能力。
更好的是:你可使用 Vision 驱动 Core ML,这容许你使用这些计算机视觉技术做为神经网络的预处理步骤。例如,你可使用 Vision 来检测人脸的位置和大小,将视频帧裁剪到该区域,而后在这部分的面部图像上运行神经网络。
事实上,任什么时候候当你结合图像或者视频使用 Core ML 时,使用 Vision 都是合理的。原始的 Core ML 须要你确保输入图像是模型所指望的格式。若是使用 Vision 框架来负责调整图像大小等,这会为你节省很多力气。
使用 Vision 来驱动 Core ML 的代码长这个样子:
// Core ML 的机器学习模型
let modelCoreML = ResNet50()复制代码
// 将 Core ML 连接到 Vision
let visionModel = try? VNCoreMLModel(for: modelCoreML.model)复制代码
let classificationRequest = VNCoreMLRequest(model: visionModel) {
request, error iniflet observations = request.results as? [VNClassificationObservation] {
/* 进行预测 */
}
}
let handler = VNImageRequestHandler(cgImage: yourImage)
try? handler.perform([classificationRequest])复制代码
请注意,VNImageRequestHandler
接受一个请求对象数组,容许你将多个计算机视觉任务连接在一块儿,以下所示:
try? handler.perform([faceDetectionRequest, classificationRequest])复制代码
Vision 使计算机视觉变得很是容易使用。 但对咱们机器学习人员很酷的事情是,你能够将这些计算机视觉任务的输出输入到你的 Core ML 模型中。 结合 Core Image 的力量,批量图像处理就跟玩儿同样!
我最后一个想要讨论的话题就是 Metal —— Apple 的 GPU 编程 API。
我今年为客户提供的不少工做涉及到使用 Metal Performance Shaders (MPS) 来构建神经网络,并对其进行优化,从而得到最佳性能。可是 iOS 10 只提供了几个用于建立神经网络的基本 kernel。一般须要编写自定义的 kernel 来弥补这个缺陷。
因此我很开心使用 iOS 11,可用的 kernel 已经增加了许多,更好的是:咱们如今有一个用于构建图的 API 了!
注意: 为何要使用 MPS 而不是 Core ML?好问题!最大的缘由是当 Core ML 不支持你想要作的事情时,或者当你想要彻底的控制权并得到最大运行速度时。
MPS 中对于机器学习来讲的最大的变化是:
递归神经网络。你如今能够建立 RNN,LSTM,GRU 和 MGU 层了。这些工做在 MPSImage
对象的序列上,但也适用于 MPSMatrix
对象的序列。这颇有趣,由于全部其余 MPS layer 仅处理图像 —— 但显然,当你使用文本或其余非图像数据时,这不是很方便。
更多数据类型。之前的权重应该是 32 位浮点数,但如今能够是 16 位浮点数(半精度),8 位整数,甚至是 2 进制数。卷积和 fully-connected 的 layer 能够用 2 进制权重和 2 进制化输入来完成。
更多的层。到目前为止,咱们不得不采用普通的常规卷积、最大池化和平均池化,可是在 iOS 11 MPS 中,你能够进行扩张卷积(Dilated Convolution)、子像素卷积(Subpixel Convolution)、转置卷积(Transposed Convolution)、上采样(Upsampling)和重采样(Resampling)、L2 范数池化(L2-norm pooling)、扩张最大池化(dilated max pooling),还有一些新的激活函数。 MPS 尚未全部的 Keras 或 Caffe layer 类型,但差距正在缩小...
更方便。使用 MPSImages
老是有点奇怪,由于 Metal 每次以 4 个通道的片断组织数据(由于图像由 MTLTexture
对象支持)。可是如今,MPSImage
有用于读取和写入数据的方法,这些数据不会让你感到困惑。
MPSCNNConvolutionDescriptor
还有一个新方法,可让你在 layer 上设置批量归一化参数。这意味着你再也不须要将批量归一化到卷积层中,而 MPS 会为你处理这些事情。很是方便!
性能改进。现有的内核变得更快。这老是好消息。 🏎
图 API。这是我最关心的消息。手动建立全部 layer 和(临时)图像老是使人讨厌的。如今你能够描述一个图,就像你在Keras 中同样。 MPS 将自动计算出图像须要多大,如何处理填充,如何设置 MPS 内核的 offset
等等。甚至能够经过融合不一样的 layer 来优化整个图。
看起来全部的 MPS 内核均可以使用 NSSecureCoding
进行序列化,这意味着你能够将图保存到文件中,而后将其还原。而且使用这个图来推断如今只是一个单一的方法调用。它不像 Core ML 那么简单,但使用 MPS 绝对比之前好用得多。
有一件事情我目前还不太清楚,那就是我不知道你是否能够编写本身的 kernel 并在这个图中使用。在我客户的工做中,我发现一般须要使用 Metel Shading 语言编写的自定义着色器来进行预处理步骤。据我所知,彷佛没有一个「MPSNNCustomKernelNode
」类。这还要再多研究一下!
结论:用于机器学习的 Metal Performance Shaders 已经在 iOS 11 中变得更增强大,可是大多数开发人员应该转而使用 Core ML(对于那些使用MPS的来讲)。
注意:新的图 API 使个人 Forge 库基本上过期了,除非你但愿在 App 中继续支持 iOS 10。我将尽快将示例应用移植到新的图 API 上,而后将写一个更详细的博客文章。
还有一些其余的更新:
Accelerate 框架: 彷佛 Accelerate 框架中的 BNNS 并无得到太多功能上的更新。它终于有了 Softmax 层,但 MPS 却没有新的 layer 类型。也许可有可无:使用 CPU 进行深层神经网络可能不是一个好主意。也就是说,我喜欢 Accelerate,它有不少好玩的东西。而今年,它确实得到了对稀疏矩阵的更多支持,很棒。
天然语言处理: Core ML不只仅只能处理图像,它还能够处理大量不一样类型的数据,包括文本。 使用的 API NSLinguisticTagger
类已经存在了一段时间,可是与 iOS 11 相比变得更加有效了。NSLinguisticTagger
如今已经能进行语言鉴别,词法分析,词性标注,词干提取和命名实体识别。
我没有什么 NLP 的经验,因此我没办法比较它与其余 NLP 框架的区别,但NSLinguisticTagger
看起来至关强大。 若是要将 NLP 添加到 App 中,此 API 彷佛是一个好的起点。
Apple 向咱们开发者提供全部的这些新工具都很是的好,可是大多数 Apple API 都有一些很重要的问题:
这三个东西加在一块儿意味着苹果的 API 总会落后于其余工具。若是 Keras 增长了一个很炫酷的新的 layer 类型,那么在 Apple 更新其框架和操做系统以前,你都没办法将它和 Core ML 一块儿使用了。
若是某些 API 获得的计算结果并非你想要的,你没办法简单的进去看看究竟是 Core ML 的问题仍是模型的问题,再去修复它 —— 你必须绕开 Core ML 来解决这个问题(并不老是可能的);要么就只能等到下一个 OS 发布了(须要你全部的用户进行升级)。
固然我不但愿 Apple 放弃他们的秘密武器,可是就像其余大多数机器学习工具开源同样,为何不让 Core ML 也开源呢? 🙏
我知道这对于 Apple 来讲不可能立刻发生,但当你决定在 App 中使用机器学习时,要记住上面的这些内容。
Matthijs Hollemans 于 2017 年 6 月 11 日
我但愿这篇文章对你有所帮助!欢迎经过 Twitter @mhollemans 或 Email matt@machinethink.net 联系我。
掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 Android、iOS、React、前端、后端、产品、设计 等领域,想要查看更多优质译文请持续关注 掘金翻译计划。