使用 TensorFlow Lite 和 Firebase 向您的应用添加建议 - iOS Codelab

1. 概览

欢迎阅读“借助 TensorFlow Lite 和 Firebase 实现推荐功能”Codelab。在此 Codelab 中,您将学习如何使用 TensorFlow Lite 和 Firebase 将推荐模型部署到应用中。此 Codelab 基于此 TensorFlow Lite 示例

借助推荐功能,应用可以使用机器学习技术智能地为每位用户提供最相关的内容。它们会考虑过去的用户行为,通过使用基于大量其他用户的汇总行为训练的模型,建议用户将来可能喜欢互动的内容。

本教程介绍了如何使用 Firebase Analytics 获取应用用户的数据,如何根据这些数据构建机器学习模型以进行推荐,以及如何在 iOS 应用中使用该模型运行推理并获取推荐。具体而言,我们的推荐功能将根据用户之前喜欢的电影列表,建议用户最有可能观看的电影。

学习内容

  • 将 Firebase Analytics 集成到 Android 应用中,以收集用户行为数据
  • 将这些数据导出到 Google BigQuery
  • 预处理数据并训练 TF Lite 推荐模型
  • 将 TF Lite 模型部署到 Firebase ML 并从应用中访问该模型
  • 使用该模型运行设备端推理,向用户提供推荐建议

所需条件

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

您打算如何使用本教程?

仅阅读教程内容 阅读并完成练习

您如何评价自己构建 iOS 应用的经验?

初级 中级 高级

2. 创建 Firebase 控制台项目

将 Firebase 添加到项目中

  1. 前往 Firebase 控制台
  2. 选择创建新项目 ,并将项目命名为“Firebase ML iOS Codelab”。

3. 获取示例项目

下载代码

首先,克隆示例项目,然后在项目目录中运行 pod update

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

如果您尚未安装 git,也可以从其 GitHub 页面下载示例项目,或点击 此链接。下载项目后,在 Xcode 中运行该项目,并试用推荐功能,了解其工作原理。

设置 Firebase

按照 文档 创建新的 Firebase 项目。创建项目后,从 Firebase 控制台下载项目的 GoogleService-Info.plist 文件,并将其拖到 Xcode 项目的根目录。

4a923d5c7ae0d8f3.png

将 Firebase 添加到 Podfile 并运行 pod install。

pod 'FirebaseAnalytics'
pod 'FirebaseMLModelDownloader', '9.3.0-beta'
pod 'TensorFlowLiteSwift'

AppDelegatedidFinishLaunchingWithOptions 方法中,在文件顶部导入 Firebase

import FirebaseCore

并添加对 Firebase 进行配置的调用。

FirebaseApp.configure()

再次运行项目,确保应用配置正确,并且在启动时不会崩溃。

  1. 确保已启用“为此项目启用 Google Analytics”。
  2. 在 Firebase 控制台中完成剩下的设置步骤,然后点击“创建项目”(如果您使用的是现有 Google 项目,则点击“添加 Firebase”)。

4. 向应用添加 Firebase Analytics

在此步骤中,您将向应用添加 Firebase Analytics,以记录用户行为数据(在本例中,即用户喜欢哪些电影)。在后续步骤中,我们将汇总使用这些数据来训练推荐模型。

在应用中设置 Firebase Analytics

LikedMoviesViewModel 包含用于存储用户喜欢的电影的函数。每次用户喜欢一部新电影时,我们都希望发送一个 Analytics 日志事件来记录该喜欢。

添加以下代码,以便在用户点击电影的“喜欢”按钮时注册 Analytics 事件。

AllMoviesCollectionViewController.swift

import FirebaseAnalytics
//


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 集成

在此步骤中,我们将在应用中生成 Analytics 事件,并验证这些事件是否已发送到 Firebase 控制台。

启用 Analytics 调试日志记录

通常,您的应用所记录的事件会每隔 1 小时左右集中起来作为一批进行处理,并一起上传。此方法能节省最终用户的设备电量和网络流量消耗。但是,为了验证您的 Analytics 实现情况(也是为了能在 DebugView 报告中查看您的 Analytics 信息),您可以在开发设备上启用调试模式,从而以最短的延迟上传事件。

要在开发设备上启用 Analytics 调试模式,请在 Xcode 中指定以下命令行参数:

-FIRDebugEnabled

至此,您已成功将 Firebase Analytics 集成到应用中。当用户使用您的应用并喜欢电影时,他们的喜欢将汇总记录。在本 Codelab 的其余部分,我们将使用此汇总数据来训练推荐模型。以下是一个可选步骤,用于查看您在 Logcat 中看到的相同 Analytics 事件是否也会流式传输到 Firebase 控制台。您可以随意跳到下一页。

可选:在 Firebase 控制台中确认 Analytics 事件

  1. 前往 Firebase 控制台
  2. 在 Analytics 下选择 DebugView
  3. 在 Xcode 中,选择运行 以启动应用,并将一些电影添加到“喜欢”列表。
  4. 在 Firebase 控制台的 DebugView 中,验证这些事件是否在您向应用中添加电影时被记录。

6. 将 Analytics 数据导出到 BigQuery

BigQuery 是 Google Cloud 产品,可供您检查和处理大量数据。在此步骤中,您将 Firebase 控制台项目连接到 BigQuery,以便将应用生成的 Analytics 数据自动导出到 BigQuery。

启用 BigQuery 导出功能

  1. 前往 Firebase 控制台
  2. 选择项目概览 旁边的设置齿轮图标,然后选择项目设置
  3. 选择集成 标签页。
  4. BigQuery 块内选择关联 (或管理 )。
  5. 如何将 Firebase 关联至 BigQuery 步骤中选择下一步
  6. 配置集成 部分下,点击开关以启用发送 Google Analytics 数据,然后选择关联到 BigQuery

现在,您已启用 Firebase 控制台项目,以自动将 Firebase Analytics 事件数据发送到 BigQuery。此过程会自动进行,无需任何进一步互动,但首次导出会在 BigQuery 中创建 Analytics 数据集,可能需要 24 小时。创建数据集后,Firebase 会不断将新的 Analytics 事件导出到 BigQuery 的当日表中,并将过去几天的事件分组到事件表中。

训练推荐模型需要大量数据。由于我们还没有生成大量数据的应用,因此在下一步中,我们将向 BigQuery 导入一个示例数据集,以供本教程的其余部分使用。

7. 使用 BigQuery 获取模型训练数据

现在,我们已连接 Firebase 控制台以导出到 BigQuery,因此应用分析事件数据会在一段时间后自动显示在 BigQuery 控制台中。为了获取一些初始数据以供本教程使用,在此步骤中,我们将向 BigQuery 控制台导入一个现有示例数据集,以用于训练推荐模型。

将示例数据集导入 BigQuery

  1. 在 Google Cloud 控制台中前往 BigQuery 信息中心。
  2. 在菜单中选择您的项目名称。
  3. 在 BigQuery 左侧导航栏底部选择您的项目名称,以查看详细信息。
  4. 选择创建数据集 以打开数据集创建面板。
  5. 数据集 ID 中输入“firebase_recommendations_dataset”,然后选择创建数据集
  6. 新数据集将显示在左侧菜单中的项目名称下。点击该数据集。
  7. 选择创建表 以打开表创建面板。
  8. 基于以下数据源创建表 中,选择“Google Cloud Storage”。
  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. 根据 Analytics 数据训练推荐模型
  4. 将模型导出为 TF Lite 模型
  5. 将模型部署到 Firebase 控制台,以便在应用中使用该模型

在启动 Colab 训练笔记本之前,我们将先启用 Firebase Model Management API,以便 Colab 可以将训练后的模型部署到 Firebase 控制台。

启用 Firebase Model Management API

创建存储分区以存储机器学习模型

在 Firebase 控制台中,前往 Storage,然后点击“开始使用”。fbbea78f0eb3dc9f.png

按照对话框设置存储分区。

19517c0d6d2aa14d.png

启用 Firebase ML API

前往 Google Cloud 控制台中的 Firebase ML API 页面,然后点击“启用”。

使用 Colab 笔记本训练和部署模型

使用以下链接打开 Colab 笔记本,然后完成其中的步骤。完成 Colab 笔记本中的步骤后,您将获得一个已部署到 Firebase 控制台的 TF Lite 模型文件,我们可以将其同步到应用中。

在 Colab 中打开

9. 在应用中下载模型

在此步骤中,我们将修改应用,以便从 Firebase Machine Learning 下载刚刚训练的模型。

添加 Firebase ML 依赖项

如需在应用中使用 Firebase Machine Learning 模型,需要添加以下依赖项。该依赖项应已添加(请验证)。

Podfile

import FirebaseCore
import FirebaseMLModelDownloader

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

将以下代码复制到 ModelLoader.swift 中,以设置模型下载发生的条件,并创建一个下载任务,将远程模型同步到应用中。

ModelLoader.swift

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))
            }
    }
  }

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 在应用中构建了推荐功能。请注意,此 Codelab 中显示的技术和流水线可以通用化,并用于提供其他类型的推荐。

所学内容

  • Firebase ML
  • Firebase Analytics
  • 将 Analytics 事件导出到 BigQuery
  • 预处理 Analytics 事件
  • 训练推荐 TensorFlow 模型
  • 导出模型并部署到 Firebase 控制台
  • 在应用中提供电影推荐

后续步骤

  • 在应用中实现 Firebase ML 推荐。

了解详情

有疑问?

报告问题