关于此 Codelab
1. 概览
欢迎参加“使用 TensorFlow Lite 和 Firebase 进行推荐”Codelab。在此 Codelab 中,您将学习如何使用 TensorFlow Lite 和 Firebase 将推荐模型部署到应用。此 Codelab 基于此 TensorFlow Lite 示例。
借助建议,应用可以使用机器学习技术智能地为每位用户投放最相关的内容。它们会考虑过去的用户行为,并使用基于大量其他用户的汇总行为训练的模型,建议用户将来可能喜欢互动的应用内容。
本教程将介绍如何使用 Firebase Analytics 从应用用户那里获取数据,如何根据这些数据构建用于推荐的机器学习模型,以及如何在 Android 应用中使用该模型运行推理并获取推荐。具体来说,我们的推荐会根据用户之前喜欢的电影列表,建议用户最有可能观看哪些电影。
学习内容
- 将 Firebase Analytics 集成到 Android 应用中以收集用户行为数据
- 将这些数据导出到 Google BigQuery
- 预处理数据并训练 TF Lite 推荐模型
- 将 TF Lite 模型部署到 Firebase ML 并从应用中访问该模型
- 使用模型在设备上运行推理,以向用户提供建议
所需条件
- 最新版本的 Android Studio。
- 示例代码。
- 搭载 Android 7 及更高版本和 Google Play 服务 9.8 或更高版本的测试设备,或者搭载 Google Play 服务 9.8 或更高版本的模拟器
- 如果使用设备,则需要连接线缆。
您打算如何使用本教程?
您如何评价自己在构建 Android 应用方面的经验水平?
2. 获取示例代码
从命令行克隆 GitHub 代码库。
$ git clone https://github.com/FirebaseExtended/codelab-contentrecommendation-android.git
3. 导入 starter 应用
在 Android Studio 中,从示例代码下载中选择 codelab-recommendations-android
目录 ( File > Open > .../codelab-recommendations-android/start) ()。
现在,您应该已在 Android Studio 中打开起始项目。
4. 创建 Firebase 控制台项目
创建新项目
- 前往 Firebase 控制台。
- 选择添加项目(如果是第一个项目,则选择创建项目)。
- 选择或输入项目名称,然后点击继续。
- 确保已启用“为此项目启用 Google Analytics”。
- 在 Firebase 控制台中完成剩下的设置步骤,然后点击“创建项目”(如果您使用的是现有 Google 项目,则点击“添加 Firebase”)。
5. 添加 Firebase
- 在新项目的概览界面中,点击 Android 图标以启动设置工作流。
- 输入 Codelab 的软件包名称:
com.google.firebase.codelabs.recommendations
- 选择注册应用。
向应用添加 google-services.json 文件
添加软件包名称并选择“注册”后,点击下载 google-services.json 以获取 Firebase Android 配置文件,然后将 google-services.json 文件复制到项目中的 app
目录。下载文件后,您可以跳过控制台中显示的后续步骤(这些步骤已在 build-android-start 项目中为您完成)。
向应用添加 google-services 插件
google-services 插件使用 google-services.json 文件来配置您的应用以使用 Firebase。以下代码行应已添加到项目中的 build.gradle.kts 文件中(请检查以确认):
app/build.grade.kts
plugins {
id("com.google.gms.google-services")
}
build.grade.kts
plugins {
id("com.google.gms.google-services") version "4.3.15" apply false
}
将您的项目与 Gradle 文件同步
为确保您的应用拥有所有依赖项,此时您应该将项目与 Gradle 文件同步。在 Android Studio 工具栏中选择 File > Sync Project with Gradle Files。
6. 运行起始应用
现在,您已将项目导入 Android Studio 并使用 JSON 文件配置了 google-services
插件,可以首次运行该应用了。连接您的 Android 设备,然后点击 Android Studio 工具栏中的 Run 图标 ( )。
应用应在设备上启动。此时,您可以看到一个正常运行的应用,其中显示了一个包含电影列表的标签页、一个“喜欢的电影”标签页和一个“推荐”标签页。您可以点击电影列表中的电影,将其添加到“我喜欢的”列表中。完成此 Codelab 的剩余步骤后,我们便可以在“建议”标签页中生成电影推荐。
7. 向应用添加 Firebase Analytics
在此步骤中,您将向应用添加 Firebase Analytics,以记录用户行为数据(在本例中为用户喜欢哪些电影)。在后续步骤中,系统将汇总使用这些数据来训练推荐模型。
添加 Firebase 物料清单和 Analytics 依赖项
如需将 Firebase Analytics 添加到应用,必须添加以下依赖项。这些依赖项应已包含在 app/build.gradle.kts 文件中(请验证)。
app/build.grade.kts
implementation(platform("com.google.firebase:firebase-bom:32.0.0"))
implementation("com.google.firebase:firebase-analytics-ktx")
在应用中设置 Firebase Analytics
LikedMoviesViewModel 包含用于存储用户喜欢的电影的函数。每次用户喜欢新电影时,我们还希望发送一个分析日志事件来记录该喜欢操作。
添加包含以下代码的 onMovieLiked 函数,以便在用户点击电影的“喜欢”按钮时注册一个 Google Analytics 事件。
LikedMoviesViewModel.kt
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.ktx.analytics
import com.google.firebase.analytics.ktx.logEvent
import com.google.firebase.ktx.Firebase
class LikedMoviesViewModel internal constructor (application: Application) : AndroidViewModel(application) {
...
fun onMovieLiked(movie: Movie) {
movies.setLike(movie, true)
logAnalyticsEvent(movie.id.toString())
}
}
添加以下字段和函数,以便在电影添加到用户的“已赞”列表时记录 Google Analytics 事件。
LikedMoviesViewModel.kt
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.ktx.analytics
import com.google.firebase.analytics.ktx.logEvent
import com.google.firebase.ktx.Firebase
class LikedMoviesViewModel internal constructor (application: Application) : AndroidViewModel(application) {
...
private val firebaseAnalytics = Firebase.analytics
...
/**
* Logs an event in Firebase Analytics that is used in aggregate to train the recommendations
* model.
*/
private fun logAnalyticsEvent(id: String) {
firebaseAnalytics.logEvent(FirebaseAnalytics.Event.SELECT_ITEM) {
param(FirebaseAnalytics.Param.ITEM_ID, id)
}
}
8. 测试 Analytics 集成
在此步骤中,我们将在应用中生成 Analytics 事件,并验证这些事件是否已发送到 Firebase 控制台。
启用 Analytics 调试日志记录
Firebase Analytics 旨在最大限度地延长用户电池续航时间,因此会在设备上对事件进行批处理,并且仅偶尔将事件发送到 Firebase。出于调试目的,我们可以停用此行为,以便通过在 shell 中运行以下命令来实时查看事件记录。
终端
adb shell setprop debug.firebase.analytics.app com.google.firebase.codelabs.recommendations
验证是否已生成 Google Analytics 事件
- 在 Android Studio 中,打开 Logcat 窗口以检查应用的日志记录。
- 将 Logcat 过滤条件设置为字符串“Logging event”。
- 验证每次在应用中喜欢某部电影时,系统是否都会发出“select_item”Google Analytics 事件。
至此,您已成功将 Firebase Analytics 集成到应用中。当用户使用您的应用并喜欢电影时,系统会以汇总方式记录他们的喜爱情况。在本 Codelab 的其余部分,我们将使用此汇总数据来训练推荐模型。以下是一个可选步骤,用于查看您在 Logcat 中看到的相同 Google Analytics 事件是否也流式传输到了 Firebase 控制台。您可以随意跳到下一页。
可选:在 Firebase 控制台中确认 Google Analytics 事件
- 前往 Firebase 控制台。
- 在“Google Analytics”下选择 DebugView
- 在 Android Studio 中,选择 Run 以启动应用,然后向“Liked”列表中添加一些电影。
- 在 Firebase 控制台的 DebugView 中,验证这些事件是否在您向应用中添加电影时被记录。
9. 将 Analytics 数据导出到 BigQuery
BigQuery 是一项 Google Cloud 产品,可让您检查和处理大量数据。在此步骤中,您将 Firebase 控制台项目连接到 BigQuery,以便将应用生成的 Google Analytics 数据自动导出到 BigQuery。
启用 BigQuery 导出
- 前往 Firebase 控制台。
- 选择项目概览旁边的“设置”齿轮图标,然后选择项目设置
- 选择集成标签页。
- 在 BigQuery 块中,选择关联(或管理)。
- 在如何将 Firebase 关联至 BigQuery 步骤中,选择下一步。
- 在配置集成部分下,点击相应开关以启用 Google Analytics 数据发送功能,然后选择关联到 BigQuery。
您现在已启用 Firebase 控制台项目,以自动将 Firebase Analytics 事件数据发送到 BigQuery。此过程会自动进行,无需任何进一步的互动,但首次导出(在 BigQuery 中创建分析数据集)可能需要 24 小时。创建数据集后,Firebase 会持续将新的 Google Analytics 事件导出到 BigQuery 中的当日表,并将过去几天的事件分组到事件表中。
训练推荐模型需要大量数据。由于我们还没有生成大量数据的应用,因此在下一步中,我们将把一个示例数据集导入 BigQuery,以便在本教程的其余部分中使用。
10. 使用 BigQuery 获取模型训练数据
现在,我们已连接 Firebase 控制台以导出到 BigQuery,过一段时间后,应用分析事件数据将自动显示在 BigQuery 控制台中。为了获取一些初始数据以用于本教程,我们将在这一步中将现有示例数据集导入到 BigQuery 控制台中,以便用于训练推荐模型。
将示例数据集导入 BigQuery
- 在 Google Cloud 控制台中前往 BigQuery 信息中心。
- 在菜单中选择您的项目名称。
- 在 BigQuery 左侧导航栏底部选择您的项目名称,即可查看详细信息。
- 选择创建数据集以打开数据集创建面板。
- 输入“firebase_recommendations_dataset”作为数据集 ID,然后选择创建数据集。
- 新数据集将显示在左侧菜单中的项目名称下方。点击该服务。
- 选择创建表,打开表格创建面板。
- 在基于以下数据创建表部分,选择“Google Cloud Storage”。
- 在从 GCS 存储分区中选择文件字段中,输入“gs://firebase-recommendations/recommendations-test/formatted_data_filtered.txt”。
- 在文件格式下拉菜单中选择“JSONL”。
- 为表名称输入“recommendations_table”。
- 勾选架构 > 自动检测 > 架构和输入参数下的复选框
- 选择创建表
探索示例数据集
此时,您可以选择探索架构并预览此数据集。
- 在左侧菜单中选择 firebase-recommendations-dataset,以展开其中包含的表。
- 选择 recommendations-table 表以查看表架构。
- 选择预览,查看此表格包含的实际 Google Analytics 事件数据。
创建服务账号凭据
现在,我们将在 Google Cloud 控制台项目中创建服务账号凭据,以便在后续步骤中在 Colab 环境中使用这些凭据来访问和加载 BigQuery 数据。
- 确保您的 Google Cloud 项目已启用结算功能。
- 启用 BigQuery 和 BigQuery Storage API。<点击此处>
- 前往创建服务账号密钥页面。
- 从服务账号列表中,选择新的服务账号。
- 在服务账号名称字段中,输入一个名称。
- 从角色列表中,选择项目 > 所有者。
- 点击创建。包含密钥的 JSON 文件就会下载到您的计算机。
在下一步中,我们将使用 Google Colab 对此数据进行预处理,并训练我们的推荐模型。
11. 预处理数据并训练推荐模型
在此步骤中,我们将使用 Colab 笔记本执行以下步骤:
- 将 BigQuery 数据导入 Colab 笔记本
- 对数据进行预处理,以便将其用于模型训练
- 根据分析数据训练推荐模型
- 将模型导出为 TF Lite 模型
- 将模型部署到 Firebase 控制台,以便在应用中使用该模型
在启动 Colab 训练笔记本之前,我们先启用 Firebase Model Management API,以便 Colab 可以将训练好的模型部署到我们的 Firebase 控制台。
启用 Firebase Model Management API
创建存储分区以存储机器学习模型
在 Firebase 控制台中,前往 Storage,然后点击“开始使用”。
按照对话框中的提示设置存储分区。
启用 Firebase ML API
前往 Google Cloud 控制台中的 Firebase ML API 页面,然后点击“启用”。
使用 Colab 笔记本训练和部署模型
使用以下链接打开 Colab 笔记本,然后完成其中的步骤。完成 Colab 笔记本中的步骤后,您将获得一个已部署到 Firebase 控制台的 TF Lite 模型文件,我们可以将其同步到我们的应用。
在 Colab 中打开
12. 在应用中下载模型
在此步骤中,我们将修改应用,使其从 Firebase Machine Learning 下载我们刚刚训练的模型。
添加 Firebase ML 依赖项
如需在应用中使用 Firebase 机器学习模型,您需要添加以下依赖项。该依赖项应已添加(请验证)。
app/build.grade.kts
implementation("com.google.firebase:firebase-ml-modeldownloader:24.1.2")
使用 Firebase Model Manager API 下载模型
将以下代码复制到 RecommendationClient.kt 中,以设置模型下载的条件并创建一个下载任务,将远程模型同步到我们的应用。
RecommendationClient.kt
private fun downloadModel(modelName: String) {
val conditions = CustomModelDownloadConditions.Builder()
.requireWifi()
.build()
FirebaseModelDownloader.getInstance()
.getModel(modelName, DownloadType.LOCAL_MODEL, conditions)
.addOnCompleteListener {
if (!it.isSuccessful) {
showToast(context, "Failed to get model file.")
} else {
showToast(context, "Downloaded remote model: $modelName")
GlobalScope.launch { initializeInterpreter(it.result) }
}
}
.addOnFailureListener {
showToast(context, "Model download failed for recommendations, please check your connection.")
}
}
13. 在应用中集成 TensorFlow Lite 推荐模型
借助 TensorFlow Lite 运行时,您可以在应用中使用模型来生成推荐。在上一步中,我们使用下载的模型文件初始化了 TFlite 解释器。在此步骤中,我们将首先加载一个字典和标签,以便在推理步骤中与模型搭配使用;然后,我们将添加预处理步骤,以生成模型的输入;最后,我们将添加后处理步骤,以从推理中提取结果。
加载字典和标签
用于通过推荐模型生成推荐候选对象的标签列在 res/assets 文件夹中的 sorted_movie_vocab.json 文件中。复制以下代码以加载这些候选字词。
RecommendationClient.kt
/** Load recommendation candidate list. */
private suspend fun loadCandidateList() {
return withContext(Dispatchers.IO) {
val collection = MovieRepository.getInstance(context).getContent()
for (item in collection) {
candidates[item.id] = item
}
Log.v(TAG, "Candidate list loaded.")
}
}
实现预处理
在预处理步骤中,我们会更改输入数据的形式,使其与模型所需的格式相匹配。在此示例中,如果我们尚未生成大量用户喜爱内容,则使用占位值填充输入长度。复制以下代码:
RecommendationClient.kt
/** Given a list of selected items, preprocess to get tflite input. */
@Synchronized
private suspend fun preprocess(selectedMovies: List<Movie>): IntArray {
return withContext(Dispatchers.Default) {
val inputContext = IntArray(config.inputLength)
for (i in 0 until config.inputLength) {
if (i < selectedMovies.size) {
val (id) = selectedMovies[i]
inputContext[i] = id
} else {
// Padding input.
inputContext[i] = config.pad
}
}
inputContext
}
}
运行解释器以生成建议
在此,我们使用在上一步中下载的模型对预处理后的输入运行推理。我们为模型设置了输入和输出类型,并运行推理来生成电影推荐。将以下代码复制到您的应用中。
RecommendationClient.kt
/** Given a list of selected items, and returns the recommendation results. */
@Synchronized
suspend fun recommend(selectedMovies: List<Movie>): List<Result> {
return withContext(Dispatchers.Default) {
val inputs = arrayOf<Any>(preprocess(selectedMovies))
// Run inference.
val outputIds = IntArray(config.outputLength)
val confidences = FloatArray(config.outputLength)
val outputs: MutableMap<Int, Any> = HashMap()
outputs[config.outputIdsIndex] = outputIds
outputs[config.outputScoresIndex] = confidences
tflite?.let {
it.runForMultipleInputsOutputs(inputs, outputs)
postprocess(outputIds, confidences, selectedMovies)
} ?: run {
Log.e(TAG, "No tflite interpreter loaded")
emptyList()
}
}
}
实现后处理
最后,在此步骤中,我们会对模型的输出进行后处理,选择置信度最高的结果并移除包含的值(用户已喜欢的电影)。将以下代码复制到您的应用中。
RecommendationClient.kt
/** Postprocess to gets results from tflite inference. */
@Synchronized
private suspend fun postprocess(
outputIds: IntArray, confidences: FloatArray, selectedMovies: List<Movie>
): List<Result> {
return withContext(Dispatchers.Default) {
val results = ArrayList<Result>()
// Add recommendation results. Filter null or contained items.
for (i in outputIds.indices) {
if (results.size >= config.topK) {
Log.v(TAG, String.format("Selected top K: %d. Ignore the rest.", config.topK))
break
}
val id = outputIds[i]
val item = candidates[id]
if (item == null) {
Log.v(TAG, String.format("Inference output[%d]. Id: %s is null", i, id))
continue
}
if (selectedMovies.contains(item)) {
Log.v(TAG, String.format("Inference output[%d]. Id: %s is contained", i, id))
continue
}
val result = Result(
id, item,
confidences[i]
)
results.add(result)
Log.v(TAG, String.format("Inference output[%d]. Result: %s", i, result))
}
results
}
}
测试应用!
重新运行应用。当您选择几部电影后,应用应会自动下载新模型并开始生成推荐内容!
14. 恭喜!
您已使用 TensorFlow Lite 和 Firebase 在应用中构建了推荐功能。请注意,此 Codelab 中展示的技术和流水线可以进行泛化,并用于提供其他类型的推荐。
所学内容
- Firebase ML
- Firebase Analytics
- 将分析事件导出到 BigQuery
- 预处理分析事件
- 训练推荐 TensorFlow 模型
- 导出模型并部署到 Firebase 控制台
- 在应用中提供电影推荐
后续步骤
- 在应用中实现 Firebase ML 建议。