我是來自山區、樸實、不偷電瓶的Python資料分析師小漠,給大家分享人工智慧、自動駕駛、機器人、3D感知相關的知識
今天是12.24號(ps,幾天前寫的文章了,今天發出來),小漠在這裡祝福大家平安夜快樂。一說到平安夜,會想到平安果——蘋果,那今天小漠就出一期Apple公司的機器學習框架Core ML的教程,喜歡的小夥伴可以傳遞下去,祝願大家“手中有卡、眼裡有丹”
Core ML是Apple的機器學習框架,將機器學習模型整合到蘋果的應用程式中。可使用coremltools 軟體包將TensorFlow等框架訓練的模型轉換為Core ML格式。如果小夥伴想開發Core ML,最好先有一臺Mac。
應用程式使用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. KerasTF一定要注意版本,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.ONNXONNX與Core ML部分相容,具體內容可以參考官方的git檢視原始碼。
import coremltools as ctmodel = ct.converters.onnx.convert(model='my_model.onnx')
5.Caffe
首先下載如下檔案:
bvlc\_alexnet.caffemodeldeploy.prototxtclass\_labels.txtimport 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.XGBoostXGBoot在建議原始碼安裝,經常有使用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")
到這裡Core ML的教程就結束了,就是這樣簡單粗暴。其實框架都大同小異,Core ML其實是小漠接觸的第一個移動端推理的框架,用起來真的非常的方便。
後天有部分小夥伴們就要走進考場,一年一度的研究生統考將要拉開帷幕,不要緊張,相信自己沒問題。今年過的真的很快,沒什麼感覺就年底了,Keras之父說現在不是人工智慧的“寒冬”,但是阿chai覺得,一定是調包俠的寒冬了。我們一期努力,爭取早日甩掉“CV”工程師的帽子