使用 TensorFlow Lite 和 Firebase 向您的應用添加推薦 - iOS Codelab

一、概述

歡迎使用 TensorFlow Lite 和 Firebase 代碼實驗室的建議。在此 Codelab 中,您將學習如何使用 TensorFlow Lite 和 Firebase 將推薦模型部署到您的應用。此代碼實驗室基於此 TensorFlow Lite示例

推薦允許應用使用機器學習智能地為每個用戶提供最相關的內容。他們考慮過去的用戶行為,通過使用針對大量其他用戶的聚合行為進行訓練的模型來建議用戶將來可能希望與之交互的應用程序內容。

本教程展示瞭如何使用 Firebase Analytics 從您的應用用戶那裡獲取數據,構建機器學習模型以根據該數據提出建議,然後在 iOS 應用中使用該模型來運行推理並獲得建議。特別是,我們的推薦將根據用戶之前喜歡的電影列表來建議用戶最有可能觀看的電影。

你會學到什麼

  • 將 Firebase Analytics 集成到 Android 應用中以收集用戶行為數據
  • 將該數據導出到 Google Big Query
  • 預處理數據並訓練 TF Lite 推薦模型
  • 將 TF Lite 模型部署到 Firebase ML 並從您的應用訪問它
  • 使用模型在設備上運行推理,向用戶提出建議

你需要什麼

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

您將如何使用本教程?

只通讀一遍閱讀並完成練習

您如何評價您構建 iOS 應用程序的體驗?

新手中間的精通

2. 創建 Firebase 控制台項目

將 Firebase 添加到項目中

  1. 轉到Firebase 控制台
  2. 選擇Create New Project並將您的項目命名為“Firebase ML iOS Codelab”。

3. 獲取示例項目

下載代碼

首先克隆示例項目並在項目目錄中運行pod update

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

如果你沒有安裝 git,你也可以從它的 GitHub 頁面或者點擊這個鏈接下載示例項目。下載項目後,在 Xcode 中運行它並嘗試使用建議以了解它是如何工作的。

設置 Firebase

按照文檔創建一個新的 Firebase 項目。獲得項目後,從Firebase 控制台下載項目的GoogleService-Info.plist文件並將其拖到 Xcode 項目的根目錄。

4a923d5c7ae0d8f3.png

將 Firebase 添加到您的 Podfile 並運行 pod install。

pod 'Firebase/Analytics'
pod 'Firebase/MLCommon'
pod 'Firebase/MLModelInterpreter'

AppDelegatedidFinishLaunchingWithOptions方法中,在文件頂部導入 Firebase

import Firebase

並添加一個調用來配置 Firebase。

FirebaseApp.configure()

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

  1. 確保啟用“為此項目啟用 Google Analytics”。
  2. 按照 Firebase 控制台中的其餘設置步驟操作,然後點擊創建項目(或添加 Firebase,如果您使用的是現有的 Google 項目)。

4. 將 Firebase Analytics 添加到應用程序

在此步驟中,您將向應用添加 Firebase Analytics 以記錄用戶行為數據(在本例中,即用戶喜歡哪些電影)。這些數據將在未來的步驟中匯總用於訓練推薦模型。

在應用中設置 Firebase Analytics

LikedMoviesViewModel包含存儲用戶喜歡的電影的函數。每次用戶喜歡一部新電影時,我們還希望發送一個分析日誌事件來記錄該喜歡。

添加下面的代碼以在用戶點擊電影時註冊分析事件。

AllMoviesCollectionViewController.swift

import Firebase
//


override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
//

if movie.liked == nil {
      movie.liked = true
      Analytics.logEvent(AnalyticsEventSelectItem, parameters: [AnalyticsParameterItemID: movie.id])
    } else {
      movie.liked?.toggle()
    }
       
}

5. 測試您的 Analytics 集成

在這一步中,我們將在應用程序中生成分析事件並驗證它們是否被發送到 Firebase 控制台。

啟用分析調試日誌

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

要在您的開發設備上啟用分析調試模式,請在 Xcode 中指定以下命令行參數:

-FIRDebugEnabled

至此,您已成功將 Firebase Analytics 集成到您的應用中。當用戶使用您的應用並喜歡電影時,他們的喜歡將被匯總記錄。我們將在本 Codelab 的其餘部分中使用這些匯總數據來訓練我們的推薦模型。以下是一個可選步驟,用於查看您在 Logcat 中看到的相同 Analytics 事件也流式傳輸到 Firebase 控制台。隨意跳到下一頁。

可選:在 Firebase 控制台中確認 Analytics 事件

  1. 轉到Firebase 控制台
  2. 在 Analytics 下選擇DebugView
  3. 在 Xcode 中,選擇Run以啟動應用程序並將一些電影添加到您的 Liked 列表中。
  4. 在 Firebase 控制台的 DebugView 中,驗證這些事件是否在您在應用中添加電影時被記錄。

6. 將 Analytics 數據導出到 Big Query

Big Query 是一款 Google Cloud 產品,可讓您檢查和處理大量數據。在此步驟中,您會將 Firebase 控制台項目連接到 Big Query,以便您的應用生成的 Analytics 數據會自動導出到 Big Query。

啟用 Big Query 導出

  1. 轉到Firebase 控制台
  2. 選擇Project Overview旁邊的 Settings 齒輪圖標,然後選擇Project settings
  3. 選擇集成選項卡。
  4. BigQuery塊中選擇Link (或Manage )。
  5. 關於將 Firebase 鏈接到 BigQuery步驟中選擇下一步
  6. 配置集成部分下,單擊開關以啟用發送 Google Analytics 數據並選擇鏈接到 BigQuery

您現在已啟用 Firebase 控制台項目以自動將 Firebase Analytics 事件數據發送到 Big Query。這會在沒有任何進一步交互的情況下自動發生,但是,在 BigQuery 中創建分析數據集的第一次導出可能不會在 24 小時內發生。創建數據集後,Firebase 會不斷將新的 Analytics 事件導出到 Big Query 到日內表中,並將過去幾天的事件分組到事件表中。

訓練推薦模型需要大量數據。由於我們還沒有生成大量數據的應用,因此在下一步中,我們會將示例數據集導入 BigQuery 以用於本教程的其餘部分。

7、使用BigQuery獲取模型訓練數據

現在我們已連接 Firebase 控制台以導出到 BigQuery,我們的應用分析事件數據將在一段時間後自動顯示在 BigQuery 控制台中。為了為本教程的目的獲取一些初始數據,在此步驟中,我們會將現有示例數據集導入您的 BigQuery 控制台,以用於訓練我們的推薦模型。

將示例數據集導入 BigQuery

  1. 轉到 Google 雲控制台中的BigQuery儀表板。
  2. 在菜單中選擇您的項目名稱。
  3. 在 BigQuery 左側導航的底部選擇您的項目名稱以查看詳細信息。
  4. 選擇創建數據集以打開數據集創建面板。
  5. 輸入 'firebase_recommendations_dataset' 作為Dataset ID並選擇Create dataset
  6. 新數據集將顯示在項目名稱下的左側菜單中。點擊它。
  7. 選擇創建表以打開表創建面板。
  8. 對於從選擇“谷歌云存儲”創建表
  9. 從 GCS 存儲桶中選擇文件字段中,輸入“gs://firebase-recommendations/recommendations-test/formatted_data_filtered.txt”。
  10. 文件格式下拉列表中選擇“JSONL”。
  11. 輸入“recommendations_table”作為表名
  12. 選中架構 > 自動檢測 > 架構和輸入參數下的框
  13. 選擇創建表

探索樣本數據集

此時,您可以選擇探索架構並預覽此數據集。

  1. 在左側菜單中選擇firebase-recommendations-dataset以展開其中包含的表。
  2. 選擇Recommendations-table表以查看表架構。
  3. 選擇預覽以查看此表包含的實際 Analytics 事件數據。

創建服務帳戶憑據

現在,我們將在我們的 Google Cloud 控制台項目中創建服務帳戶憑據,我們可以在接下來的步驟中在 Colab 環境中使用它來訪問和加載我們的 BigQuery 數據。

  1. 確保為您的 Google Cloud 項目啟用了結算功能。
  2. 啟用 BigQuery 和 BigQuery Storage API API。 <點擊這裡>
  3. 轉到創建服務帳戶密鑰頁面
  4. 服務帳戶列表中,選擇新建服務帳戶
  5. 服務帳戶名稱字段中,輸入名稱。
  6. 角色列表中,選擇項目>所有者
  7. 單擊創建。一個 JSON 文件,其中包含您下載到計算機的密鑰。

下一步,我們將使用 Google Colab 預處理這些數據並訓練我們的推薦模型。

8. 預處理數據和訓練推薦模型

在這一步中,我們將使用 Colab 筆記本執行以下步驟:

  1. 將 BigQuery 數據導入 Colab 筆記本
  2. 預處理數據以準備模型訓練
  3. 在分析數據上訓練推薦模型
  4. 將模型導出為 TF lite 模型
  5. 將模型部署到 Firebase 控制台,以便我們可以在應用程序中使用它

在啟動 Colab 訓練筆記本之前,我們將首先啟用 Firebase 模型管理 API,以便 Colab 可以將訓練後的模型部署到我們的 Firebase 控制台。

啟用 Firebase 模型管理 API

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

在您的 Firebase 控制台中,轉到存儲並單擊開始。 fbbea78f0eb3dc9f.png

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

19517c0d6d2aa14d.png

啟用 Firebase 機器學習 API

轉到 Google Cloud Console 上的Firebase ML API 頁面,然後單擊啟用。

使用 Colab notebook 訓練和部署模型

使用以下鏈接打開 colab 筆記本並完成其中的步驟。完成 Colab 筆記本中的步驟後,您將有一個 TF lite 模型文件部署到 Firebase 控制台,我們可以將其同步到我們的應用程序。

在 Colab 中打開

9. 在您的應用中下載模型

在這一步中,我們將修改我們的應用程序以下載我們剛剛從 Firebase 機器學習訓練的模型。

添加 Firebase ML 依賴項

為了在您的應用中使用 Firebase 機器學習模型,需要以下依賴項。它應該已經被添加(驗證)。

播客文件

import Firebase

使用 Firebase 模型管理器 API 下載模型

將以下代碼複製到ModelDownloader.swift以設置模型下載發生的條件並創建下載任務以將遠程模型同步到我們的應用程序。

模型下載器.swift

  static func downloadModel(named name: String,
                            completion: @escaping (RemoteModel?,         DownloadError?) -> Void) {
    guard FirebaseApp.app() != nil else {
      completion(nil, .firebaseNotInitialized)
      return
    }
    guard success == nil && failure == nil else {
      completion(nil, .downloadInProgress)
      return
    }

    let remoteModel = CustomRemoteModel(name: name)
    let conditions = ModelDownloadConditions(allowsCellularAccess: true,
                                             allowsBackgroundDownloading: true)

    success = NotificationCenter.default.addObserver(forName: .firebaseMLModelDownloadDidSucceed,
                                                     object: nil,
                                                     queue: nil) { (notification) in
      defer { success = nil; failure = nil }
      guard let userInfo = notification.userInfo,
          let model = userInfo[ModelDownloadUserInfoKey.remoteModel.rawValue] as? RemoteModel
      else {
        completion(nil, .downloadReturnedEmptyModel)
        return
      }
      guard model.name == name else {
        completion(nil, .downloadReturnedWrongModel)
        return
      }
      completion(model, nil)
    }
    failure = NotificationCenter.default.addObserver(forName: .firebaseMLModelDownloadDidFail,
                                                     object: nil,
                                                     queue: nil) { (notification) in
      defer { success = nil; failure = nil }
      guard let userInfo = notification.userInfo,
          let error = userInfo[ModelDownloadUserInfoKey.error.rawValue] as? Error
      else {
        completion(nil, .mlkitError(underlyingError: DownloadError.unknownError))
        return
      }
      completion(nil, .mlkitError(underlyingError: error))
    }
    ModelManager.modelManager().download(remoteModel, conditions: conditions)
  }

模型下載器.swift

  static func fetchModel(named name: String,
                         completion: @escaping (String?, DownloadError?) -> Void) {
    let remoteModel = CustomRemoteModel(name: name)
    if ModelManager.modelManager().isModelDownloaded(remoteModel) {
      ModelManager.modelManager().getLatestModelFilePath(remoteModel) { (path, error) in
        completion(path, error.map { DownloadError.mlkitError(underlyingError: $0) })
      }
    } else {
      downloadModel(named: name) { (model, error) in
        guard let model = model else {
          let underlyingError = error ?? DownloadError.unknownError
          let compositeError = DownloadError.mlkitError(underlyingError: underlyingError)
          completion(nil, compositeError)
          return
        }
        ModelManager.modelManager().getLatestModelFilePath(model) { (path, pathError) in
          completion(path, error.map { DownloadError.mlkitError(underlyingError: $0) })
        }
      }
    }
  }

10. 在你的應用中集成 Tensorflow Lite 推薦模型

Tensorflow Lite 運行時將允許您在應用程序中使用您的模型來生成建議。在上一步中,我們使用下載的模型文件初始化了一個 TFlite 解釋器。在這一步中,我們將首先在推理步驟中加載字典和標籤以伴隨我們的模型,然後我們將添加預處理以生成模型的輸入和後處理,我們將從推理中提取結果.

加載字典和標籤

推薦模型用於生成推薦候選的標籤列在 assets 文件夾中的sorted_movie_vocab.json文件中。複製以下代碼以加載這些候選者。

RecommendationsViewController.swift

  func getMovies() -> [MovieItem] {
    let barController = self.tabBarController as! TabBarController
    return barController.movies
  }

實施預處理

在預處理步驟中,我們更改輸入數據的形式以匹配我們模型的預期。在這裡,如果我們還沒有產生很多用戶喜歡,我們用佔位符值填充輸入長度。複製以下代碼:

RecommendationsViewController.swift

  // Given a list of selected items, preprocess to get tflite input.
  func preProcess() -> Data {
    let likedMovies = getLikedMovies().map { (MovieItem) -> Int32 in
      return MovieItem.id
    }
    var inputData = Data(copyingBufferOf: Array(likedMovies.prefix(10)))

    // Pad input data to have a minimum of 10 context items (4 bytes each)
    while inputData.count < 10*4 {
      inputData.append(0)
    }
    return inputData
  }

運行解釋器以生成推薦

在這裡,我們使用我們在上一步中下載的模型來對我們的預處理輸入進行推理。我們為我們的模型設置輸入和輸出的類型並運行推理來生成我們的電影推薦。將以下代碼複製到您的應用程序中。

RecommendationsViewController.swift

import TensorFlowLite

RecommendationsViewController.swift

 private var interpreter: Interpreter?

 func loadModel() {
    // Download the model from Firebase
    print("Fetching recommendations model...")
    ModelDownloader.fetchModel(named: "recommendations") { (filePath, error) in
      guard let path = filePath else {
        if let error = error {
          print(error)
        }
        return
      }
      print("Recommendations model download complete")
      self.loadInterpreter(path: path)
    }
  }

 func loadInterpreter(path: String) {
    do {
      interpreter = try Interpreter(modelPath: path)

      // Allocate memory for the model's input `Tensor`s.
      try interpreter?.allocateTensors()

      let inputData = preProcess()

      // Copy the input data to the input `Tensor`.
      try self.interpreter?.copy(inputData, toInputAt: 0)

      // Run inference by invoking the `Interpreter`.
      try self.interpreter?.invoke()

      // Get the output `Tensor`
      let confidenceOutputTensor = try self.interpreter?.output(at: 0)
      let idOutputTensor = try self.interpreter?.output(at: 1)

      // Copy output to `Data` to process the inference results.
      let confidenceOutputSize = confidenceOutputTensor?.shape.dimensions.reduce(1, {x, y in x * y})

      let idOutputSize = idOutputTensor?.shape.dimensions.reduce(1, {x, y in x * y})

      let confidenceResults =
        UnsafeMutableBufferPointer<Float32>.allocate(capacity: confidenceOutputSize!)
      let idResults =
        UnsafeMutableBufferPointer<Int32>.allocate(capacity: idOutputSize!)
      _ = confidenceOutputTensor?.data.copyBytes(to: confidenceResults)
      _ = idOutputTensor?.data.copyBytes(to: idResults)

      postProcess(idResults, confidenceResults)

      print("Successfully ran inference")
      DispatchQueue.main.async {
        self.tableView.reloadData()
      }
    } catch {
      print("Error occurred creating model interpreter: \(error)")
    }
  }

實施後處理

最後,在這一步中,我們對模型的輸出進行後處理,選擇置信度最高的結果並刪除包含的值(用戶已經喜歡的電影)。將以下代碼複製到您的應用程序中。

RecommendationsViewController.swift

  // Postprocess to get results from tflite inference.
  func postProcess(_ idResults: UnsafeMutableBufferPointer<Int32>, _ confidenceResults: UnsafeMutableBufferPointer<Float32>) {
    for i in 0..<10 {
      let id = idResults[i]
      let movieIdx = getMovies().firstIndex { $0.id == id }
      let title = getMovies()[movieIdx!].title
      recommendations.append(Recommendation(title: title, confidence: confidenceResults[i]))
    }
  }

測試您的應用程序!

重新運行您的應用程序。當您選擇幾部電影時,它應該會自動下載新模型並開始生成推薦!

11. 恭喜!

您已使用 TensorFlow Lite 和 Firebase 在您的應用中構建了推薦功能。請注意,此代碼實驗室中顯示的技術和管道也可以推廣並用於提供其他類型的推薦。

我們涵蓋的內容

  • Firebase 機器學習
  • Firebase 分析
  • 將分析事件導出到 BigQuery
  • 預處理分析事件
  • 訓練推薦 TensorFlow 模型
  • 導出模型並部署到 Firebase 控制台
  • 在應用程序中提供電影推薦

下一步

  • 在您的應用中實施 Firebase ML 建議。

學到更多

有一個問題?

報告問題