最近的苹果iPhone X发布会,你会看到iPhone X有一些很酷的功能,比如FaceID,Animoji和AR。我们需要弄明白建立这样一个系统需要什么。
当进一步研究时,得到的答案是苹果的官方机器学习工具CoreML。它适用于iPhone、Macbook、Apple TV、Apple watch,以及每一个苹果设备。
另一个有趣的信息是,苹果公司在最新的iphon上设计了一个定制的GPU和一个带有神经引擎(neural engine)深度加工的A11 Bionic(仿生)芯片,该芯片用于深度学习的优化。
“随着计算引擎的核心的日益强大,iPhone将会打开新的机器学习的途径,CoreML在未来的日子里的意义只会上升。”
在这篇文章的结尾,你将知道Apple CoreML是什么,以及它为什么会获得动力。我们还将通过构建iPhone的垃圾信息分类应用程序来研究CoreML的实现细节。
我们将客观地看待这篇文章的利弊。
苹果公司今年在他们的年度开发者大会WWDC(https://developer.apple.com/wwdc/)(相当于谷歌I / O会议)上发布了CoreML(https://developer.apple.com/documentation/coreml),并大肆宣传。为了更好地理解CoreML的作用,我们必须了解一些它的相关背景。
这并不是苹果第一次推出机器学习框架。去年,它还推出了一组同样的库:
不同的是,一个优化了CPU,而另一个优化了GPU。这样做的原因是,在推理过程中,CPU有时可能比GPU快。而在训练过程中,几乎每次都是GPU更快。
多个框架在开发人员之间造成了很大的混乱,因为它们非常接近硬件(为了高性能),因此很难进行编程。
CoreML为前两个库提供了另一个抽象化的层,并提供了一个简单的接口,以达到同样的效率水平。另一个好处是,在应用程序运行时,CoreML负责处理CPU和GPU本身之间的上下文转接。
“也就是说,例如,你有一个内存繁重的任务,该任务涉及文本处理(自然语言处理),CoreML将自动在CPU上运行它,如果计算像图像分类这样的繁重任务,它将使用GPU。如果应用程序中有两个功能,它也会自动处理这些功能,这样你就能在两个世界中获得最好的效果。”
CoreML还附带了三个建立在其上的库:
以上所有的库,都很容易使用,并提供了一个简单的接口来完成一系列任务。使用上述库,CoreML的最终结构将如下所示:
注意,上面的设计为iOS应用程序提供了一个很好的模块结构。对于不同的任务对应不同的层,可以以多种方式使用它们(例如,在应用程序中使用带有图像分类的NLP)。
可以在这里阅读更多关于这些库的内容:
视觉(https://developer.apple.com/documentation/vision)Foundation(https://developer.apple.com/documentation/foundation) 游戏工具包(https://developer.apple.com/documentation/gameplaykit)
要充分利用CoreML,需要遵循以下设置要求:
sudo easy_install pip
sudo pip install-U coremltools
登录后,需要验证Apple ID,你将收到与注册Apple ID的设备相同的通知。
选择“Allow”并在网站上输入给出的6位密码。
完成此步骤后,将显示一个下载选项,可以从那里下载Xcode。现在我们已经建立了自己的系统,并准备好继续执行实现部分。
我们将利用CoreML的力量来构建两种重要的方法。
开始:
将机器学习模型转换成CoreML格式
CoreML的优势之一是支持在其他流行的框架中建立训练机器学习模型的转换,比如sklearn,caffe,xgboost等。
“这并没有使数据科学社区疏远CoreML,因为他们可以在他们最喜欢的环境中进行实验,训练他们的模型,然后将其导入到他们的iOS / MacOS应用程序中。”
下面是CoreML支持的框架:
mlmodel是什么?
为了简化转换过程,苹果设计了自己的开放格式,用于表示跨框架机器学习模型,并命名为mlmodel。这个模型文件包含对模型各层的描述、输入和输出、类标签以及需要对数据进行的任何预处理。它还包含所有的学习参数(权重和偏差)。
转换流看起来是这样的:
在这个示例中,我们将在sklearn中构建一个垃圾信息分类器,然后将相同的模型转移到CoreML。
关于垃圾信息集合数据集
SMS垃圾信息集合v.1(http://www.dt.fee.unicamp.br/~tiago/smsspamcollection/)是一组公开的SMS标签的信息,已被用于手机垃圾信息的研究。它有一个集合,由5574个英语,真实和非编码信息组成,被标记为合法(ham)或垃圾信息。
可以从这里下载数据集(http://simplysanad.com/CoreML-on-iPhone/Complete%20App/coreml%20test/SMSSpamCollection.txt)。
构建基本模型
我们将在sklearn中建立一个使用LinearSVC
(http://scikit-learn.org/stable/modules/generated/sklearn.svm.LinearSVC.html)的基本模型。另外,我在信息文本中使用了 TF-IDF作为模型的一个特性。 TF-IDF是一种在自然语言处理中使用的技术,可以对基于唯一识别文档的文档进行分类。
这是它的代码:
import numpy as np
import pandas as pd
#Reading in and parsing data
raw_data= open('SMSSpamCollection.txt','r')
sms_data= []
for linein raw_data:
split_line= line.split("\t")
sms_data.append(split_line)
#Splitting data into messages and labels and training and test
sms_data= np.array(sms_data)
X= sms_data[:,1]
y= sms_data[:,0]
#Build a LinearSVC model
from sklearn.feature_extraction.textimport TfidfVectorizer
from sklearn.svmimport LinearSVC
#Build tf-idf vector representation of data
vectorizer= TfidfVectorizer()
vectorized_text= vectorizer.fit_transform(X)
text_clf= LinearSVC()
text_clf= text_clf.fit(vectorized_text, y)
模型创建完成。用垃圾信息对它进行测试。
#Test the model
print text_clf.predict(vectorizer.transform(["""XXXMobileMovieClub: To use your credit, click the WAP link in the next txt message or click here>> http://wap. xxxmobilemovieclub.com?n=QJKGIGHJJGCBL"""]))
模型运行良好,添加一些交叉验证。
#Cross - Validation
from sklearn.model_selectionimport cross_val_score
cross_score= cross_val_score(text_clf, vectorized_text, y, cv=10)
print cross_score
print "mean:",np.mean(cross_score)
我们已经构建了模型,需要将其转换为 .mlmodel格式,以便与CoreML兼容。我们将使用前面安装的coremltools程序包(https://pypi.python.org/pypi/coremltools)。下面的代码将把我们的模型转换为.mlmodel格式:
import coremltools
#convert to coreml model
coreml_model= coremltools.converters.sklearn.convert(text_clf,"message","spam_or_not")
#set parameters of the model
coreml_model.short_description= "Classify whether message is spam or not"
coreml_model.input_description["message"]= "TFIDF of message to be classified"
coreml_model.output_description["spam_or_not"]= "Whether message is spam or not"
#save the model
coreml_model.save("SpamMessageClassifier.mlmodel")
发生了什么?
首先导入python中的coremltools程序包。然后使用转换器转换模型,在这种情况下,我们使用converters.sklearn,因为我们必须转换在sklearn中建立的模型。然后,传递模型对象、输入变量名和. convert()中的输出变量名。接着,设置模型的参数,以添加更多关于输入、输出的信息,最后调用. save()来保存模型文件。
当双击模型文件时,它应该在Xcode窗口中打开。
模型文件显示了模型的类型、输入、输出等的详细信息。上面的图像突出显示了这些信息。这些描述与我们在转换为.mlmodel时提供的描述相匹配。
将模型导入CoreML很容易。现在模型进入了苹果系统,这才是真正的开始。
该步骤的完整的代码文件:https://github.com/mohdsanadzakirizvi/CoreML-on-iPhone/blob/master/Complete%20App/CoreML%20Conversion.ipynb 更多关于coremltools的信息:https://apple.github.io/coremltools/ 不同类型的转换器:https://apple.github.io/coremltools/coremltools.converters.html
集成带有应用程序的模型
现在已经训练了我们的模型并将它转移到CoreML,接下来我们将使用这个模型,为iPhone构建一个垃圾信息分类器应用程序。
我们会在模拟器上运行我们的应用程序。模拟器是一个软件,它展示了应用程序的外观和工作方式,就好像它真的在手机上运行一样。这节省了很多时间,因为我们可以用我们的代码进行实验,并在实际手机上试验应用程序之前,修复所有的bug。看看最终的产品会是什么样子:
下载项目
我已经为我们的应用建立了一个基本的UI,它可以在GitHub上使用。使用以下命令来启动和运行:
git clone https://github.com/mohdsanadzakirizvi/CoreML-on-iPhone.git
cd CoreML-on-iPhone/Practice\ App/
open coreml\ test.xcodeproj/
使用Xcode打开我们的项目。
Xcode窗口突出了三个主要区域:
先运行我们的应用程序,看看会发生什么。点击左上方的播放按钮,在模拟器上运行我们的应用程序。试着在文本框里输入一些文本并点击“Predict”按钮。会发生什么呢?
目前,我们的应用程序并没有做很多事情,只是输出了在文本框里键入的东西。
在应用程序中添加预先训练的模型
以下是整个过程:
编译模型
从模型开始进行推断之前,我们需要利用Xcode去创建阶段编译模型。步骤如下:
每次运行应用程序时,Xcode都会编译我们的机器学习模型,以便它进行预测。
在代码中使用模型
苹果设备的应用程序都是用swift(https://developer.apple.com/swift/)编程。在本教程中,不需要学习swift,但如果你对它感兴趣,并且想深入学习,可以跟随教程(https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/GuidedTour.html)。
let enteredMessage= messageTextField.text!
if (enteredMessage != ""){
spamLabel.text= ""
}
//Fetch tfidf representation of text
let vec= tfidf(sms: enteredMessage)
do {
//Get prediction on the text
let prediction= try SpamMessageClassifier().prediction(message: vec).spam_or_not
print (prediction)
if (prediction== "spam"){
spamLabel.text= "SPAM!"
}
else if(prediction== "ham"){
spamLabel.text= "NOT SPAM"
}
}
catch{
spamLabel.text= "No Prediction"
}
上面的代码用来检查用户是否在文本框中输入任何信息。如果有,它将调用tfidf()函数来计算文本的tfidf。然后,创建SpamMessageClassifier的对象,并调用 .prediction() 函数。这相当于sklearn中的 .predict()函数。然后,根据预测显示适当的信息。
为什么需要tfidf()?
我们基于文本的tf – idf表示来训练我们的模型,所以我们模型期望输入的格式相同。一旦我们收到在文本框中的输入信息,我们就调用tfidf()函数来执行相同的操作。接下来编写代码,将下面的代码复制到predictSpam()函数下面:
//MARK: Functionality code
func tfidf(sms: String)-> MLMultiArray{
//get pathfor files
let wordsFile= Bundle.main.path(forResource:"wordlist", ofType:"txt")
let smsFile= Bundle.main.path(forResource:"SMSSpamCollection", ofType:"txt")
do {
//read wordsfile
let wordsFileText= try String(contentsOfFile: wordsFile!, encoding: String.Encoding.utf8)
var wordsData= wordsFileText.components(separatedBy: .newlines)
wordsData.removeLast()// Trailing newline.
//read spam collectionfile
let smsFileText= try String(contentsOfFile: smsFile!, encoding: String.Encoding.utf8)
var smsData= smsFileText.components(separatedBy: .newlines)
smsData.removeLast()// Trailing newline.
let wordsInMessage= sms.split(separator:" ")
//create a multi-dimensional array
let vectorized= try MLMultiArray(shape: [NSNumber(integerLiteral: wordsData.count)], dataType: MLMultiArrayDataType.double)
for iin 0..<wordsData.count{
let word= wordsData[i]
if sms.contains(word){
var wordCount= 0
for substrin wordsInMessage{
if substr.elementsEqual(word){
wordCount+= 1
}
}
let tf= Double(wordCount)/ Double(wordsInMessage.count)
var docCount= 0
for smsin smsData{
if sms.contains(word) {
docCount+= 1
}
}
let idf= log(Double(smsData.count)/ Double(docCount))
vectorized[i]= NSNumber(value: tf* idf)
}else {
vectorized[i]= 0.0
}
}
return vectorized
} catch {
return MLMultiArray()
}
}
上面的代码找到了在文本框中输入信息的tfidf表示,它读取原始数据集文件SMSSpamCollection.txt和返回相同的操作。一旦你保存了程序并重新运行模拟器,应用程序就应该可以正常运行了。
就像所有发展中的库一样,它也有它的优点和缺点,让我们明确地说明它们。
优点:
1.支持向量机(SVM);
2.tree ensembles,如随机森林和提升数模型(boosted trees)
3.线性回归和逻辑回归;
4.神经网络:前馈,卷积,反复。
缺点
在这篇文章中,我们学习了更多关于CoreML的知识,以及它在构建iPhone机器学习应用程序方面的应用。CoreML是一个相对较新的库,因此有它自己的优点和缺点。其中一个非常有用的特性是它在本地设备上运行,从而提供了更快的速度和更多的数据隐私。与此同时,它还不能被认为是一个成熟的数据科学家友好的库。我们将拭目以待,看看它在即将发布的版本中会如何发展。
本文的所有代码:https://github.com/mohdsanadzakirizvi/CoreML-on-iPhone
另外,如果你想更深入地探索CoreML,这些是一些资源:
核心ML介绍:构建一个简单的图像识别应用(https://www.appcoda.com/coreml-introduction/)。