使用 TensorFlow Lite 和 Firebase 向您的应用添加推荐 - Android Codelab

1. 概述

欢迎使用 TensorFlow Lite 和 Firebase 代码实验室的建议。在此 Codelab 中,您将学习如何使用 TensorFlow Lite 和 Firebase 将推荐模型部署到您的应用。本程式码实验室基于此TensorFlow精简版例子

推荐允许应用使用机器学习为每个用户智能地提供最相关的内容。他们通过使用在大量其他用户的聚合行为上训练的模型,将过去的用户行为考虑在内,以建议用户将来可能喜欢与之交互的应用程序内容。

本教程展示了如何使用 Firebase Analytics 从您的应用程序的用户那里获取数据,为来自该数据的推荐构建机器学习模型,然后在 Android 应用程序中使用该模型运行推理并获取推荐。特别是,我们的推荐将根据用户以前喜欢的电影列表建议用户最有可能观看的电影。

你会学到什么

  • 将 Firebase Analytics 集成到 Android 应用程序中以收集用户行为数据
  • 将该数据导出到 Google Big Query
  • 预处理数据并训练 TF Lite 推荐模型
  • 将 TF Lite 模型部署到 Firebase ML 并从您的应用程序访问它
  • 使用模型在设备上运行推理以向用户提出建议

你需要什么

  • Android Studio 3.4+ 版。
  • 示例代码。
  • 具有 Android 2.3+ 和 Google Play 服务 9.8 或更高版本的测试设备,或具有 Google Play 服务 9.8 或更高版本的模拟器
  • 如果使用设备,连接电缆。

您将如何使用本教程?

只通读一遍阅读并完成练习

您如何评价您构建 Android 应用程序的体验?

新手中间的精通

2.获取示例代码

从命令行克隆 GitHub 存储库。

$ git clone https://github.com/FirebaseExtended/codelab-contentrecommendation-android.git

3. 导入入门应用

从Android Studio中,选择codelab-recommendations-android目录( android_studio_folder.png )从示例代码下载(文件>打开> ... /代码实验室的建议,安卓/启动)。

您现在应该在 Android Studio 中打开了启动项目。

4. 创建 Firebase 控制台项目

创建一个新项目

  1. 转至火力地堡控制台
  2. 选择添加项目(或创建一个项目,如果它是第一个)。
  3. 选择或输入项目名称,然后点击继续
  4. 确保已启用“为此项目启用 Google Analytics”。
  5. 按照 Firebase 控制台中剩余的设置步骤进行操作,然后点击创建项目(或添加 Firebase,如果您使用的是现有的 Google 项目)。

5. 添加 Firebase

  1. 在新项目的概览屏幕中,单击 Android 图标以启动设置工作流程。
  2. 输入代码实验室的包名称: com.google.firebase.codelabs.recommendations
  3. 选择注册的应用程序

将 google-services.json 文件添加到您的应用程序

将包名称并选择注册后,点击下载谷歌,services.json获得你的火力地堡的Android配置文件,则谷歌,services.json文件复制到该app在你的项目目录。文件下载后,您可以跳过控制台中显示的下一步骤(他们已经被你在集结的Android启动项目完成)。

将 google-services 插件添加到您的应用程序

google-services 插件使用 google-services.json 文件来配置您的应用程序以使用 Firebase。以下几行应该已经添加到项目中的 build.gradle 文件中(检查以确认):

应用程序/build.grade

apply plugin: 'com.google.gms.google-services'

建造等级

classpath 'com.google.gms:google-services:4.3.4'

将您的项目与 gradle 文件同步

为了确保您的应用程序可以使用所有依赖项,此时您应该将项目与 gradle 文件同步。选择文件>同步项目从Android Studio中的工具栏摇篮文件

6. 运行启动应用程序

现在,您已经导入项目进入Android的工作室,并配置了google-services与您的JSON文件的插件,你就可以运行首次应用。连接您的Android设备,然后点击运行执行.png ) 在 Android Studio 工具栏中。

该应用程序应在您的设备上启动。此时,您可以看到一个功能正常的应用程序,该应用程序显示一个带有电影列表的选项卡、一个喜欢的电影选项卡和一个推荐选项卡。您可以单击电影列表中的电影将其添加到您喜欢的列表中。完成 codelab 的其余步骤后,我们将能够在“推荐”选项卡中生成电影推荐。

7. 将 Firebase Analytics 添加到应用程序

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

添加 Firebase Analytics 依赖项

以下依赖项是将 Firebase Analytics 添加到您的应用所必需的。它应该已经包含在 app/build.gradle 文件中(验证)。

应用程序/build.grade

implementation 'com.google.firebase:firebase-analytics-ktx:17.6.0'

在应用中设置 Firebase Analytics

LikedMoviesViewModel包含的功能是存储用户喜欢的电影。每次用户喜欢一部新电影时,我们还希望发送一个分析日志事件来记录该喜欢的电影。

使用以下代码添加 onMovieLiked 函数,以在用户单击电影时注册分析事件。

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

添加以下字段和函数以在将电影添加到用户的“喜欢”列表时记录分析事件。

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 控制台。

启用分析调试日志记录

Firebase Analytics 旨在最大限度地延长用户电池寿命,并将在设备上批量处理事件,并且仅偶尔将它们发送到 Firebase。出于调试目的,我们可以禁用此行为以通过在 shell 中运行以下命令来查看实时记录的事件。

终端

adb shell setprop debug.firebase.analytics.app com.google.firebase.codelabs.recommendations

验证已生成 Analytics 事件

  1. 在 Android Studio 中,打开 Logcat 窗口以检查应用程序的日志记录。
  2. 将 Logcat 过滤器设置为字符串“Logging event”。
  3. 验证“select_item”分析事件是否在您每次喜欢应用中的电影时发出。

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

可选:在火力地堡控制台确认Analytics(分析)事件

  1. 转至火力地堡控制台
  2. 分析下选择的DebugView
  3. 在Android Studio中,选择运行来启动应用程序和一些电影添加到您喜欢的列表中。
  4. 在 Firebase 控制台的 DebugView 中,验证在应用中添加电影时是否记录了这些事件。

9. 将 Analytics 数据导出到 Big Query

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

启用 Big Query 导出

  1. 转至火力地堡控制台
  2. 选择旁边的项目概述设置齿轮图标,然后选择项目设置
  3. 选择集成选项卡。
  4. 选择链接(或管理)的BigQuery的块中。
  5. 选择下一步有关链接火力地堡至BigQuery一步。
  6. 根据配置的集成部分,单击开关,可发送谷歌Analytics的数据,然后选择链接至BigQuery。

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

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

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

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

将示例数据集导入 BigQuery

  1. 转至BigQuery的在谷歌云控制台仪表板。
  2. 在菜单中选择您的项目名称。
  3. 在 BigQuery 左侧导航底部选择您的项目名称以查看详细信息。
  4. 选择创建数据集来打开数据集创建面板。
  5. 输入“firebase_recommendations_dataset”为数据集ID,然后选择创建数据集
  6. 新数据集将显示在项目名称下方的左侧菜单中。点击它。
  7. 选择创建表打开表的创建面板。
  8. 选择“谷歌云存储”创建表
  9. 从GCS斗选择文件,输入“GS://firebase-recommendations/recommendations-test/formatted_data_filtered.txt”。
  10. 文件格式选择“JSONL”降下来了。
  11. 输入“recommendations_table”表名
  12. 检查模式下的框>自动检测>模式和输入参数
  13. 选择创建表

探索示例数据集

此时,您可以选择探索架构并预览此数据集。

  1. 选择火力的建议,数据集在左侧菜单中展开它包含的表。
  2. 选择推荐表表查看表模式。
  3. 选择预览查看实际的分析事件数据该表中包含。

创建服务帐户凭据

现在,我们将在 Google Cloud 控制台项目中创建服务帐户凭据,我们可以在接下来的步骤中在 Colab 环境中使用它来访问和加载我们的 BigQuery 数据。

  1. 确保为您的 Google Cloud 项目启用了结算功能。
  2. 启用 BigQuery 和 BigQuery Storage API API。 <点击此处>
  3. 转至创建服务帐户密钥页
  4. 服务帐户列表中,选择新的服务帐户
  5. 服务帐户名称字段中,输入一个名称。
  6. 角色列表,选择项目>所有者
  7. 点击创建。包含下载到计算机的密钥的 JSON 文件。

在下一步中,我们将使用 Google Colab 来预处理这些数据并训练我们的推荐模型。

11. 预处理数据并训练推荐模型

在这一步中,我们将使用 Colab notebook 执行以下步骤:

  1. 将 BigQuery 数据导入 Colab 笔记本
  2. 预处理数据为模型训练做准备
  3. 在分析数据上训练推荐模型
  4. 将模型导出为 TF lite 模型
  5. 将模型部署到 Firebase 控制台,以便我们可以在我们的应用程序中使用它

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

启用 Firebase 模型管理 API

创建一个存储桶来存储您的 ML 模型

在您的 Firebase 控制台中,转到存储并单击开始。 fbbea78f0eb3dc9f.png

按照对话设置您的存储桶。

19517c0d6d2aa14d.png

启用 Firebase ML API

进入火力地堡ML API页面在谷歌云端控制台,然后单击启用。

使用 Colab notebook 训练和部署模型

使用以下链接打开 colab 笔记本并完成其中的步骤。完成 Colab 笔记本中的步骤后,您将有一个 TF lite 模型文件部署到 Firebase 控制台,我们可以将其同步到我们的应用程序。

在 Colab 中打开

12. 在您的应用程序中下载模型

在这一步中,我们将修改我们的应用程序以下载我们刚刚从 Firebase Machine Learning 训练的模型。

添加 Firebase ML 依赖项

需要以下依赖项才能在您的应用中使用 Firebase 机器学习模型。它应该已经被添加(验证)。

应用程序/build.grade

implementation 'com.google.firebase:firebase-ml-model-interpreter:22.0.4'

使用 Firebase Model Manager API 下载模型

下面的代码复制到RecommendationClient.kt建立在其模型下载发生的条件,并创建一个下载任务同步的远程模式,我们的应用程序。

推荐客户端.kt

    private fun downloadModel(modelName: String) {
        val remoteModel = FirebaseCustomRemoteModel.Builder(modelName).build()
        val firebaseModelManager = FirebaseModelManager.getInstance()
        firebaseModelManager
            .isModelDownloaded(remoteModel)
            .continueWithTask { task ->
                // Create update condition if model is already downloaded, otherwise create download
                // condition.
                val conditions = if (task.result != null && task.result == true) {
                    FirebaseModelDownloadConditions.Builder()
                        .requireWifi()
                        .build() // Update condition that requires wifi.
                } else {
                    FirebaseModelDownloadConditions.Builder().build(); // Download condition.
                }
                firebaseModelManager.download(remoteModel, conditions)
            }
            .addOnSuccessListener {
                firebaseModelManager.getLatestModelFile(remoteModel)
                    .addOnCompleteListener {
                        val model = it.result
                        if (model == null) {
                            showToast(context, "Failed to get model file.")
                        } else {
                            showToast(context, "Downloaded remote model")
                            GlobalScope.launch { initializeInterpreter(model) }
                        }
                    }
            }
            .addOnFailureListener {
                showToast(context, "Model download failed for recommendations, please check your connection.")
            }
    }



13. 在你的应用中集成 Tensorflow Lite 推荐模型

Tensorflow Lite 运行时将让您在应用程序中使用您的模型来生成建议。在上一步中,我们使用下载的模型文件初始化了一个 TFlite 解释器。在这一步中,我们将首先在推理步骤中加载字典和标签以伴随我们的模型,然后我们将添加预处理以生成模型的输入和后处理,我们将从推理中提取结果.

加载字典和标签

用来通过的建议模型推荐候选的标签在RES文件sorted_movie_vocab.json上市/ assets文件夹。复制以下代码以加载这些候选项。

推荐客户端.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.")
        }
    }

实施预处理

在预处理步骤中,我们更改输入数据的形式以匹配我们模型的预期。在这里,如果我们还没有产生很多用户喜欢,我们用占位符值填充输入长度。复制下面的代码:

推荐客户端.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
        }
    }


运行解释器以生成建议

在这里,我们使用我们在上一步中下载的模型对我们的预处理输入进行推理。我们为我们的模型设置输入和输出的类型并运行推理来生成我们的电影推荐。将以下代码复制到您的应用中。

推荐客户端.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()
            }
        }
    }



实施后处理

最后,在这一步中,我们对模型的输出进行后处理,选择置信度最高的结果并删除包含的值(用户已经喜欢的电影)。将以下代码复制到您的应用中。

推荐客户端.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 在您的应用中构建了推荐功能。请注意,此代码实验室中显示的技术和流程可以推广并用于提供其他类型的推荐。

我们涵盖的内容

  • 火力基地机器学习
  • Firebase 分析
  • 将分析事件导出到 BigQuery
  • 预处理分析事件
  • 训练推荐 TensorFlow 模型
  • 导出模型并部署到 Firebase 控制台
  • 在应用程序中提供电影推荐

下一步

  • 在您的应用中实施 Firebase ML 建议。

了解更多

有一个问题?

报告问题