將 Firebase 添加到 TFLite 支援的 iOS 應用程式

1. 概述

目標

Firebase ML 可讓您無線部署模型。這可讓您保持較小的應用程式大小,並且僅在需要時下載 ML 模型、試驗多個模型或更新您的 ML 模型,而無需重新發​​布整個應用程式。

在此 Codelab 中,您將使用靜態 TFLite 模型將 iOS 應用程式轉換為使用 Firebase 動態提供的模型的應用程式。你將學到如何:

  1. 將 TFLite 模型部署到 Firebase ML 並從您的應用程式存取它們
  2. 使用 Analytics 記錄與模型相關的指標
  3. 透過Remote Config選擇載入哪個模型
  4. A/B 測試不同模型

先決條件

在開始此 Codelab 之前,請確保您已安裝:

  • Xcode 11(或更高版本)
  • CocoaPods 1.9.1(或更高版本)

2.建立Firebase控制台項目

將 Firebase 新增到專案中

  1. 轉到Firebase 控制台
  2. 選擇“建立新專案”並將您的專案命名為“Firebase ML iOS Codelab”。

3. 取得範例項目

下載程式碼

首先克隆範例專案並在專案目錄中執行pod update

git clone https://github.com/FirebaseExtended/codelab-digitclassifier-ios.git
cd codelab-digitclassifier-ios
pod install --repo-update

如果您沒有安裝 git,您也可以從其 GitHub 頁面或點擊此連結下載範例專案。下載專案後,在 Xcode 中運行它並使用數位分類器來了解它的工作原理。

設定 Firebase

依照文件建立新的 Firebase 專案。取得專案後,從Firebase 主機下載專案的GoogleService-Info.plist檔案並將其拖曳到 Xcode 專案的根目錄。

f06cb08d48de7e10.png

將 Firebase 新增到您的 Podfile 並執行 pod install。

pod 'FirebaseMLModelDownloader', '9.3.0-beta'

AppDelegatedidFinishLaunchingWithOptions方法中,在檔案頂部匯入 Firebase

import FirebaseCore

並新增一個呼叫來配置 Firebase。

FirebaseApp.configure()

再次運行專案以確保應用程式配置正確並且在啟動時不會崩潰。

4. 將模型部署到 Firebase ML

將模型部署到 Firebase ML 非常有用,主要原因有兩個:

  1. 我們可以保持應用程式安裝較小,僅在需要時下載模型
  2. 該模型可以定期更新,並且發布週期與整個應用程式不同

在我們用從 Firebase 動態下載的模型取代應用程式中的靜態模型之前,我們需要將其部署到 Firebase ML。此模型可以透過控制台部署,也可以使用 Firebase Admin SDK 以程式設計方式部署。在此步驟中,我們將透過控制台進行部署。

為了簡單起見,我們將使用應用程式中已有的 TensorFlow Lite 模型。首先,打開 Firebase 並點擊左側導覽面板中的「機器學習」。然後導航到“自訂”並點擊“新增模型”按鈕。

出現提示時,為模型指定一個描述性名稱(例如mnist_v1 ,然後從 Codelab 專案目錄上傳檔案。

3c3c50e6ef12b3b.png

5. 從 Firebase ML 下載模型

選擇何時將遠端模型從 Firebase 下載到您的應用程式中可能很棘手,因為 TFLite 模型可能會變得相對較大。理想情況下,我們希望避免在應用程式啟動時立即載入模型,因為如果我們的模型僅用於一項功能並且用戶從不使用該功能,那麼我們將無緣無故地下載大量資料。我們還可以設定下載選項,例如僅在連接到 WiFi 時取得模型。如果您想確保模型即使在沒有網路連線的情況下也可用,您還應該將模型捆綁為應用程式的一部分作為備份。

為了簡單起見,我們將刪除預設的捆綁模型,並在應用程式啟動時始終從 Firebase 下載模型。這樣,當執行數字識別時,您可以確保推理是使用 Firebase 提供的模型運行的。

ModelLoader.swift的頂部,導入 Firebase 模組。

import FirebaseCore
import FirebaseMLModelDownloader

然後執行下面的方法。

static func downloadModel(named name: String,
                          completion: @escaping (CustomModel?, DownloadError?) -> Void) {
  guard FirebaseApp.app() != nil else {
    completion(nil, .firebaseNotInitialized)
    return
  }
  guard success == nil && failure == nil else {
    completion(nil, .downloadInProgress)
    return
  }
  let conditions = ModelDownloadConditions(allowsCellularAccess: false)
  ModelDownloader.modelDownloader().getModel(name: name, downloadType: .localModelUpdateInBackground, conditions: conditions) { result in
          switch (result) {
          case .success(let customModel):
                  // Download complete.
                  // The CustomModel object contains the local path of the model file,
                  // which you can use to instantiate a TensorFlow Lite classifier.
                  return completion(customModel, nil)
          case .failure(let error):
              // Download was unsuccessful. Notify error message.
            completion(nil, .downloadFailed(underlyingError: error))
          }
  }
}

ViewController.swiftviewDidLoad中,用我們的新模型下載方法取代 DigitClassifier 初始化呼叫。

    // Download the model from Firebase
    print("Fetching model...")
    ModelLoader.downloadModel(named: "mnist_v1") { (customModel, error) in
      guard let customModel = customModel else {
        if let error = error {
          print(error)
        }
        return
      }

      print("Model download complete")
      
      // Initialize a DigitClassifier instance
      DigitClassifier.newInstance(modelPath: customModel.path) { result in
      switch result {
        case let .success(classifier):
          self.classifier = classifier
        case .error(_):
          self.resultLabel.text = "Failed to initialize."
        }
      }
    }

重新運行您的應用程式。幾秒鐘後,您應該在 Xcode 中看到一條日誌,指示遠端模型已成功下載。嘗試繪製一個數字並確認應用程式的行為沒有改變。

6. 追蹤使用者回饋和轉換以衡量模型準確性

我們將透過追蹤使用者對模型預測的回饋來衡量模型的準確性。如果使用者點擊“是”,則表示預測是準確的。

我們可以記錄分析事件來追蹤模型的準確性。首先,我們必須將 Analytics 加入 Podfile 中,然後才能在專案中使用:

pod 'FirebaseAnalytics'

然後在ViewController.swift中檔案頂部導入 Firebase

import FirebaseAnalytics

並在correctButtonPressed方法中加入以下程式碼行。

Analytics.logEvent("correct_inference", parameters: nil)

再次運行應用程式並繪製一個數字。按下“是”按鈕幾次即可發送推斷準確的回饋。

偵錯分析

通常,您的應用程式記錄的事件會在大約一小時的時間內批次處理並一起上傳。這種方法可以節省最終用戶設備的電池並減少網路數據的使用。但是,為了驗證分析實作(並且為了在 DebugView 報告中查看分析),您可以在開發裝置上啟用偵錯模式,以便以最小的延遲上傳事件。

若要在開發裝置上啟用分析偵錯模式,請在 Xcode 中指定下列命令列參數:

-FIRDebugEnabled

再次運行應用程式並繪製一個數字。按下“是”按鈕幾次即可發送推斷準確的回饋。現在,您可以透過 Firebase 控制台中的偵錯視圖近乎即時地查看日誌事件。點選左側導覽列中的“分析”>“調試視圖”。

5276199a086721fd.png

7. 使用 Firebase Performance 追蹤推理時間

測試模型時,在開發設備上製定的效能指標不足以捕捉模型在使用者手中的執行情況,因為很難判斷使用者將在哪些硬體上運行您的應用程式。幸運的是,您可以使用 Firebase Performance 來衡量模型在使用者裝置上的效能,以便更好地了解模型的效能。

若要測量執行推理所需的時間,請先在 DigitClassifier.swift 中匯入 Firebase:

import FirebasePerformance

然後在分類方法中啟動性能跟踪,並在推理完成時停止跟踪。確保在 DispatchQueue.global.async 閉包內新增以下程式碼行,而不是直接在方法聲明下方新增。

let inferenceTrace = Performance.startTrace(name: "tflite inference")
defer {
  inferenceTrace?.stop()
}

如果您好奇,可以透過此處的說明啟用偵錯日誌記錄,以確認您的效能追蹤已被記錄。一段時間後,效能追蹤也將在 Firebase 控制台中可見。

8. 將第二個模型部署到 Firebase ML

當提出模型的新版本時,例如具有更好模型架構的模型或在更大或更新的資料集上訓練的模型,我們可能會想用新版本替換當前模型。然而,在測試中表現良好的模型不一定在生產中表現同樣好。因此,讓我們在生產中進行 A/B 測試,以比較我們的原始模型和新模型。

啟用 Firebase 模型管理 API

在此步驟中,我們將啟用 Firebase 模型管理 API,以使用 Python 程式碼部署新版本的 TensorFlow Lite 模型。

建立一個儲存桶來儲存您的 ML 模型

在 Firebase 控制台中,前往「儲存」並按一下「開始」。 fbbea78f0eb3dc9f.png

按照對話設定您的儲存桶。

19517c0d6d2aa14d.png

啟用 Firebase ML API

前往 Google Cloud Console 上的Firebase ML API 頁面,然後按一下啟用。

2414fd5cced6c984.png當詢問時選擇數字分類器應用程式。

現在,我們將使用更大的資料集訓練新版本的模型,然後使用 Firebase Admin SDK 直接從訓練筆記本以程式設計方式部署它。

下載服務帳戶的私鑰

在使用 Firebase Admin SDK 之前,我們需要建立一個服務帳戶。按一下此連結以開啟 Firebase 控制台的服務帳戶面板,然後按一下按鈕為 Firebase Admin SDK 建立新的服務帳戶。出現提示時,按一下「產生新私鑰」按鈕。我們將使用服務帳戶金鑰來驗證來自 Colab 筆記本的請求。

c3b95de1e5508516.png

現在我們可以訓練和部署新模型。

  1. 打開此Colab 筆記本,並將其複製到您自己的雲端硬碟下。
  2. 點擊第一個單元格左側的播放按鈕來運行第一個單元格「訓練改進的 TensorFlow Lite 模型」。這將訓練一個新模型,可能需要一些時間。
  3. 運行第二個單元將建立文件上傳提示。上傳您在建立服務帳號時從 Firebase 控制台下載的 json 檔案。

71e847c6a85423b3.png

  1. 運行最後兩個單元格。

運行 colab 筆記本後,您應該在 Firebase 控制台中看到第二個模型。確保第二個模型名為mnist_v2

c316683bb4d75d57.png

9. 透過遠端配置選擇型號

現在我們有兩個獨立的模型,我們將添加一個參數來選擇在運行時下載哪個模型。客戶端收到的參數值將決定客戶端下載哪個模型。首先,開啟 Firebase 控制台,然後按一下左側導覽功能表中的「遠端設定」按鈕。然後,按一下“新增參數”按鈕。

將新參數命名為model_name並為其指定預設值mnist_v1 。點擊“發布更改”以應用更新。透過將模型的名稱放入遠端配置參數中,我們可以測試多個模型,而無需為每個要測試的模型新增參數。

添加參數後,您應該在控制台中看到它:

699b3fd32acce887.png

在我們的程式碼中,我們需要在載入遠端模型時添加檢查。當我們收到遠端配置的參數時,我們將取得具有對應名稱的遠端模型;否則我們將嘗試載入mnist_v1 。在使用遠端配置之前,我們必須透過在 Podfile 中將其指定為依賴項來將其新增至我們的專案:

pod 'FirebaseRemoteConfig'

執行 pod install 並重新開啟 Xcode 專案。在ModelLoader.swift中,實作fetchParameterizedModel方法。

static func fetchParameterizedModel(completion: @escaping (CustomModel?, DownloadError?) -> Void) {
  RemoteConfig.remoteConfig().fetchAndActivate { (status, error) in
    DispatchQueue.main.async {
      if let error = error {
        let compositeError = DownloadError.downloadFailed(underlyingError: error)
        completion(nil, compositeError)
        return
      }

      let modelName: String
      if let name = RemoteConfig.remoteConfig().configValue(forKey: "model_name").stringValue {
        modelName = name
      } else {
        let defaultName = "mnist_v1"
        print("Unable to fetch model name from config, falling back to default \(defaultName)")
        modelName = defaultName
      }
      downloadModel(named: modelName, completion: completion)
    }
  }
}

最後,在ViewController.swift中,用我們剛剛實作的新方法取代downloadModel呼叫。

// Download the model from Firebase
print("Fetching model...")
ModelLoader.fetchParameterizedModel { (customModel, error) in
  guard let customModel = customModel else {
    if let error = error {
      print(error)
    }
    return
  }

  print("Model download complete")
  
  // Initialize a DigitClassifier instance
  DigitClassifier.newInstance(modelPath: customModel.path) { result in
  switch result {
    case let .success(classifier):
      self.classifier = classifier
    case .error(_):
      self.resultLabel.text = "Failed to initialize."
    }
  }
}

重新運行應用程式並確保它仍然正確載入模型。

10. A/B 測試兩個模型

最後,我們可以使用 Firebase 內建的 A/B 測試行為來查看兩個模型中哪一個表現較好。前往 Firebase 控制台中的「分析」->「事件」。如果顯示了correct_inference事件,請將其標記為“轉換事件”,如果沒有,您可以轉到“分析”->“轉換事件”,然後按一下“建立新的轉換事件”並輸入correct_inference.

現在轉到 Firebase 控制台中的“遠端配置”,從我們剛剛新增的“model_name”參數的更多選項選單中選擇“A/B 測試”按鈕。

fad5ea36969d2aeb.png

在隨後的選單中,接受預設名稱。

d7c006669ace6e40.png

在下拉清單中選擇您的應用,並將定位條件變更為 50% 的活躍使用者。

6246dd7c660b53fb.png

如果您之前能夠將correct_inference事件設定為轉化,請使用此事件作為要追蹤的主要指標。否則,如果您不想等待事件顯示在 Analytics 中,您可以手動新增correct_inference

1ac9c94fb3159271.png

最後,在「變體」畫面上,將控制組變體設定為使用mnist_v1 ,將變體 A 組設定為使用mnist_v2

e4510434f8da31b6.png

點選右下角的「審閱」按鈕。

恭喜,您已成功為兩個單獨的模型創建了 A/B 測試! A/B 測試目前處於草稿狀態,可以隨時透過點擊「開始實驗」按鈕開始。

若要詳細了解 A/B 測試,請查看A/B 測試文件

11. 結論

在此 Codelab 中,您學習如何使用 Firebase 動態載入的 TFLite 模型來取代應用程式中靜態捆綁的 tflite 資源。要了解有關 TFLite 和 Firebase 的更多信息,請查看其他 TFLite 範例和 Firebase 入門指南。

有一個問題?

報告問題