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

歡迎使用 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 應用程序的體驗?

新手中間的精通

從命令行克隆 GitHub 存儲庫。

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

從Android Studio中,選擇codelab-recommendations-android目錄( android_studio_folder.png )從示例代碼下載(文件>打開> ... /代碼實驗室的建議,安卓/啟動)。

您現在應該在 Android Studio 中打開了啟動項目。

創建一個新項目

  1. 轉至火力地堡控制台
  2. 選擇添加項目(或創建一個項目,如果它是第一個)。
  3. 選擇或輸入項目名稱,然後點擊繼續
  4. 確保已啟用“為此項目啟用 Google Analytics”。
  5. 按照 Firebase 控制台中剩餘的設置步驟進行操作,然後點擊創建項目(或添加 Firebase,如果您使用的是現有的 Google 項目)。
  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中的工具欄搖籃文件

現在,您已經導入項目進入Android的工作室,並配置了google-services與您的JSON文件的插件,你就可以運行首次應用。連接您的Android設備,然後點擊運行執行.png ) 在 Android Studio 工具欄中。

該應用程序應在您的設備上啟動。此時,您可以看到一個功能正常的應用程序,該應用程序顯示一個帶有電影列表的選項卡、一個喜歡的電影選項卡和一個推薦選項卡。您可以單擊電影列表中的電影將其添加到您喜歡的列表中。完成 codelab 的其餘步驟後,我們將能夠在“推薦”選項卡中生成電影推薦。

在此步驟中,您將向應用添加 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)
        }
    }

在這一步中,我們將在應用程序中生成 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 中,驗證在應用中添加電影時是否記錄了這些事件。

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 以用於本教程的其餘部分。

現在我們已經連接了 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 來預處理這些數據並訓練我們的推薦模型。

在這一步中,我們將使用 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 中打開

在這一步中,我們將修改我們的應用程序以下載我們剛剛從 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.")
            }
    }



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


測試您的應用程序!

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

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

我們涵蓋的內容

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

下一步

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

了解更多

有一個問題?

報告問題