vlambda博客
学习文章列表

Apple 机器学习框架 Core ML 教程



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



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

Apple 机器学习框架 Core ML 教程

Apple 机器学习框架 Core ML 教程


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

Apple 机器学习框架 Core ML 教程

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

安装与测试

1.安装

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

创建虚拟环境:

conda create --name coremltools-env

激活并安装:

# 激活环境
conda activate coremltools-env

# 安装
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=(2242243,),
    classes=1000,
)

import urllib
label_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) == 1000

for i, label in enumerate(class_labels):
  if isinstance(label, bytes):
    class_labels[i] = label.decode("utf8")

模型转换:

import coremltools as ct

image_input = ct.ImageType(shape=(12242243,),
                           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 ct
import tensorflow as tf 

tf_model = tf.keras.applications.MobileNet()

model_from_tf = ct.convert(tf_model)

2. Keras

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

mport coremltools as ct

model = ct.converters.keras.convert('keras_model.h5')

from keras.models import load_model
keras_model = load_model("keras_model.h5")

model = ct.converters.keras.convert(keras_model)

3. PyTorch

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

import coremltools as ct
import torch
import torchvision

model = torchvision.models.mobilenet_v2()
model.eval()
example_input = torch.rand(13224224)
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=(13224224))])

4.ONNX

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

import coremltools as ct

model  = ct.converters.onnx.convert(model='my_model.onnx')

5.Caffe

首先下载如下文件:

  • bvlc_alexnet.caffemodel
  • deploy.prototxt
  • class_labels.txt
import coremltools as ct

model = 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 ct
from coremltools.models.neural_network import quantization_utils

model_fp32 = coremltools.models.MLModel('model.mlmodel')

model_fp16 = quantization_utils.quantize_weights(model_fp32, nbits=16)

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

# linear
model_8bit = quantize_weights(model_fp32, nbits=8)

# kmeans
model_8bit = quantize_weights(model_fp32, nbits=8,
                             quantization_mode="kmeans")

# linearsymmetric
model_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 AdvancedQuantizedLayerSelector

selector = 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 QuantizedLayerSelector

class 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 True

selector = MyLayerSelector()
quantized_model = quantize_weights(
  mlmodel, 
  nbits = 8
  quantization_mode='linear'
  selector=selector
)

机器学习

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

1.Scikit-learn

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

from sklearn.linear_model import LinearRegression
import pandas as pd

# 导入数据
data = pd.read_csv('houses.csv')

# 训练模型
model = LinearRegression()
model.fit(data[["bedroom""bath""size"]], data["price"])

# 转换并保存
import coremltools as ct
coreml_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 svmutil
problem = 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 ct
coreml_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 urllib
import warnings
warnings.simplefilter(action='ignore', category=FutureWarning)

import torch
import torch.nn as nn
import torchvision
import json

from torchvision import transforms
from PIL import Image

import coremltools as ct

model = 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.4850.4560.406],
        std=[0.2290.2240.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")  

Apple 机器学习框架 Core ML 教程

Apple 机器学习框架 Core ML 教程

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


Apple 机器学习框架 Core ML 教程

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