Adicionar recomendações ao app com o TensorFlow Lite e o Firebase: codelab do Android

1. Visão geral

Este é o codelab "Recomendações com TensorFlow Lite e Firebase". Neste codelab, você vai aprender a usar o TensorFlow Lite e o Firebase para implantar um modelo de recomendação no seu app. Este codelab é baseado neste exemplo do TensorFlow Lite.

Com as recomendações, os apps podem usar o aprendizado de máquina para veicular de forma inteligente o conteúdo mais relevante para cada usuário. Elas consideram o comportamento anterior do usuário para sugerir conteúdo do app com que ele pode querer interagir no futuro. Para isso, usam um modelo treinado com o comportamento agregado de um grande número de outros usuários.

Neste tutorial, mostramos como coletar dados dos usuários do seu app com o Firebase Analytics, criar um modelo de machine learning para recomendações com base nesses dados e usar esse modelo em um app Android para executar inferências e receber recomendações. Em particular, nossas recomendações sugerem os filmes que um usuário provavelmente vai assistir com base na lista de filmes que ele gostou anteriormente.

O que você vai aprender

  • Integrar o Firebase Analytics a um app Android para coletar dados de comportamento do usuário
  • Exportar esses dados para o Google BigQuery
  • Pré-processar os dados e treinar um modelo de recomendações do TF Lite
  • Implante o modelo do TF Lite no Firebase ML e acesse-o no app
  • Executar a inferência no dispositivo usando o modelo para sugerir recomendações aos usuários

O que é necessário

  • A versão mais recente do Android Studio.
  • Exemplo de código.
  • um dispositivo de teste com Android 7 ou mais recente e Google Play Services 9.8 ou mais recente, ou um emulador com Google Play Services 9.8 ou mais recente.
  • Se estiver usando um dispositivo, um cabo de conexão.

Como você usará este tutorial?

Apenas leitura Leitura e exercícios

Como você classificaria sua experiência com a criação de apps Android?

Iniciante Intermediário Proficiente

2. Acessar o exemplo de código

Clone o repositório do GitHub na linha de comando.

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

3. Importar o app inicial

No Android Studio, selecione o diretório codelab-recommendations-android ( android_studio_folder.png) no download do código de amostra (File > Open > .../codelab-recommendations-android/start).

Agora você deve ter o projeto inicial aberto no Android Studio.

4. Criar um projeto do console do Firebase

Criar um projeto

  1. Acesse o Console do Firebase.
  2. Selecione Adicionar projeto ou Criar um projeto se for o primeiro.
  3. Selecione ou insira um nome para o projeto e clique em Continuar.
  4. Verifique se a opção "Ativar o Google Analytics neste projeto" está marcada.
  5. Siga as demais etapas de configuração no Console do Firebase e clique em "Criar projeto" ou "Adicionar Firebase", se estiver usando um projeto atual do Google.

5. Adicionar Firebase

  1. Na tela de visão geral do novo projeto, clique no ícone do Android para iniciar o fluxo de trabalho de configuração.
  2. Insira o nome do pacote do codelab: com.google.firebase.codelabs.recommendations
  3. Selecione Registrar app.

Adicionar o arquivo google-services.json ao app

Depois de adicionar o nome do pacote e selecionar "Registrar", clique em Fazer o download do google-services.json para receber o arquivo de configuração do Firebase para Android. Em seguida, copie o arquivo google-services.json para o diretório app no projeto. Depois que o arquivo for baixado, clique em Pular nas próximas etapas mostradas no console. Elas já foram realizadas para você no projeto build-android-start.

Adicionar o plug-in google-services ao app

O plug-in google-services usa o arquivo google-services.json para configurar seu aplicativo para usar o Firebase. As linhas a seguir já devem estar adicionadas aos arquivos build.gradle.kts no projeto. Verifique para confirmar:

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
}

Sincronize seu projeto com arquivos do Gradle

Para garantir que todas as dependências estejam disponíveis para seu app, sincronize o projeto com os arquivos do Gradle neste momento. Selecione File > Sync Project with Gradle Files na barra de ferramentas do Android Studio.

6. Executar o app inicial

Agora que você importou o projeto para o Android Studio e configurou o plug-in google-services com seu arquivo JSON, já pode executar o app pela primeira vez. Conecte o dispositivo Android e clique em Executar ( execute.png) na barra de ferramentas do Android Studio.

O app vai ser iniciado no dispositivo. Neste ponto, você pode ver um aplicativo funcional que mostra uma guia com uma lista de filmes, uma guia "Filmes marcados como gostei" e uma guia "Recomendações". Clique em um filme na lista para adicioná-lo à sua lista de vídeos marcados como "Gostei". Depois de concluir as etapas restantes do codelab, será possível gerar recomendações de filmes na guia "Recomendações".

7. Adicionar o Firebase Analytics ao app

Nesta etapa, você vai adicionar o Firebase Analytics ao app para registrar dados de comportamento do usuário (neste caso, quais filmes um usuário gosta). Esses dados serão usados de forma agregada nas próximas etapas para treinar o modelo de recomendações.

Adicionar a lista de materiais do Firebase e a dependência do Analytics

As dependências a seguir são necessárias para adicionar o Google Analytics ao seu app. Elas já devem estar incluídas no arquivo app/build.gradle.kts (verifique).

app/build.grade.kts

implementation(platform("com.google.firebase:firebase-bom:32.0.0"))
implementation("com.google.firebase:firebase-analytics-ktx")

Configurar o Firebase Analytics no app

O LikedMoviesViewModel contém funções para armazenar os filmes que o usuário gosta. Sempre que o usuário gostar de um novo filme, também queremos enviar um evento de registro do Google Analytics para registrar essa ação.

Adicione a função "onMovieLiked" com o código abaixo para registrar um evento do Google Analytics quando o usuário clicar em "Gostei" em um filme.

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

Adicione o seguinte campo e função para registrar um evento do Google Analytics quando um filme for adicionado à lista de favoritos do usuário.

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. Testar a integração do Google Analytics

Nesta etapa, vamos gerar eventos do Google Analytics no app e verificar se eles estão sendo enviados ao console do Firebase.

Ativar a geração de registros de depuração do Google Analytics

O Firebase Analytics foi projetado para maximizar a vida útil da bateria do usuário. Ele agrupa eventos no dispositivo e os envia ao Firebase apenas ocasionalmente. Para fins de depuração, podemos desativar esse comportamento e ver os eventos registrados em tempo real executando o seguinte comando no shell.

Terminal

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

Verificar se os eventos do Google Analytics estão sendo gerados

  1. No Android Studio, abra a janela Logcat para examinar o registro do seu app.
  2. Defina o filtro do Logcat como a string "Logging event".
  3. Verifique se os eventos "select_item" do Google Analytics são emitidos sempre que você marca um filme como "Gostei" no app.

Neste ponto, você já integrou o Firebase Analytics ao seu app. À medida que os usuários usam o app e marcam filmes como favoritos, essas preferências são registradas de forma agregada. Vamos usar esses dados agregados no restante deste codelab para treinar nosso modelo de recomendações. Esta é uma etapa opcional para ver os mesmos eventos do Google Analytics que você viu no Logcat também transmitidos para o console do Firebase. Você pode pular para a próxima página.

Opcional: confirmar eventos do Analytics no console do Firebase

  1. Acesse o Console do Firebase.
  2. Selecione DebugView em "Analytics".
  3. No Android Studio, selecione Executar para iniciar o app e adicionar alguns filmes à sua lista de vídeos marcados como "Gostei".
  4. Na DebugView do console do Firebase, verifique se esses eventos estão sendo registrados à medida que você adiciona filmes no app.

9. Exportar dados do Analytics para o BigQuery

O BigQuery é um produto do Google Cloud que permite examinar e processar grandes quantidades de dados. Nesta etapa, você vai conectar seu projeto do console do Firebase ao BigQuery para que os dados do Google Analytics gerados pelo app sejam exportados automaticamente para o BigQuery.

Ativar o BigQuery Export

  1. Acesse o Console do Firebase.
  2. Selecione o ícone de engrenagem "Configurações" ao lado de Visão geral do projeto e escolha Configurações do projeto.
  3. Selecione a guia Integrações.
  4. Selecione Vincular (ou Gerenciar) no bloco BigQuery.
  5. Selecione Próxima na etapa Sobre a vinculação entre Firebase e BigQuery.
  6. Na seção Configurar integração, clique no botão para ativar o envio de dados do Google Analytics e selecione Vincular ao BigQuery.

Agora você ativou seu projeto do console do Firebase para enviar automaticamente dados de eventos do Firebase Analytics ao BigQuery. Isso acontece automaticamente sem mais interações. No entanto, a primeira exportação que cria o conjunto de dados de análise no BigQuery pode levar até 24 horas. Depois que o conjunto de dados é criado, o Firebase exporta continuamente novos eventos do Google Analytics para o BigQuery na tabela intradiária e agrupa os eventos de dias anteriores na tabela de eventos.

O treinamento de um modelo de recomendações exige muitos dados. Como ainda não temos um app que gere grandes quantidades de dados, na próxima etapa vamos importar um conjunto de dados de amostra para o BigQuery e usar no restante deste tutorial.

10. Usar o BigQuery para extrair dados de treinamento do modelo

Agora que conectamos o console do Firebase para exportar para o BigQuery, os dados de eventos de análise do app vão aparecer automaticamente no console do BigQuery depois de algum tempo. Para ter alguns dados iniciais para este tutorial, nesta etapa vamos importar um conjunto de dados de amostra para o console do BigQuery e usá-lo para treinar nosso modelo de recomendações.

Importar o conjunto de dados de amostra para o BigQuery

  1. Acesse o painel do BigQuery no console do Google Cloud.
  2. Selecione o nome do projeto no menu.
  3. Selecione o nome do projeto na parte de baixo da navegação à esquerda do BigQuery para conferir os detalhes.
  4. Selecione Criar conjunto de dados para abrir o painel de criação de conjuntos de dados.
  5. Insira "firebase_recommendations_dataset" no campo ID do conjunto de dados e selecione Criar conjunto de dados.
  6. O novo conjunto de dados vai aparecer no menu à esquerda, abaixo do nome do projeto. Clique nele.
  7. Selecione Criar tabela para abrir o painel de criação de tabela.
  8. Em Criar tabela de, selecione "Google Cloud Storage".
  9. No campo Selecionar arquivo do bucket do GCS, insira "gs://firebase-recommendations/recommendations-test/formatted_data_filtered.txt".
  10. Selecione "JSONL" no menu suspenso Formato do arquivo.
  11. Insira "recommendations_table" em Nome da tabela.
  12. Marque a caixa em Esquema > Detectar automaticamente > Parâmetros de esquema e entrada.
  13. Selecione Criar tabela.

Analisar o conjunto de dados de amostra

Neste ponto, você pode explorar o esquema e visualizar o conjunto de dados.

  1. Selecione firebase-recommendations-dataset no menu à esquerda para abrir as tabelas que ele contém.
  2. Selecione a tabela recommendations-table para conferir o esquema dela.
  3. Selecione Visualização para conferir os dados reais de eventos do Google Analytics que essa tabela contém.

Criar credenciais de conta de serviço

Agora, vamos criar credenciais de conta de serviço no projeto do console do Google Cloud que podem ser usadas no ambiente do Colab na próxima etapa para acessar e carregar os dados do BigQuery.

  1. Verifique se a cobrança está ativada para o seu projeto do Google Cloud.
  2. Ative as APIs BigQuery e BigQuery Storage. < clique aqui>
  3. Acesse a página Criar chave da conta de serviço.
  4. Na lista Conta de serviço, selecione Nova conta de serviço.
  5. No campo Nome da conta de serviço, insira um nome.
  6. Na lista Papel, selecione Projeto > Proprietário.
  7. Clique em Criar. O download de um arquivo JSON com sua chave é feito no seu computador.

Na próxima etapa, vamos usar o Google Colab para pré-processar esses dados e treinar nosso modelo de recomendações.

11. Pré-processar dados e treinar o modelo de recomendações

Nesta etapa, vamos usar um notebook do Colab para realizar as seguintes etapas:

  1. importar os dados do BigQuery para o notebook do Colab
  2. pré-processar os dados para prepará-los para o treinamento do modelo
  3. treinar o modelo de recomendações com os dados de análise
  4. exportar o modelo como um modelo do TF Lite
  5. implante o modelo no Console do Firebase para que possamos usá-lo no nosso app.

Antes de iniciar o notebook de treinamento do Colab, vamos ativar a API Firebase Model Management para que o Colab possa implantar o modelo treinado no Console do Firebase.

Ativar a API Firebase Model Management

Criar um bucket para armazenar seus modelos de ML

No console do Firebase, acesse "Storage" e clique em "Começar". fbbea78f0eb3dc9f.png

Siga o diálogo para configurar seu bucket.

19517c0d6d2aa14d.png

Ativar a API Firebase ML

Acesse a página da API Firebase ML no console do Google Cloud e clique em "Ativar".

Usar o notebook do Colab para treinar e implantar o modelo

Abra o notebook do Colab usando o link a seguir e conclua as etapas. Depois de concluir as etapas no bloco do Colab, você terá um arquivo de modelo do TF Lite implantado no Console do Firebase que pode ser sincronizado com o app.

Abrir no Colab

12. Baixar o modelo no app

Nesta etapa, vamos modificar o app para fazer o download do modelo que acabamos de treinar no Firebase Machine Learning.

Adicionar dependência do Firebase ML

A seguinte dependência é necessária para usar modelos de aprendizado de máquina do Firebase no seu app. Ela já deve ter sido adicionada (verifique).

app/build.grade.kts

implementation("com.google.firebase:firebase-ml-modeldownloader:24.1.2")

Baixe o modelo com a API Firebase Model Manager

Copie o código abaixo em RecommendationClient.kt para configurar as condições em que o download do modelo ocorre e crie uma tarefa de download para sincronizar o modelo remoto com nosso app.

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. Integrar o modelo de recomendação do TensorFlow Lite ao app

O tempo de execução do TensorFlow Lite permite usar o modelo no app para gerar recomendações. Na etapa anterior, inicializamos um interpretador do TFlite com o arquivo do modelo que baixamos. Nesta etapa, primeiro vamos carregar um dicionário e rótulos para acompanhar nosso modelo na etapa de inferência. Depois, vamos adicionar pré-processamento para gerar as entradas do modelo e pós-processamento para extrair os resultados da inferência.

Carregar dicionário e rótulos

Os rótulos usados para gerar os candidatos a recomendação pelo modelo de recomendações estão listados no arquivo sorted_movie_vocab.json na pasta res/assets. Copie o código a seguir para carregar esses candidatos.

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

Implementar o pré-processamento

Na etapa de pré-processamento, mudamos a forma dos dados de entrada para corresponder ao que nosso modelo espera. Aqui, adicionamos um valor de marcador de posição ao comprimento da entrada se ainda não tivermos gerado muitos likes do usuário. Copie o código abaixo:

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


Executar o intérprete para gerar recomendações

Aqui, usamos o modelo que baixamos em uma etapa anterior para executar a inferência na entrada pré-processada. Definimos o tipo de entrada e saída do nosso modelo e executamos a inferência para gerar recomendações de filmes. Copie o código a seguir no seu app.

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



Implementar pós-processamento

Por fim, nesta etapa, fazemos o pós-processamento da saída do nosso modelo, selecionando os resultados com maior confiança e removendo os valores contidos (filmes que o usuário já gostou). Copie o código a seguir no seu app.

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


Teste seu app!

Execute o app novamente. Ao selecionar alguns filmes, ele vai baixar automaticamente o novo modelo e começar a gerar recomendações.

14. Parabéns!

Você criou um recurso de recomendações no seu app usando o TensorFlow Lite e o Firebase. As técnicas e o pipeline mostrados neste codelab podem ser generalizados e usados para veicular outros tipos de recomendações também.

O que vimos

  • Firebase ML
  • Firebase Analytics
  • Exportar eventos do Google Analytics para o BigQuery
  • Pré-processar eventos do Analytics
  • Treinar um modelo do TensorFlow de recomendações
  • Exportar o modelo e implantar no console do Firebase
  • Veicular recomendações de filmes em um app

Próximas etapas

  • Implemente as recomendações do Firebase ML no seu app.

Saiba mais

Perguntas?

Informar problemas