- 原文地址:iOS 11: Machine Learning for everyone
- 原文做者:Matthijs Hollemans
- 譯文出自:掘金翻譯計劃
- 譯者:Changkun Ou
- 校對者:wilsonandusa atuooo
WWDC 2017 使一件事情變得很是清楚,那就是:Apple 正在盡心盡力地支持「設備上的機器學習」了。前端
他們但願 App 的開發者們可以儘量的簡單的加入他們的行列中。python
Apple 去年發佈了能夠用於建立基本的卷積神經網的 Metal CNN 和 BNNS 框架。今年,Metal 獲得了進一步擴展,增長了一個全新的計算機視覺框架,以及 Core ML:一個可以輕鬆地將機器學習集成到 App 中的工具包。react
在這片文章中,我將就 iOS 11 和 macOS 10.13 中這些新推出的機器學習的內容,分享我本身的一些想法和經驗。android
Core ML 在 WWDC 上得到了極大的關注度,緣由很簡單:大部分開發者但願可以在他們的 App 中使用這個框架。ios
Core ML 的 API 很是簡單。你只能用它作這些事情:git
這看起來好像頗有限,但實際上你通常只會在 App 中加載模型和作出預測這兩件事。github
在 Core ML 以前,加載訓練好的模型是很是困難的 —— 實際上,我寫過一個框架來減輕這種痛苦。因此如今我對這一個簡單的兩步過程感到很是高興。編程
模型被包含在了一個 .mlmodel 的文件中。這是一種新的開源文件格式,用於描述模型中的 layer、輸入輸出、標籤,以及須要在數據上產生的任何預處理過程。它還包括了全部的學習參數(權重和偏置)。swift
使用模型所需的一切都在這一個文件裏面了。後端
你只須要將 mlmodel 文件放入你的項目中,Xcode 將會自動生成一個 Swift 或 Objective-C 的包裝類,使你能簡單的使用這個模型。
舉個例子,若是你把文件 ResNet50.mlmodel 添加到你的 Xcode 項目中,那麼你就能夠這麼寫來實例化這個模型:
let model = ResNet50()複製代碼
而後作出預測:
let pixelBuffer: CVPixelBuffer = /* your image */if let prediction = try? model.prediction(image: pixelBuffer) {
print(prediction.classLabel)
}複製代碼
這差很少就是全部要寫的東西了。你不須要編寫任何代碼來加載模型,或者將其輸出轉換成能夠從 Swift 直接使用的內容 —— 這一切都將由 Core ML 和 Xcode 來處理。
注意: 要了解背後發生了什麼,能夠在 Project Navigator 裏選擇 mlmodel 文件,而後點擊 Swift generated source 右邊的箭頭按鈕,就可以查看生成的幫助代碼了。
Core ML 將決定本身究竟是在 CPU 上運行仍是 GPU 上運行。這使得它可以充分的利用能夠用的資源。Core ML 甚至能夠將模型分割成僅在 GPU 上執行的部分(須要大量計算的任務)以及 CPU 上的其餘部分(須要大量內存的任務)。
Core ML 使用 CPU 的能力對於咱們開發者來講另外一個很大的好處是:你能夠從 iOS 模擬器運行它,從而運行那些對於 Metal 來講作不到,同時在單元測試中也不太好的任務。
上面的 ResNet50 例子展現的是一個圖像分類器,可是 Core ML 能夠處理幾種不一樣類型的模型,如:
全部這些模型均可以用於迴歸問題和分類問題。此外,你的模型能夠包含這些典型的機器學習預處理操做,例如獨熱編碼(one-hot encoding)、特徵縮放(feature scaling)、缺失值處理等等。
Apple 提供了不少已經訓練好的模型可供下載,例如 Inception v三、ResNet50 和 VGG16 等,但你也可使用 Core ML Tools 這個 Python 庫來轉換本身的模型。
目前,你能夠轉換使用 Keras、Caffe、scikit-learn、XGBoost 和 libSVM 訓練的模型。轉換工具只會支持具體指定的版本,好比 Keras 支持 1.2.2 但不支持 2.0。辛運的是,該工具是開源的,因此毫無疑問它未來會支持更多的訓練工具包。
若是這些都不行,你仍是能夠隨時編寫本身的轉換器。mlmodel 文件格式是開源且能夠直接使用的(由 Apple 制定發佈的一種 protobuf 格式)
若是你想在你的 App 上立刻運行一個模型, Core ML 很不錯。然而使用這樣一個簡單的 API 必定會有一些限制。
若是你可以忍受這些限制,那麼 Core ML 對你來講就是正確的選擇。
不然的話,若是你想要徹底的控制權,那麼你必須使用 Metal Performance Shader 或 Accelerate 框架 —— 甚至一塊兒使用 —— 來驅動你的模型了!
固然,真正的黑魔法不是 Core ML,而是你的模型。若是你連模型都沒有,Core ML 是沒有用的。而設計和訓練一個模型就是機器學習的難點所在……
我寫了一個使用了 Core ML 的簡單的示例項目,和往常同樣,你能夠在 GitHub 上找到源碼。
這個示例程序使用了 MobileNet 架構來分類圖片中的貓。
最初這個模型是用 Caffe 訓練得出的。我花了一點時間來搞清楚如何將它轉換到一個 mlmodel 文件,可是一旦我有了這個轉換好的模型,便很容易集成到 App 中了(轉換腳本包含在 GitHub 中)。
雖然這個 App 不是頗有趣 —— 它只輸出了一張靜態圖片的前五個預測值 —— 但卻展現了使用 Core ML 是多麼的簡單。幾行代碼就夠了。
注意: 示例程序在模擬器上工做正常,可是設備上運行就會崩潰。繼續閱讀來看看爲何會發生這種狀況 ;-)
固然,我想知道發生了什麼事情。事實證實 mlmodel 實際上被編譯進應用程序 bundle 的 mlmodelc 文件夾中了。這個文件夾裏包含了一堆不一樣的文件,一些二進制文件,一些 JSON文件。因此你你能夠看到 Core ML 是如何將 mlmodel 在實際部署到應用中以前進行轉換的。
例如,MobileNet Caffe 模型使用了批量歸一化(Batch Normalization)層,我驗證了這些轉換也存在於 mlmodel 文件中。可是在編譯的 mlmodelc 中,這些批量歸一化 layer 彷佛就被移除了。這是個好消息:Core ML 優化了該模型。
儘管如此,它彷佛能夠更好的優化該模型的結構,由於 mlmodelc 仍然包含一些沒必要要的 scaling layer。
固然,咱們還處在 iOS 11 beta 1 的版本,Core ML 可能還會改進。也就是說,在應用到 Core ML 以前,仍是值得對模型進一步優化的 —— 例如,經過「folding」操做對 layer 進行批量歸一化(Batch Normalization) —— 但這是你必須對你的特性模型進行測量和比較的東西。
還有其餘一些你必須檢查的:你的模型是否在 CPU 和 GPU 上運行相同。我提到 Core ML 將選擇是否在 CPU 上運行模型(使用 Accelerate 框架)或 GPU(使用 Metal )。事實證實,這兩個實現可能會有所不一樣 —— 因此你兩個都須要測試!
例如,MobileNet 使用所謂的「depthwise」卷積層。原始模型在 Caffe 中進行訓練,Caffe 經過使正常卷積的 groups
屬性等於輸出通道的數量來支持 depthwise 卷積。所獲得的 MobileNet.mlmodel 文件也同樣。這在 iOS 模擬器中工做正常,但它在設備上就會崩潰!
發生這一切的緣由是:模擬器使用的是 Accelerate 框架,可是該設備上使用的倒是 Metal Performance Shaders。因爲 Metal 對數據進行編碼方式的特殊性, MPSCNNConvolution
內核限制了:不能使 groups 數等於輸出通道的數量。噢嚯!
我向 Apple 提交了一個 bug,可是我想說的是:模型能在模擬器上運行正常並不意味着它在設備上運行正常。必定要測試!
我沒有辦法測試 Core ML 的速度,由於個人全新 10.5 寸 iPad Pro 下個星期才能到(呵呵)。
我感興趣的是我本身寫的 Forge 庫和 Core ML (考慮到咱們都是一個早期的測試版)之間運行 MobileNets 之間的性能差別。
敬請關注!當我有數據能夠分享時,我會更新這一節內容。
下一個要討論的事情就是全新的 Vision 框架。
你可能已經從它的名字中猜到了,Vision 可讓你執行計算機視覺任務。在之前你可能會使用 OpenCV,但如今 iOS 有本身的 API 了。
Vision 能夠執行的任務有如下幾種:
Core Image 和 AVFoundation 已經能夠實現其中的一些任務,但如今他們都集成在一個具備一致性 API 的框架內了。
若是你的應用程序須要執行這些計算機視覺任務之一,不再用跑去本身實現或使用別人的庫了 - 只需使用 Vision 框架。你還能夠將其與 Core Image 框架相結合,以得到更多的圖像處理能力。
更好的是:你可使用 Vision 驅動 Core ML,這容許你使用這些計算機視覺技術做爲神經網絡的預處理步驟。例如,你可使用 Vision 來檢測人臉的位置和大小,將視頻幀裁剪到該區域,而後在這部分的面部圖像上運行神經網絡。
事實上,任什麼時候候當你結合圖像或者視頻使用 Core ML 時,使用 Vision 都是合理的。原始的 Core ML 須要你確保輸入圖像是模型所指望的格式。若是使用 Vision 框架來負責調整圖像大小等,這會爲你節省很多力氣。
使用 Vision 來驅動 Core ML 的代碼長這個樣子:
// Core ML 的機器學習模型
let modelCoreML = ResNet50()複製代碼
// 將 Core ML 連接到 Vision
let visionModel = try? VNCoreMLModel(for: modelCoreML.model)複製代碼
let classificationRequest = VNCoreMLRequest(model: visionModel) {
request, error iniflet observations = request.results as? [VNClassificationObservation] {
/* 進行預測 */
}
}
let handler = VNImageRequestHandler(cgImage: yourImage)
try? handler.perform([classificationRequest])複製代碼
請注意,VNImageRequestHandler
接受一個請求對象數組,容許你將多個計算機視覺任務連接在一塊兒,以下所示:
try? handler.perform([faceDetectionRequest, classificationRequest])複製代碼
Vision 使計算機視覺變得很是容易使用。 但對咱們機器學習人員很酷的事情是,你能夠將這些計算機視覺任務的輸出輸入到你的 Core ML 模型中。 結合 Core Image 的力量,批量圖像處理就跟玩兒同樣!
我最後一個想要討論的話題就是 Metal —— Apple 的 GPU 編程 API。
我今年爲客戶提供的不少工做涉及到使用 Metal Performance Shaders (MPS) 來構建神經網絡,並對其進行優化,從而得到最佳性能。可是 iOS 10 只提供了幾個用於建立神經網絡的基本 kernel。一般須要編寫自定義的 kernel 來彌補這個缺陷。
因此我很開心使用 iOS 11,可用的 kernel 已經增加了許多,更好的是:咱們如今有一個用於構建圖的 API 了!
注意: 爲何要使用 MPS 而不是 Core ML?好問題!最大的緣由是當 Core ML 不支持你想要作的事情時,或者當你想要徹底的控制權並得到最大運行速度時。
MPS 中對於機器學習來講的最大的變化是:
遞歸神經網絡。你如今能夠建立 RNN,LSTM,GRU 和 MGU 層了。這些工做在 MPSImage
對象的序列上,但也適用於 MPSMatrix
對象的序列。這頗有趣,由於全部其餘 MPS layer 僅處理圖像 —— 但顯然,當你使用文本或其餘非圖像數據時,這不是很方便。
更多數據類型。之前的權重應該是 32 位浮點數,但如今能夠是 16 位浮點數(半精度),8 位整數,甚至是 2 進制數。卷積和 fully-connected 的 layer 能夠用 2 進制權重和 2 進制化輸入來完成。
更多的層。到目前爲止,咱們不得不採用普通的常規卷積、最大池化和平均池化,可是在 iOS 11 MPS 中,你能夠進行擴張卷積(Dilated Convolution)、子像素卷積(Subpixel Convolution)、轉置卷積(Transposed Convolution)、上採樣(Upsampling)和重採樣(Resampling)、L2 範數池化(L2-norm pooling)、擴張最大池化(dilated max pooling),還有一些新的激活函數。 MPS 尚未全部的 Keras 或 Caffe layer 類型,但差距正在縮小...
更方便。使用 MPSImages
老是有點奇怪,由於 Metal 每次以 4 個通道的片斷組織數據(由於圖像由 MTLTexture
對象支持)。可是如今,MPSImage
有用於讀取和寫入數據的方法,這些數據不會讓你感到困惑。
MPSCNNConvolutionDescriptor
還有一個新方法,可讓你在 layer 上設置批量歸一化參數。這意味着你再也不須要將批量歸一化到卷積層中,而 MPS 會爲你處理這些事情。很是方便!
性能改進。現有的內核變得更快。這老是好消息。 🏎
圖 API。這是我最關心的消息。手動建立全部 layer 和(臨時)圖像老是使人討厭的。如今你能夠描述一個圖,就像你在Keras 中同樣。 MPS 將自動計算出圖像須要多大,如何處理填充,如何設置 MPS 內核的 offset
等等。甚至能夠經過融合不一樣的 layer 來優化整個圖。
看起來全部的 MPS 內核均可以使用 NSSecureCoding
進行序列化,這意味着你能夠將圖保存到文件中,而後將其還原。而且使用這個圖來推斷如今只是一個單一的方法調用。它不像 Core ML 那麼簡單,但使用 MPS 絕對比之前好用得多。
有一件事情我目前還不太清楚,那就是我不知道你是否能夠編寫本身的 kernel 並在這個圖中使用。在我客戶的工做中,我發現一般須要使用 Metel Shading 語言編寫的自定義着色器來進行預處理步驟。據我所知,彷佛沒有一個「MPSNNCustomKernelNode
」類。這還要再多研究一下!
結論:用於機器學習的 Metal Performance Shaders 已經在 iOS 11 中變得更增強大,可是大多數開發人員應該轉而使用 Core ML(對於那些使用MPS的來講)。
注意:新的圖 API 使個人 Forge 庫基本上過期了,除非你但願在 App 中繼續支持 iOS 10。我將盡快將示例應用移植到新的圖 API 上,而後將寫一個更詳細的博客文章。
還有一些其餘的更新:
Accelerate 框架: 彷佛 Accelerate 框架中的 BNNS 並無得到太多功能上的更新。它終於有了 Softmax 層,但 MPS 卻沒有新的 layer 類型。也許可有可無:使用 CPU 進行深層神經網絡可能不是一個好主意。也就是說,我喜歡 Accelerate,它有不少好玩的東西。而今年,它確實得到了對稀疏矩陣的更多支持,很棒。
天然語言處理: Core ML不只僅只能處理圖像,它還能夠處理大量不一樣類型的數據,包括文本。 使用的 API NSLinguisticTagger
類已經存在了一段時間,可是與 iOS 11 相比變得更加有效了。NSLinguisticTagger
如今已經能進行語言鑑別,詞法分析,詞性標註,詞幹提取和命名實體識別。
我沒有什麼 NLP 的經驗,因此我沒辦法比較它與其餘 NLP 框架的區別,但NSLinguisticTagger
看起來至關強大。 若是要將 NLP 添加到 App 中,此 API 彷佛是一個好的起點。
Apple 向咱們開發者提供全部的這些新工具都很是的好,可是大多數 Apple API 都有一些很重要的問題:
這三個東西加在一塊兒意味着蘋果的 API 總會落後於其餘工具。若是 Keras 增長了一個很炫酷的新的 layer 類型,那麼在 Apple 更新其框架和操做系統以前,你都沒辦法將它和 Core ML 一塊兒使用了。
若是某些 API 獲得的計算結果並非你想要的,你沒辦法簡單的進去看看究竟是 Core ML 的問題仍是模型的問題,再去修復它 —— 你必須繞開 Core ML 來解決這個問題(並不老是可能的);要麼就只能等到下一個 OS 發佈了(須要你全部的用戶進行升級)。
固然我不但願 Apple 放棄他們的祕密武器,可是就像其餘大多數機器學習工具開源同樣,爲何不讓 Core ML 也開源呢? 🙏
我知道這對於 Apple 來講不可能立刻發生,但當你決定在 App 中使用機器學習時,要記住上面的這些內容。
Matthijs Hollemans 於 2017 年 6 月 11 日
我但願這篇文章對你有所幫助!歡迎經過 Twitter @mhollemans 或 Email matt@machinethink.net 聯繫我。
掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 Android、iOS、React、前端、後端、產品、設計 等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃。