Core ML学习笔记
一、Core ML简介
1、Core ML框架
iOS11推出了Core ML框架,极大地降低了开发者在iphone上使用机器学习的门槛。
苹果文档给出了如下的描述:
Core ML is the foundation for domain-specific frameworks and functionality. Core ML supports Vision for image analysis, Foundation for natural language processing (for example, the NSLinguisticTagger class), and GameplayKit for evaluating learned decision trees. Core ML itself builds on top of low-level primitives like Accelerate and BNNS, as well as Metal Performance Shaders.
简单而言,Core ML使得模型能在设备上高效地运行,主要有以下几个优点:
1)较低的内存占用
2)较低的电池消耗
3)更快的计算速度
4)本地计算,不需要网络的支持
2、Core ML支持的模型
Core ML supports a variety of machine learning models, including neural networks, tree ensembles, support vector machines, and generalized linear models. Core ML requires the Core ML model format (models with a .mlmodel file extension).
二、Core ML Tools介绍
1、安装coremltools
coremltools是一个python工具包,可以通过如下命令进行安装:
pip install -U coremltools
如果提示six相关错误,可以尝试加上命令选项“--ignore-installed six”。原因:Apple预安装的这个six库出于安全原因而被设置为sudo也不可以执行操作,依赖于高版本的库就需要更新six,但是没有six的权限,因而就报错了。
coremltools需要依赖numpy (1.12.1+)、protobuf (3.1.0+)两个库。
如果需要查看系统已经安装的numpy、protobuf的版本信息,可以使用如下命令:
pip show numpy protobuf
若需要转化其他模型(如SVM),还需要其他依赖库,可以在这里查看
这里有个demo可以验证下环境是否搭建成功。 Demo
2、模型转化
本文以caffe训练得到的模型为例作为介绍。整个转化过程非常简单,只需两行代码,涉及两个接口调用:convert和save。
coreml_model = coremltools.converters.caffe.convert(('bvlc_alexnet.caffemodel', 'deploy.prototxt'), predicted_feature_name= 'class_labels.txt')
coreml_model.save('BVLCObjectClassifier.mlmodel’)
这个转化是很基本的,没有涉及过多的参数。但是别的模型下,比如Resnet-50,它要求输入mean image,此时需要指定参数image_input_names=[]。
convert接口完整的参数如下:
coremltools.converters.caffe.convert(model, image_input_names=[], is_bgr=False, red_bias=0.0, blue_bias=0.0, green_bias=0.0, gray_bias=0.0, image_scale=1.0, class_labels=None, predicted_feature_name=None)
3、苹果在这里给出了coremltools完整的使用文档。
三、iOS测试demo
上述得到的模型比较大(244M),为了方便,直接从苹果下载一个较小的模型gooLeNetPlaces。该模型能检测机场、卧室、森林等205个场景。
1、添加模型到Xcode工程
直接将模型拖到Xcode工程中,就完成了模型的添加。只需确认在Build Phases - Compile Sources中包含了该模型文件。注意不是Copy bundle Resources,因为Xcode会根据模型自动生成相关的代码文件,所以.mlmodel也算是一种编译源文件。
2、查看模型概述信息
在工程中点击对应的模型,则可以看到模型的相关信息。信息分为3栏,包括模型的基本描述、模型生成的代码和模型的输入输出参数。如下图所示。
注意图中红色的小圈,点击之后可以查看Xcode自动生成的模型代码。这个箭头在系统完成代码生成之后才会显示,所以第一次导入需要一定的时间等待。
点击进去可以看到三个类的声明GoogLeNetPlaces、GoogLeNetPlacesInput、GoogLeNetPlacesOutput,从这些信息我们就可以知道模型该如何调用。
当然,对于输入、输出信息,也可以在Model Evaluation Parameters 中查看,其信息更为简明扼要。
通过上述信息,可以知道模型的输入是一个224*224的CVPixelBufferRef,输出为识别结果标签和概率字典。
3、模型的使用demo
Demo的功能是从相册中选取一张图片,然后使用模型进行识别,并将识别结果显示出来。
对于GoogLeNetPlaces,模型提供了两个预测接口:
- (nullable GoogLeNetPlacesOutput *)predictionFromFeatures:(GoogLeNetPlacesInput *)input error:(NSError * _Nullable * _Nullable)error;
- (nullable GoogLeNetPlacesOutput *)predictionFromSceneImage:(CVPixelBufferRef)sceneImage error:(NSError * _Nullable * _Nullable)error;
但不管使用哪个接口,我们都需要将待识别的图片缩放到224*224,并转化成CVPixelBufferRef类型。
所以整个核心代码就如下几句:
NSTimeInterval startTime = clock();
_image = [UIImage scaleImage:_image toSize:CGSizeMake(224, 224)];
CVPixelBufferRef pix = [UIImage createPixelBufferFromCGImage:_image.CGImage];
GoogLeNetPlacesOutput *output = [_predict predictionFromSceneImage:pix error:nil];
CVPixelBufferRelease(pix);
NSTimeInterval endTime = clock();
NSTimeInterval predictCostTime = (endTime - startTime) * 1000 / CLOCKS_PER_SEC;
NSString *resultStr = [NSString stringWithFormat:@" Label: %@\n Probs: %@\n PredictCostTime: %fms", output.sceneLabel, output.sceneLabelProbs[output.sceneLabel], predictCostTime];
[_resultLabel setText:resultStr];
大致的流程就是将UIImage进行缩放到224*224,同时转化成CVPixelBufferRef,最后通过GoogLeNetPlaces进行识别并得到结果。
完整的demo可以在这里下载
从demo测试的结果看,每一张图平均识别时间不到50ms,识别速度相当不错。另一方面,对于一些大型网络结构,训练得到的模型很大,甚至到达几百兆,这对整个app的体积带来极大的影响,因为这个模型是没发动态下发的,Xcode需要依赖模型文件来生成代码。
参考
Core ML https://developer.apple.com/documentation/coreml
coremltools使用文档 https://apple.github.io/coremltools/index.html
Vision https://developer.apple.com/documentation/vision
官方模型下载 https://developer.apple.com/machine-learning/
coremltools安装 https://pypi.python.org/pypi/coremltools#downloads