Core ML 與 Vision:iOS 11 機器學(xué)習(xí)教程

此文翻譯自 Core ML and Vision: Machine Learning in iOS 11 Tutorial

注意:此教程需要 Xcode 9 Beta1 或更新的版本、Swift 4 以及 iOS 11.

機器學(xué)習(xí)正在肆虐橫行。很多人都聽說過,但很少有人知道這是什么。

這篇《iOS 機器學(xué)習(xí)教程》會為你介紹 Core MLVision,iOS 11 中推出的兩個全新框架。

具體來說,你會學(xué)習(xí)如何借助 Places205-GoogLeNet 模型,使用新的 API 對圖像的場景進行分類。

開始

下載起始項目。它已包含了用于顯示圖片的用戶界面,并允許用戶從照片庫中選擇另一張圖片。這樣你就可以專注于實現(xiàn) App 的機器學(xué)習(xí)和視覺方面。

構(gòu)建并運行該項目;可以看到一張城市夜景圖,以及一個按鈕:

從“照片” App 的照片庫中選擇另一張圖片。此起始項目的 Info.plist 已經(jīng)有 Privacy – Photo Library Usage Description,所以你會被提示允許使用。

圖片和按鈕之間的空隙有一個 label,將會在此顯示模型對圖片場景的分類。

iOS 機器學(xué)習(xí)

機器學(xué)習(xí)是一種人工智能,計算機會“學(xué)習(xí)”而不是被明確編程。不用編寫算法,機器學(xué)習(xí)工具通過在大量數(shù)據(jù)中尋找模式,使計算機能夠開發(fā)和優(yōu)化算法。

深度學(xué)習(xí)

自20世紀(jì)50年代以來,AI 研究人員開發(fā)了許多機器學(xué)習(xí)方法。蘋果的 Core ML 框架支持神經(jīng)網(wǎng)絡(luò)、樹組合、支持向量機、廣義線性模型、特征工程和流水線模型。但是,神經(jīng)網(wǎng)絡(luò)最近已經(jīng)取得了很多極為神奇的成功,開始于 2012 年谷歌使用 YouTube 視頻訓(xùn)練 AI 來識別貓和人。僅僅五年后,谷歌正在贊助一場確定 5000 種植物和動物的比賽。像 Siri 和 Alexa 這樣的 App 也存在它們自己的神經(jīng)網(wǎng)絡(luò)。

神經(jīng)網(wǎng)絡(luò)嘗試用節(jié)點層來模擬人腦流程,并將節(jié)點層用不同的方式連接在一起。每增加一層都需要增加大量計算能力:Inception v3,一個對象識別模型,有48層以及大約2000萬個參數(shù)。但計算基本上都是矩陣乘法,GPU 來處理會非常有效。GPU 成本的下降使我們能夠創(chuàng)建多層深度神經(jīng)網(wǎng)絡(luò),此為深度學(xué)習(xí)。

神經(jīng)網(wǎng)絡(luò),circa 2016

神經(jīng)網(wǎng)絡(luò)需要大量的訓(xùn)練數(shù)據(jù),這些訓(xùn)練數(shù)據(jù)理想化地代表了全部可能性。用戶生成的數(shù)據(jù)爆炸性地產(chǎn)生也促成了機器學(xué)習(xí)的復(fù)興。

訓(xùn)練模型意味著給神經(jīng)網(wǎng)絡(luò)提供訓(xùn)練數(shù)據(jù),并讓它計算公式,此公式組合輸入?yún)?shù)以產(chǎn)生輸出。訓(xùn)練是離線的,通常在具有多個 GPU 的機器上。

使用這個模型,就給它新的輸入,它就會計算輸出:這叫做推論。推論仍然需要大量計算,以從新的輸入計算輸出。因為有了 Metal 這樣的框架,現(xiàn)在可以在手持設(shè)備上進行這些計算。

在本教程的結(jié)尾你會發(fā)現(xiàn),深度學(xué)習(xí)遠(yuǎn)非完美。真的很難建立具有代表性的訓(xùn)練數(shù)據(jù),很容易就會過度訓(xùn)練模型,以至于它會過度重視一些古怪的特征。

蘋果提供了什么?

蘋果在 iOS 5 里引入了 NSLinguisticTagger 來分析自然語言。iOS 8 出了 Metal,提供了對設(shè)備 GPU 的底層訪問。

去年,蘋果在 Accelerate 框架添加了 Basic Neural Network Subroutines (BNNS),使開發(fā)者可以構(gòu)建用于推理(不是訓(xùn)練)的神經(jīng)網(wǎng)絡(luò)。

今年,蘋果給了我們 Core ML 和 Vision!

  • Core ML 讓我們更容易在 App 中使用訓(xùn)練過的模型。
  • Vision 讓我們輕松訪問蘋果的模型,用于面部檢測、面部特征點、文字、矩形、條形碼和物體。

你還可以在 Vision 模型中包裝任意的圖像分析 Core ML 模型,我們在這篇教程中就干這個。由于這兩個框架是基于 Metal 構(gòu)建的,它們能在設(shè)備上高效運行,所以不需要把用戶的數(shù)據(jù)發(fā)送到服務(wù)器。

將 Core ML 模型集成到你的 App

本教程使用 Places205-GoogLeNet 模型,可以從蘋果的“機器學(xué)習(xí)”頁面下載。往下滑找到 Working with Models,下載第一個。還在這個頁面,注意一下其它三個模型,它們都用于在圖片中檢測物體——樹、動物、人等等。

注意:如果你有一個訓(xùn)練過的模型,并且是使用受支持的機器學(xué)習(xí)工具訓(xùn)練的,例如 Caffe、Keras 或 scikit-learn,Converting Trained Models to Core ML 介紹了如何將其轉(zhuǎn)換為 Core ML 格式。

為你的項目添加模型

下載 GoogLeNetPlaces.mlmodel 后,把它從 Finder 拖到項目導(dǎo)航器的 Resources 組里:

選擇該文件,然后等一會兒。Xcode 生成了模型類后會顯示一個箭頭:

點擊箭頭,查看生成的類:

Xcode 已生成了輸入和輸出類以及主類 GoogLeNetPlaces,主類有一個 model 屬性和兩個 prediction 方法。

GoogLeNetPlacesInput 有一個 CVPixelBuffer 類型的 sceneImage 屬性??蘖耍@些都是什么鬼?!不要害怕,Vision 框架會負(fù)責(zé)把我們熟悉的圖片格式轉(zhuǎn)換成正確的輸入類型。:]

Vision 框架還會把 GoogLeNetPlacesOutput 屬性轉(zhuǎn)換為自己的 results 類型,并管理對 prediction 方法的調(diào)用,所以在所有生成的代碼中,我們只會使用 model 屬性。

在 Vision Model 中包裝 Core ML Model

終于,要開始寫代碼了!打開 ViewController.swift,并在 import UIKit 下面 import 兩個框架:

import CoreML
import Vision

下一步,在 IBActions 擴展下方添加如下擴展:

// MARK: - Methods
extension ViewController {

  func detectScene(image: CIImage) {
    answerLabel.text = "detecting scene..."
  
    // 從生成的類中加載 ML 模型
    guard let model = try? VNCoreMLModel(for: GoogLeNetPlaces().model) else {
      fatalError("can't load Places ML model")
    }
  }
}

我們上面的代碼做了這些事:

首先,給用戶顯示一條消息,讓他們知道正在發(fā)生什么事情。

GoogLeNetPlaces 的指定初始化方法會拋出一個 error,所以創(chuàng)建時必須用 try

VNCoreMLModel 只是用于 Vision 請求的 Core ML 模型的容器。

標(biāo)準(zhǔn)的 Vision 工作流程是創(chuàng)建模型,創(chuàng)建一或多個請求,然后創(chuàng)建并運行請求處理程序。我們剛剛已經(jīng)創(chuàng)建了模型,所以下一步是創(chuàng)建請求。

detectScene(image:) 的末尾添加如下幾行:

// 創(chuàng)建一個帶有 completion handler 的 Vision 請求
let request = VNCoreMLRequest(model: model) { [weak self] request, error in
  guard let results = request.results as? [VNClassificationObservation],
    let topResult = results.first else {
      fatalError("unexpected result type from VNCoreMLRequest")
  }

  // 在主線程上更新 UI
  let article = (self?.vowels.contains(topResult.identifier.first!))! ? "an" : "a"
  DispatchQueue.main.async { [weak self] in
    self?.answerLabel.text = "\(Int(topResult.confidence * 100))% it's \(article) \(topResult.identifier)"
  }
}

VNCoreMLRequest 是一個圖像分析請求,它使用 Core ML 模型來完成工作。它的 completion handler 接收 requesterror 對象。

檢查 request.results 是否是 VNClassificationObservation 對象數(shù)組,當(dāng) Core ML 模型是分類器,而不是預(yù)測器或圖像處理器時,Vision 框架就會返回這個。而 GoogLeNetPlaces 是一個分類器,因為它僅預(yù)測一個特征:圖像的場景分類。

VNClassificationObservation 有兩個屬性:identifier - 一個 String,以及 confidence - 介于0和1之間的數(shù)字,這個數(shù)字是是分類正確的概率。使用對象檢測模型時,你可能只會看到那些 confidence 大于某個閾值的對象,例如 30% 的閾值。

然后取第一個結(jié)果,它會具有最高的 confidence 值,然后根據(jù) identifier 的首字母把不定冠詞設(shè)置為“a”或“an”。最后,dispatch 回到主線程來更新 label。你很快會明白分類工作為什么不在主線程,因為它會很慢。

現(xiàn)在,做第三步:創(chuàng)建并運行請求處理程序。

把下面幾行添加到 detectScene(image:) 的末尾:

// 在主線程上運行 Core ML GoogLeNetPlaces 分類器
let handler = VNImageRequestHandler(ciImage: image)
DispatchQueue.global(qos: .userInteractive).async {
  do {
    try handler.perform([request])
  } catch {
    print(error)
  }
}?

VNImageRequestHandler 是標(biāo)準(zhǔn)的 Vision 框架請求處理程序;不特定于 Core ML 模型。給它 image 作為 detectScene(image:) 的參數(shù)。然后調(diào)用它的 perform 方法來運行處理程序,傳入請求數(shù)組。在這個例子里,我們只有一個請求。

perform 方法會拋出 error,所以用 try-catch 將其包住。

使用模型來分類場景

哇,剛剛寫了好多代碼!但現(xiàn)在只需要在兩個地方調(diào)用 detectScene(image:) 就好了。

把下面幾行添加到 viewDidLoad() 的末端和 imagePickerController(_:didFinishPickingMediaWithInfo:) 的末端:

guard let ciImage = CIImage(image: image) else {
  fatalError("couldn't convert UIImage to CIImage")
}

detectScene(image: ciImage)

現(xiàn)在構(gòu)建并運行。不需要多久就可以看見分類:

哈哈,是的,圖片里有 skyscrapers(摩天大樓)。還有一列火車。

點擊按鈕,選擇照片庫里的第一張圖片:一些樹葉上太陽光斑的特寫:

75%這是一個水族池

啊哈哈哈哈哈,瞇起眼睛,也許可以想象尼莫或多莉正在里面游泳?但至少你知道應(yīng)該用 “a” 還是 “an”。;]

看一眼蘋果的 Core ML 示例 App

本教程的項目和 WWDC 2017 Session 506 Vision Framework: Building on Core ML示例項目很相似。Vision + ML Example App 使用 MNIST 分類器,可以識別手寫數(shù)字——對郵政分類自動化非常有幫助。它還使用原生 Vision 框架方法 VNDetectRectanglesRequest,還包括 Core Image 的代碼來矯正矩形檢測的透視。

還可以從 Core ML 文檔頁面下載另一個示例項目。MarsHabitatPricePredictor 模型的輸入只是數(shù)字,因此代碼直接使用生成的 MarsHabitatPricer 方法和屬性,而不是將模型包裝在 Vision 模型中。每次都改一下參數(shù),很容易看出模型只是一個線性回歸:

137 * solarPanels + 653.50 * greenHouses + 5854 * acres

下一步?

可以從這里下載教程的完整項目。如果模型顯示為缺失,將其替換為你下載的那個。

你現(xiàn)在已經(jīng)有能力將現(xiàn)有的模型整合到你的 App 中。這里有一些資源可以更詳細(xì)地介紹:

2016 年的:

想構(gòu)建自己的模型?恐怕這超出了本教程的范圍(以及我的專業(yè)知識)。但這些資源可能會幫你上手:

  • RWDevCon 2017 Session 3 Machine Learning in iOS: Alexis Gallagher 做了一項絕對精彩的工作,指導(dǎo)你一系列流程,為神經(jīng)網(wǎng)絡(luò)收集訓(xùn)練數(shù)據(jù)(你微笑或皺眉的視頻),訓(xùn)練,然后檢查它是否有效。他的結(jié)論:“不需要是數(shù)學(xué)家或大公司也可以建立有效的模型?!?/li>
  • Quartz article on Apple’s AI research paper: Dave Gershgorn’s 有關(guān) AI 的文章都很清晰和翔實。此文做了一項杰出的工作,總結(jié)了蘋果的第一篇 AI 研究論文:研究人員使用基于真實圖像訓(xùn)練的神經(jīng)網(wǎng)絡(luò)來優(yōu)化圖像合成,從而有效地產(chǎn)生了大量高質(zhì)量的新訓(xùn)練數(shù)據(jù),而沒有個人數(shù)據(jù)隱私問題。

最后,我從 Andreessen Horowitz 的 Frank Chen 那里真的學(xué)習(xí)了很多 AI 的簡史:AI and Deep Learning a16z podcast。

希望本教程對你有所幫助。隨意在下方加入討論!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容