AI学习者 · 2020年12月29日

平安夜的平安果——Apple机器学习框架Core ML教程

文章转载于微信公众号:阿chai带你学AI
作者:阿chai

学生人工智能技术干货请关注AIZOOJack Cui

机器人与自动驾驶课程请关注深蓝学院

我是来自山区、朴实、不偷电瓶的AI算法工程师阿chai,给大家分享人工智能、自动驾驶、机器人、3D感知相关的知识

今天是12.24号,阿chai在这里祝福大家平安夜快乐。一说到平安夜,会想到平安果——苹果,那今天阿chai就出一期Apple公司的机器学习框架Core ML的教程,喜欢的小伙伴可以传递下去,祝愿大家“手中有卡、眼里有丹”

Core ML是Apple的机器学习框架,将机器学习模型集成到苹果的应用程序中。可使用coremltools 软件包将TensorFlow等框架训练的模型转换为Core ML格式。如果小伙伴想开发Core ML,最好先有一台Mac。

image.png

应用程序使用Core ML API和用户数据在用户设备上进行预测并微调模型。Core ML通过利用CPU,GPU和神经引擎来优化设备上的性能,同时最大程度地减少其内存占用空间和功耗。

安装与测试

1.安装

安装环境最好使用Conda,具体安装请参考阿chai之前的教程。

创建虚拟环境:

conda create --name coremltools-env

激活并安装:

# 激活环境conda activate coremltools-env# 安装pip install --upgrade coremltools
# 安装
pip install --upgrade coremltools

2. 测试

测试以TF2.x复现的MobileNetV2模型为例:

import tensorflow as tf import cv2# 下载 MobileNetv2 keras_model = tf.keras.applications.MobileNetV2(    weights="imagenet",     input_shape=(224, 224, 3,),    classes=1000,)import urlliblabel_url = 'https://storage.googleapis.com/download.tensorflow.org/data/ImageNetLabels.txt'class_labels = urllib.request.urlopen(label_url).read().splitlines()class_labels = class_labels[1:] assert len(class_labels) == 1000for i, label in enumerate(class_labels):  if isinstance(label, bytes):    class_labels[i] = label.decode("utf8")

模型转换:

import coremltools as ctimage_input = ct.ImageType(shape=(1, 224, 224, 3,),                           bias=[-1,-1,-1], scale=1/127)classifier_config = ct.ClassifierConfig(class_labels)model = ct.convert(    keras_model, inputs=[image_input], classifier_config=classifier_config,)

CoreML可以设定一些描述模型特征的参数,在Xcode中使用可以查看部分信息,便于开发者使用。

model.author = 'xxxx'model.license = 'xxxx'model.short_description = 'xxxx'model.version = 'xxxx'

保存与加载模型:

# 保存模型model.save("MobileNetV2.mlmodel")                  # 加载模型loaded_model = ct.models.MLModel("MobileNetV2.mlmodel")

进行预测:

example_image = cv2.imread('dog.jpg')# 预测out_dict = model.predict({"input_1": example_image})print(out_dict["classLabel"])

Xcode的使用教程请前往B站、油管等资源网站寻找。

模型转换

CoreML在iOS、iPad、Apple Watch上的模型加速效果非常棒,但是小伙伴们用的训练框架种类很多,那今天就来个大杂烩,都来一遍。

1. TensorFlow 2.x

这里的TF2.x并不是Keras。

import coremltools as ctimport tensorflow as tf tf_model = tf.keras.applications.MobileNet()model_from_tf = ct.convert(tf_model)

2. Keras

TF一定要注意版本,Theano做后端时会麻烦一些。

mport coremltools as ctmodel = ct.converters.keras.convert('keras_model.h5')from keras.models import load_modelkeras_model = load_model("keras_model.h5")model = ct.converters.keras.convert(keras_model)

3. PyTorch

PyTorch能直接转换,并不需要ONNX。

import coremltools as ctimport torchimport torchvisionmodel = torchvision.models.mobilenet_v2()model.eval()example_input = torch.rand(1, 3, 224, 224)traced_model = torch.jit.trace(model, example_input)traced_model.save("torchvision_mobilenet_v2.pt")mlmodel = ct.convert("torchvision_mobilenet_v2.pt",                    inputs=[ct.TensorType(shape=(1, 3, 224, 224))])

4.ONNX

ONNX与Core ML部分兼容,具体内容可以参考官方的git查看源码。

import coremltools as ctmodel  = ct.converters.onnx.convert(model='my_model.onnx')

5.Caffe

首先下载如下文件:

  • bvlc\_alexnet.caffemodel
  • deploy.prototxt
  • class\_labels.txt
import coremltools as ctmodel = ct.converters.caffe.convert(    ('bvlc_alexnet.caffemodel', 'deploy.prototxt'),    predicted_feature_name='class_labels.txt')model.save('BVLCObjectClassifier.mlmodel')

量化方法

Core ML模型转换后的默认精度为FP32。FP16shi 官方认为最保险的方法。

import coremltools as ctfrom coremltools.models.neural_network import quantization_utilsmodel_fp32 = coremltools.models.MLModel('model.mlmodel')model_fp16 = quantization_utils.quantize_weights(model_fp32, nbits=16)

量化到8位可能会出现精度下降的情况。

# linearmodel_8bit = quantize_weights(model_fp32, nbits=8)# kmeansmodel_8bit = quantize_weights(model_fp32, nbits=8,                             quantization_mode="kmeans")# linearsymmetricmodel_8bit = quantize_weights(model_fp32, nbits=8,                             quantization_mode="linear_symmetric")

linear:默认模式,对权重使用线性量化,并带有比例和偏差项。

linear\_symmetric:对称量化,只有比例项。

kmeans\_lut:使用Kmeans算法构造权重的查找表量化。

Core ML默认对所有具有权重参数的图层进行量化。由于模型的准确性可能对某些图层敏感,因此不应进行量化,因此可以选择跳过某些图层。

有两种方法可以执行此操作。一种是通过使用类,该类允许您设置简单的属性,例如图层类型,重量计数等。

from coremltools.models.neural_network.quantization_utils import AdvancedQuantizedLayerSelectorselector = AdvancedQuantizedLayerSelector(    skip_layer_types=['batchnorm', 'bias', 'depthwiseConv'],    minimum_conv_kernel_channels=4,    minimum_conv_weight_count=4096)quantized_model = quantize_weights(model,                                    nbits=8,                                   quantization_mode='linear_symmetric',                                   selector=selector)

编写自定义规则来通过扩展类来对图层进行量化。

from coremltools.models.neural_network.quantization_utils import QuantizedLayerSelectorclass MyLayerSelector(QuantizedLayerSelector):    def __init__(self):        super(MyLayerSelector, self).__init__()    def do_quantize(self, layer, **kwargs):        ret = super(MyLayerSelector, self).do_quantize(layer)        if not ret or layer.name == 'dense_2':            return Trueselector = MyLayerSelector()quantized_model = quantize_weights(  mlmodel,   nbits = 8,   quantization_mode='linear',   selector=selector)

机器学习

Core ML同时也支持一下机器学习的加速推理,例如一些回归、分类的模型。

1.Scikit-learn

最好不要下载最新版本,阿chai测试出现了一些问题。

from sklearn.linear_model import LinearRegressionimport pandas as pd# 导入数据data = pd.read_csv('houses.csv')# 训练模型model = LinearRegression()model.fit(data[["bedroom", "bath", "size"]], data["price"])# 转换并保存import coremltools as ctcoreml_model = ct.converters.sklearn.convert(  model, ["bedroom", "bath", "size"], "price")coreml_model.save('HousePricer.mlmodel')

2.XGBoost

XGBoot在建议源码安装,经常有使用pip出问题。

import coremltools as ct# 转换、保存coreml_model = ct.converters.xgboost.convert(model)coreml_model.save('my_model.mlmodel')

3.LIBSVM

当时看到支持LIBSVM的时候阿chai愣了一下,后来一想,也有道理。

import svmutilproblem = svmutil.svm_problem([0,0,1,1], [[0,1], [1,1], [8,9], [7,7]])libsvm_model = svmutil.svm_train(problem, svmutil.svm_parameter())import coremltools as ctcoreml_model = ct.converters.libsvm.convert(libsvm_model)coreml_model.save('./my_model.mlmodel')coreml_model = ct.converters.libsvm.convert(libsvm_model, input_names=['x', 'y'])

完整案例

前面对Core ML的安装测试、模型转换、量化以及结合机器学习框架等的方法进行了描述,下面我们根据小伙伴们常用的PyTorch来实现一个完成整的模型转换的案例。

以DeepLab v3为例,Xcode的操作以及分割效果放在代码下面。

import urllibimport warningswarnings.simplefilter(action='ignore', category=FutureWarning)import torchimport torch.nn as nnimport torchvisionimport jsonfrom torchvision import transformsfrom PIL import Imageimport coremltools as ctmodel = torch.hub.load('pytorch/vision:v0.6.0', 'deeplabv3_resnet101', pretrained=True).eval()input_image = Image.open("test.jpg")preprocess = transforms.Compose([    transforms.ToTensor(),    transforms.Normalize(        mean=[0.485, 0.456, 0.406],        std=[0.229, 0.224, 0.225],    ),])input_tensor = preprocess(input_image)input_batch = input_tensor.unsqueeze(0)with torch.no_grad():    output = model(input_batch)['out'][0]torch_predictions = output.argmax(0)class WrappedDeeplabv3Resnet101(nn.Module):        def __init__(self):        super(WrappedDeeplabv3Resnet101, self).__init__()        self.model = torch.hub.load('pytorch/vision:v0.6.0', 'deeplabv3_resnet101', pretrained=True).eval()        def forward(self, x):        res = self.model(x)        x = res["out"]        return x        traceable_model = WrappedDeeplabv3Resnet101().eval()trace = torch.jit.trace(traceable_model, input_batch)mlmodel = ct.convert(    trace,    inputs=[ct.TensorType(name="input", shape=input_batch.shape)],)mlmodel.save("SegmentationModel_no_metadata.mlmodel")mlmodel = ct.models.MLModel("SegmentationModel_no_metadata.mlmodel")labels_json = {"labels": ["background", "aeroplane", "bicycle", "bird", "board", "bottle", "bus", "car", "cat", "chair", "cow", "diningTable", "dog", "horse", "motorbike", "person", "pottedPlant", "sheep", "sofa", "train", "tvOrMonitor"]}mlmodel.user_defined_metadata["com.apple.coreml.model.preview.type"] = "imageSegmenter"mlmodel.user_defined_metadata['com.apple.coreml.model.preview.params'] = json.dumps(labels_json)mlmodel.save("SegmentationModel_with_metadata.mlmodel")  

image.png

image.png

到这里Core ML的教程就结束了,就是这样简单粗暴。其实框架都大同小异,Core ML其实是阿chai接触的第一个移动端推理的框架,用起来真的非常的方便。

后天有部分小伙伴们就要走进考场,一年一度的研究生统考将要拉开帷幕,不要紧张,相信自己没问题。今年过的真的很快,没什么感觉就年底了,Keras之父说现在不是人工智能的“寒冬”,但是阿chai觉得,一定是调包侠的寒冬了。我们一期努力,争取早日甩掉“CV”工程师的帽子

推荐阅读

更多嵌入式AI技术干货请关注嵌入式AI专栏。
推荐阅读
关注数
18840
内容数
1376
嵌入式端AI,包括AI算法在推理框架Tengine,MNN,NCNN,PaddlePaddle及相关芯片上的实现。欢迎加入微信交流群,微信号:aijishu20(备注:嵌入式)
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息