神经网络模型在移动端可以利用CPU加速,但是,如果算法同事那边为了更好的效果在尝试不同的模型,相应的在部署iOS移动端这块就需要不断的修改网络模型。Core ML的出现使部署移动端的任务量可以缩减到最少两行代码。

苹果官方给出了如何利用Core ML的demo,并且给出了两个例子。一个是根绝输入相关数据预测房价,另外一个是输入图片给出分类结果(结合了Vision框架)。打开Xcode ->window->Developer Documentation,输入Core ML,得到相应的官方介绍。

结合官方文档,首选任务是如何获取一个Core ML模型,该模型文件的后缀为.mlmodel。

Core ML Tool:

该工具是Python语言写的工具包,支持很多机器学习平台生成的模型转成mlmodel文件,如caffe、keras等,可惜不支持TensorFlow。如果使用TensorFlow,可利用GitHub上的第三方平台进行转换(tf-coreml),并且只支持部分OP操作。现在话题转移到TensorFlow模型转换成mlmodel的工具上。从该项目上下载代码后,暂时感觉有两个比较重要的功能,一个在inspect_pb.py文件里面,调用该文件里面的inspect方法(需要输入两个参数,第一个参数为pb文件路径,第二个为输出txt文件路径)。该方法是读取pb文件里所有OP操作的名字以及相应配置,并写入txt文件。读取txt文件信息你可以了解到该模型的每一次OP的名字,并且到这里tensor的shape是多少。拉到该txt文件的最下面,你还可以知道该模型每一个OP操作一共执行了多少次。如图所示:

另外一个比较重要的文件肯定是如何利用该工具将pb文件转成mlmodel文件了。在tests文件夹的tests_tf_converter.py的最后,可以看到使用tf_converter.convert()方法,点到convert()方法里面,可以看到后很多参数,但是必须输入的是前三个,tf模型路径,输出mlmodel的路径以及输出tensor的名字,这里感觉input_name_shape_dict也是需要给出的,毕竟如果该网络不是全卷机网络,那么该输入的图片尺寸就必须是固定的,那么你就应当给出输入tensor或者placeholder的具体shape。另外,这其中有个很容易忽略的参数,如果忽略了,那么在iOS采用Core ML进行模型推理的时候会变得很麻烦(稍后会解释),该参数就是image_input_names。该参数是一个string类型,表示一个tensor的名字,给与该参数赋值表明该tensor接受的是一个image(pixelBuffer)类型,因此一般是输入tensor的名字:例如:

模型的可视化

我们查看模型的结构,除了使用netron该神器(可以查看很多机器学习平台生成的模型结构,caffe、TensorFlow、MXNet等等),也可以使用Core ML Tool,很简单,两行代码:

import coremltoolsmodel =  coremltools.models.MLModel('HousePricer.mlmodel')model.visualize_spec()

mlmodel文件的使用

通过上述步骤,应该会顺利得到mlmodel文件。这里就只是展示了官方给的demo上的mlmodel文件进行说明。首先拖入到xcode后点击MobileNet.mlmodel会看到:

首先,红框地方表示输入的一些信息,可以看到输入的是一个image,尺寸为224x224。输入的是一个字典类型和一个classLabel总集。在这里之所以标红是因为上面说的image_input_names在pb文件转成mlmodel文件时,设置该参数的问题。如果不设置,那么你可能会看到类似这种输入信息:

该MultiArray输入类型在Python中的数组处理应该比较简单,Python本身很多图片处理框架读取一张图片直接就是三维数组的形式,但是在iOS中就比较麻烦。所以在转换模型的时候,image_input_names参数一定要设置好。

点击上图中红圈标记的地方后,会跳如mlmodel文件自动生成的一个同名swift文件。它是有三个类组成,一个是模型输入类、模型类、模型输出类。输出和输入这两个类的使用和创建还是比较简单的,他们都继承自MLFeatureProvider。而且他们的方法还都很类似,其中一个叫做MLFeatureValue,这个类很有意思。查看他的相关解释会发现,他几乎hold住了所有Core ML中相关数据类型的一个类,比如imageBufferValue,multiArrayValue等等。

这里应当注意的是,在accessing the value 这个解释下面,他的每个属性都是在他初始化传入数据格式时就已经确定,比如说初始化的时候为传入的数据为MLMutiArray,那么只有他的multiArrayValue这个属性不为空。曾经用到的时候,天真的以为初始化时传入MLMutiArray,那么通过他的imageBufferValue属性就可以得到pixelBuffer的图像格式,这样就省去了MLMutiArray到pixelBuffer格式转换的麻烦。所以当我们用到类似风格转换的神经网络图像处理时,输出来的是MLMutiArray的格式,只能老老实实的用相关方法转成image了。还好已经有大神为我们写好相关方法——CoreMLHelper,只是速度有点慢。利用CoreMLHelper项目中的转换方法,可以得出能够显示的image:

//image为从相册取出的image,imageToPixelBuffer是image->pixelBuffer的格式转换方法let pixBuffer = self.imageToPixelBuffer(image: image, width: 1280, height: 720)!guard let outModel = try?self.model.prediction(src_input__0: pixBuffer) else {fatalError("Visionular warning : Unexpected runtime error.")}let resultMultiArray = outModel.imgout__0let result_image = resultMultiArray.image(min:0,max:255)

不过,在仔细研究了Core MLtools后发现了即使输入和输出是MLMutiArray,但是通过该工具是可以在次转换的。即通过tf_coreml工具转换后,还可以继续使用苹果自家的Core ML Tool工具把格式以及一些描述信息给添加上。由于主要是输出的数据格式转换,那么这里就只给了输出的格式转换,因此还是要多关注一下Core ML Tool 具体的操作。

def export_coreml_image(image, array_shape):from coremltools.proto import FeatureTypes_pb2 as ftchannels, height, width = array_shapeif channels == 1:image.type.imageType.colorSpace = ft.ImageFeatureType.ColorSpace.Value('GRAYSCALE')elif channels == 3:image.type.imageType.colorSpace = ft.ImageFeatureType.ColorSpace.Value('RGB')else:raise ValueError("Channel Value %d not supported for image inputs" % channels)image.type.imageType.width = widthimage.type.imageType.height = heightif __name__ == '__main__':path = '/Users/MacBook/Desktop/v1.0.0.1_pb/Out_format_isImage.mlmodel'coreml_model = tf_converter.convert(tf_model_path="/Users/MacBook/Desktop/v1.0.0.1_pb/coustome.pb",mlmodel_path="/Users/MacBook/Desktop/v1.0.0.1_pb/out_model.mlmodel",image_input_names="src_input:0",output_feature_names=['imgout:0'],input_name_shape_dict={'src_input:0':[1, 720, 1280, 3]})spec = coreml_model.get_spec()toolmodel = coremltools.models.MLModel(spec)image_output = spec.description.output[0]output_array_shape = tuple(image_output.type.multiArrayType.shape)export_coreml_image(image_output, output_array_shape)toolmodel.save(path)

那么,在将转出来的模型利用xcode可以看到:

输出是image格式,第二个箭头处的description则是空白的,比如我们可用:
coreml_model.output_description[outImageName] = 'out_image'

outImageName是输出的tensor的名字,这里是imgout。好比代码中的:output_feature_names=['imgout:0']。

其他的信息设置还有:

coreml_model.author = 'John Smith'
coreml_model.license = 'BSD'
coreml_model.short_description = 'Predicts the price of a house in the Seattle area.'
# Set feature descriptions manually
model.input_description['bedroom'] = 'Number of bedrooms'
model.input_description['bathrooms'] = 'Number of bathrooms'
model.input_description['size'] = 'Size (in square feet)'
# Set the output descriptions
model.output_description['price'] = 'Price of the house'# Save the model
model.save('HousePricer.mlmodel')

mlmodel的瘦身与选择运行设备

在官网提供的方法中,默认直接利用的MobileNet()方法加载了mlmode模型。加入我们要选择设备运行方式呢,即:使用CPU还是GPU甚至NPU来对模型进行加速呢。苹果已经提供了相应的配置方法。这里就采用懒加载的方式在里面进行设置了:

    lazy var model : MobileNet = {do{let config = MLModelConfiguration.init()config.computeUnits = MLComputeUnits.cpuAndGPUlet model = try MobileNet.init(configuration: config)return model}catch{fatalError("Failed to load MobileNet ML model: \(error)")}}()

通过MLModelConfiguration类可以对模型使用哪种设备来加速进行配置。MLComputeUnits有cpuOnly、cpuAndGPU、all。前面两个就比较好解释了,最后一个all是cpu、GPU、还有苹果自家芯片A11以及后代产品中自带的NPU。由此也可以看出,我们没有办法独自选择GPU或者NPU进行加速。在这里稍微提一下,如果采用带有NPU的设备,并且利用了NPU(也就是配置中选择了all,或者直接采用let mode = MobileNet()创建的model。)结果有可能不对(起码我在项目中遇到了该问题,配置选择cpuOnly或者CPUAndGPU没有问题),对于该问题,GitHub相关项目上也有人提到,很多人猜测可能是NPU中数据处理的格式类型有可能不对(比如说cpu中用到的是float32,而NPU用到的是float8等等,当然这也只是猜测)。

一般神网训练出来的模型比较大,在预测精度降低不是那么明显的情况下,选择量化方案可大大降低模型的大小。Core ML Tool自带了该工具。用法特别简单,直接在安装了Core ML Tool工具的Python包中调用相关API即可:

import coremltoolsfrom coremltools.models.neural_network.quantization_utils import *
urlPath = 'Path/model.mlmodel'
desPath = 'Path/model_8.mlmodel'
model = coremltools.models.MLModel(urlPath)
line_quant_model_8 = quantize_weights(model, 8, "linear")
line_quant_model_8.save(desPath)

主要是quantize_weights()该方法,第一个参数不用解释,第二个参数即量化的bit量,可以为16,8,4,甚至为2。第三个参数即量化方法,这里使用的是线性量化,其他的量化方法可点进去看一下,比如说kmeam量化方法等。

需要指出的是,在我测试的项目中,模型尽管变小了,但是计算速度并没有提高,甚至还有所下降。当然精度肯定是下降的。

iOS(swift): Core ML的使用相关推荐

  1. iOS 11: CORE ML—浅析

    本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/OWD5UEiVu5JpYArcd2H9ig 作者:l ...

  2. iOS 11 : CORE ML—浅析

    导语:在刚刚过去的WWDC上,苹果发布了Core ML这个机器学习框架.现在,开发者可以轻松的使用Core ML把机器学习功能集成到自己的应用里,让应用变得更加智能,给用户更牛逼的体验. 苹果在 iO ...

  3. ios 11 CORE ML 学习入门

    导语:在刚刚过去的WWDC上,苹果发布了Core ML这个机器学习框架.现在,开发者可以轻松的使用Core ML把机器学习功能集成到自己的应用里,让应用变得更加智能,给用户更牛逼的体验. 苹果在 iO ...

  4. 手把手教你在应用里用上iOS机器学习框架Core ML

    2017-06-10 Cocoa开发者社区 2017年的WWDC上,苹果发布了Core ML这个机器学习框架.现在,开发者可以轻松的使用Core ML把机器学习功能集成到自己的应用里,让应用变得更加智 ...

  5. iOS Core ML与Vision初识

    代码地址如下: http://www.demodashi.com/demo/11715.html 教之道 贵以专 昔孟母 择邻处 子不学 断机杼 随着苹果新品iPhone x的发布,正式版iOS 11 ...

  6. 使用YOLO Core ML模型构建对象检测iOS应用(七)

    目录 在我们的应用程序中添加模型 在捕获的视频帧上运行目标检测 绘制边界框 实际应用 下一步? 总目录 将ONNX对象检测模型转换为iOS Core ML(一) 解码Core ML YOLO对象检测器 ...

  7. 为iOS Vision盒子架构建Core ML管道(五)

    目录 介绍 去掉多余的盒子 构建管道 对管道的预测 下一步 总目录 将ONNX对象检测模型转换为iOS Core ML(一) 解码Core ML YOLO对象检测器(二) 使用数组操作解码YOLO C ...

  8. 将ONNX对象检测模型转换为iOS Core ML(一)

    目录 介绍 使用YOLO进行物体检测 寻找正确的模型 将ONNX转换为Core ML 下一步 总目录 将ONNX对象检测模型转换为iOS Core ML(一) 解码Core ML YOLO对象检测器( ...

  9. AR Kit Core ML 将救百万iOS开发者于水深火热中

    AR 市场到底有多大? 目前AR 的困境之处,主要是AR 穿戴设备这一个问题上.可以预知到,AR一旦有了成熟的设备问世, AR将会以迅雷不及掩耳之速普及市场. 支付宝对社交的渴望是路人皆知的,但此前的 ...

  10. 使用数组操作解码YOLO Core ML对象检测(三)

    目录 介绍 解码YOLO输出的正确方式 下一步 总目录 将ONNX对象检测模型转换为iOS Core ML(一) 解码Core ML YOLO对象检测器(二) 使用数组操作解码YOLO Core ML ...

最新文章

  1. QT中无法使用10^n次方来计算
  2. 技术干货 | Native 页面下如何实现导航栏的定制化开发?
  3. shell 非_Shell基本操作(一)
  4. 网页 php pdf文件怎么打开是乱码,打开php文件乱码的解决方法
  5. c 修改mysql数据库_c 修改mysql数据库
  6. 快速理解设计模式六大原则
  7. 模块使用:time、datetime、calendar、sys、os、os.path、normcase和normapath、random、json、pickle...
  8. kotlin多继承_Kotlin继承
  9. 转发的 呀 犯法不 顶级 的 学学不错 【分享】各大资源论坛推荐及优势特点
  10. IGBT功率半导体器件
  11. 机械工业出版社6000册图书都有哪些?
  12. 经纬度转GeoHash
  13. 聊一聊如何把SSL证书安装到小鸟云服务器上
  14. mac笔记本电脑外接显示器没有声音
  15. z-buffer算法
  16. MEMS mic之PDM mic(二)
  17. 性能测试——CPU占用率的计算原理
  18. python3_面向对象
  19. faq页面 html csdn,jQuery和css3简单实用的FAQ问答页面模板
  20. 220V转5V非隔离2W电源--超低成本

热门文章

  1. 如何高效录制和分享教学视频?我尝试了芦笋
  2. 后场村的加班别有不同
  3. 同济大学Openwrt路由器 ipv6教程(新手导向)
  4. 下载Youtube单个视频和播放列表的方法详细教程
  5. 开关稳压器详解(四)-Buck降压型开关稳压器自举电路
  6. matlab求解一元函数积分,matlab实现一元函数积分
  7. CentOS下查看本机ip地址方法
  8. y的花式写法_y的花式写法_26个字母的花式写法,总有一个你喜欢哒
  9. 7-2 求交错序列前N项和 (10 分)
  10. 四种用电脑给手机发短信方法