Como criar um sistema de recomendação de filmes de pilha completa

1. Antes de começar

Desde a recomendação de filmes ou restaurantes até o destaque de vídeos divertidos, os mecanismos de recomendação, também conhecidos como recomendadores, são uma aplicação muito importante do aprendizado de máquina. Os recomendadores ajudam você a mostrar conteúdo atraente de um grande conjunto de candidatos para seus usuários. Por exemplo, a Google Play Store oferece milhões de apps para você instalar, enquanto o YouTube oferece bilhões de vídeos para você assistir. E ainda mais apps e vídeos são adicionados a cada dia.

Neste codelab, você vai aprender a criar um recomendador de pilha completa usando:

  • TensorFlow Recommenders para treinar um modelo de recuperação e de classificação para recomendações de filmes
  • TensorFlow Serving para disponibilizar os modelos
  • Flutter para criar um app multiplataforma para mostrar filmes recomendados

Pré-requisitos

  • Conhecimento básico de desenvolvimento do Flutter com Dart
  • Conhecimento básico de machine learning com o TensorFlow, como treinamento ou implantação
  • Noções básicas sobre sistemas de recomendação
  • Conhecimento básico de Python, terminais e Docker

O que você vai aprender

  • Como treinar modelos de recuperação e classificação usando o TensorFlow Recommenders
  • Como exibir os modelos de recomendação treinados usando o TensorFlow Serving
  • Como criar um app Flutter multiplataforma para mostrar os itens recomendados.

O que é necessário

2. Configurar o ambiente de desenvolvimento do Flutter

Para desenvolver o Flutter, você precisa de dois softwares para concluir este codelab: o SDK do Flutter e um editor (links em inglês).

É possível executar o front-end do codelab usando qualquer um destes dispositivos:

  • O simulador para iOS, que exige a instalação de ferramentas do Xcode.
  • O Android Emulator, que requer configuração no Android Studio.
  • Um navegador (o Chrome é necessário para depuração).
  • Como um aplicativo para computador Windows, Linux ou macOS. Você precisa desenvolver na plataforma em que planeja implantar. Portanto, se quiser desenvolver um app para um computador Windows, você terá que desenvolver no Windows para acessar a cadeia de builds adequada. Há requisitos específicos de cada sistema operacional que são abordados em detalhes em docs.flutter.dev/desktop.

Para o back-end, você precisará do seguinte:

  • Uma máquina Linux ou um Mac com Intel.

3. Começar a configuração

Para fazer o download do código para este codelab, faça o seguinte:

  1. Navegue até o repositório do GitHub deste codelab.
  2. Clique em Code > Download zip para fazer o download de todo o código para este codelab.

2cd45599f51fb8a2.png

  1. Descompacte o arquivo ZIP salvo para acessar uma pasta raiz codelabs-main com todos os recursos necessários.

Para este codelab, você só precisa dos arquivos no subdiretório tfrs-flutter/ do repositório, que contém várias pastas:

  • As pastas de step0 a step5 contêm o código inicial baseado em cada etapa deste codelab.
  • A pasta finished contém o código concluído do app de exemplo finalizado.
  • Cada pasta contém uma subpasta backend, que inclui o código de back-end do mecanismo de recomendação, e uma subpasta frontend, que inclui o código de front-end do Flutter.

4. Fazer o download das dependências do projeto

Back-end

Vamos usar Flask para criar nosso back-end. Abra o terminal e execute o seguinte:

pip install Flask flask-cors requests numpy

Front-end

  1. No VS Code, clique em File > Open Folder e selecione a pasta step0 no código-fonte que você salvou anteriormente.
  2. Abra step0/frontend/lib/main.dart. Se aparecer uma caixa de diálogo do VS Code solicitando o download dos pacotes necessários para o app inicial, clique em Get packages.
  3. Se a caixa de diálogo não aparecer, abra o terminal e execute o comando flutter pub get na pasta step0/frontend.

7ada07c300f166a6.png

5. Etapa 0: executar o app inicial

  1. Abra o arquivo step0/frontend/lib/main.dart no VS Code, verifique se o Android Emulator ou o simulador de iOS está configurado corretamente e aparece na barra de status.

Por exemplo, veja o que você verá ao usar o Pixel 5 com o Android Emulator:

9767649231898791.png

Veja o que você verá ao usar o iPhone 13 com o iOS Simulator:

95529e3a682268b2.png

  1. Clique em a19a0c68bc4046e6.png Iniciar depuração.

Executar e explorar o app

O app será iniciado no Android Emulator ou no iOS Simulator. A interface é bem direta. Há um campo de texto que permite que o usuário digite o texto como o ID do usuário. O app Flutter vai enviar a solicitação de consulta para o back-end, que executa dois modelos de recomendação e retorna uma lista de classificação de recomendações de filmes. O front-end vai exibir o resultado na interface depois de receber a resposta.

d21427db9587560f.png 73e8272a5ce8dfbc.png

Se você clicar em Recomendar agora, nada acontecerá porque o app ainda não pode se comunicar com o back-end.

6. Etapa 1: criar os modelos de recuperação e classificação para o mecanismo de recomendação

Os mecanismos de recomendação do mundo real costumam ser compostos de vários estágios:

  1. A fase de recuperação é responsável por selecionar um conjunto inicial de centenas de candidatos dentre todos os possíveis. O principal objetivo deste modelo é eliminar de forma eficiente todos os candidatos em que o usuário não está interessado. Como o modelo de recuperação pode lidar com milhões de candidatos, ele precisa ser eficiente em termos computacionais.
  2. A fase de classificação usa os resultados do modelo de recuperação e os ajusta para selecionar a melhor quantidade de recomendações possível. Sua tarefa é restringir o conjunto de itens em que o usuário pode estar interessado em uma lista selecionada de prováveis candidatos na ordem de centenas.
  3. A fase pós-classificação ajuda a garantir a diversidade, a atualidade e a imparcialidade, além de reorganizar os itens candidatos em um conjunto de recomendações úteis na ordem de dezenas.

70dfc0d7e989164f.png

Neste codelab, você vai treinar um modelo de recuperação e um modelo de classificação usando o conhecido conjunto de dados MovieLens. É possível abrir o código de treinamento abaixo pelo Colab e seguir as instruções:

7. Etapa 2: criar o back-end do mecanismo de recomendação

Agora que você treinou os modelos de recuperação e classificação, é possível implantá-los e criar um back-end.

Iniciar o TensorFlow Serving

Como você precisa usar os modelos de recuperação e classificação para gerar a lista de filmes recomendados, implante os dois ao mesmo tempo usando o TensorFlow Serving.

  • No seu terminal, acesse a pasta step2/backend no computador e inicie o TensorFlow Serving com o Docker:
docker run -t --rm -p 8501:8501 -p 8500:8500 -v "$(pwd)/:/models/" tensorflow/serving --model_config_file=/models/models.config

Primeiro, o Docker faz o download automático da imagem do TensorFlow Serving em um minuto. Depois disso, o TensorFlow Serving será iniciado. O registro será semelhante a este snippet de código:

2022-04-24 09:32:06.461702: I tensorflow_serving/model_servers/server_core.cc:465] Adding/updating models.
2022-04-24 09:32:06.461843: I tensorflow_serving/model_servers/server_core.cc:591]  (Re-)adding model: retrieval
2022-04-24 09:32:06.461907: I tensorflow_serving/model_servers/server_core.cc:591]  (Re-)adding model: ranking
2022-04-24 09:32:06.576920: I tensorflow_serving/core/basic_manager.cc:740] Successfully reserved resources to load servable {name: retrieval version: 123}
2022-04-24 09:32:06.576993: I tensorflow_serving/core/loader_harness.cc:66] Approving load for servable version {name: retrieval version: 123}
2022-04-24 09:32:06.577011: I tensorflow_serving/core/loader_harness.cc:74] Loading servable version {name: retrieval version: 123}
2022-04-24 09:32:06.577848: I external/org_tensorflow/tensorflow/cc/saved_model/reader.cc:38] Reading SavedModel from: /models/retrieval/exported-retrieval/123
2022-04-24 09:32:06.583809: I external/org_tensorflow/tensorflow/cc/saved_model/reader.cc:90] Reading meta graph with tags { serve }
2022-04-24 09:32:06.583879: I external/org_tensorflow/tensorflow/cc/saved_model/reader.cc:132] Reading SavedModel debug info (if present) from: /models/retrieval/exported-retrieval/123
2022-04-24 09:32:06.584970: I external/org_tensorflow/tensorflow/core/platform/cpu_feature_guard.cc:142] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX2 FMA
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
2022-04-24 09:32:06.629900: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:206] Restoring SavedModel bundle.
2022-04-24 09:32:06.634662: I external/org_tensorflow/tensorflow/core/platform/profile_utils/cpu_utils.cc:114] CPU Frequency: 2800000000 Hz
2022-04-24 09:32:06.672534: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:190] Running initialization op on SavedModel bundle at path: /models/retrieval/exported-retrieval/123
2022-04-24 09:32:06.673629: I tensorflow_serving/core/basic_manager.cc:740] Successfully reserved resources to load servable {name: ranking version: 123}
2022-04-24 09:32:06.673765: I tensorflow_serving/core/loader_harness.cc:66] Approving load for servable version {name: ranking version: 123}
2022-04-24 09:32:06.673786: I tensorflow_serving/core/loader_harness.cc:74] Loading servable version {name: ranking version: 123}
2022-04-24 09:32:06.674731: I external/org_tensorflow/tensorflow/cc/saved_model/reader.cc:38] Reading SavedModel from: /models/ranking/exported-ranking/123
2022-04-24 09:32:06.683557: I external/org_tensorflow/tensorflow/cc/saved_model/reader.cc:90] Reading meta graph with tags { serve }
2022-04-24 09:32:06.683601: I external/org_tensorflow/tensorflow/cc/saved_model/reader.cc:132] Reading SavedModel debug info (if present) from: /models/ranking/exported-ranking/123
2022-04-24 09:32:06.688665: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:277] SavedModel load for tags { serve }; Status: success: OK. Took 110815 microseconds.
2022-04-24 09:32:06.690019: I tensorflow_serving/servables/tensorflow/saved_model_warmup_util.cc:59] No warmup data file found at /models/retrieval/exported-retrieval/123/assets.extra/tf_serving_warmup_requests
2022-04-24 09:32:06.693025: I tensorflow_serving/core/loader_harness.cc:87] Successfully loaded servable version {name: retrieval version: 123}
2022-04-24 09:32:06.702594: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:206] Restoring SavedModel bundle.
2022-04-24 09:32:06.745361: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:190] Running initialization op on SavedModel bundle at path: /models/ranking/exported-ranking/123
2022-04-24 09:32:06.772363: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:277] SavedModel load for tags { serve }; Status: success: OK. Took 97633 microseconds.
2022-04-24 09:32:06.774853: I tensorflow_serving/servables/tensorflow/saved_model_warmup_util.cc:59] No warmup data file found at /models/ranking/exported-ranking/123/assets.extra/tf_serving_warmup_requests
2022-04-24 09:32:06.777706: I tensorflow_serving/core/loader_harness.cc:87] Successfully loaded servable version {name: ranking version: 123}
2022-04-24 09:32:06.778969: I tensorflow_serving/model_servers/server_core.cc:486] Finished adding/updating models
2022-04-24 09:32:06.779030: I tensorflow_serving/model_servers/server.cc:367] Profiler service is enabled
2022-04-24 09:32:06.784217: I tensorflow_serving/model_servers/server.cc:393] Running gRPC ModelServer at 0.0.0.0:8500 ...
[warn] getaddrinfo: address family for nodename not supported
2022-04-24 09:32:06.785748: I tensorflow_serving/model_servers/server.cc:414] Exporting HTTP/REST API at:localhost:8501 ...
[evhttp_server.cc : 245] NET_LOG: Entering the event loop ...

Criar um novo endpoint

Como o TensorFlow Serving não oferece suporte ao encadeamento, vários modelos sequenciais, é preciso criar um novo serviço que conecte os modelos de recuperação e classificação.

  • Adicione este código à função get_recommendations() no arquivo step2/backend/recommendations.py:
user_id = request.get_json()["user_id"]
retrieval_request = json.dumps({"instances": [user_id]})
retrieval_response = requests.post(RETRIEVAL_URL, data=retrieval_request)
movie_candidates = retrieval_response.json()["predictions"][0]["output_2"]

ranking_queries = [
    {"user_id": u, "movie_title": m}
    for (u, m) in zip([user_id] * NUM_OF_CANDIDATES, movie_candidates)
]
ranking_request = json.dumps({"instances": ranking_queries})
ranking_response = requests.post(RANKING_URL, data=ranking_request)
movies_scores = list(np.squeeze(ranking_response.json()["predictions"]))
ranked_movies = [
    m[1] for m in sorted(list(zip(movies_scores, movie_candidates)), reverse=True)
]

return make_response(jsonify({"movies": ranked_movies}), 200)

Inicie o serviço Flask

Agora você pode iniciar o serviço Flask.

  • No seu terminal, acesse a pasta step2/backend/ e execute o seguinte:
FLASK_APP=recommender.py FLASK_ENV=development flask run

O Flask vai criar um novo endpoint em http://localhost:5000/recommend. O registro vai aparecer assim:

 * Serving Flask app 'recommender.py' (lazy loading)
 * Environment: development
 * Debug mode: on
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 705-382-264
127.0.0.1 - - [25/Apr/2022 19:44:47] "POST /recommend HTTP/1.1" 200 -

Você pode enviar um exemplo de solicitação ao endpoint para verificar se está funcionando conforme o esperado:

curl -X POST -H "Content-Type: application/json" -d '{"user_id":"42"}' http://localhost:5000/recommend

O endpoint vai retornar uma lista de filmes recomendados para o usuário 42:

{
  "movies": [
    "While You Were Sleeping (1995)",
    "Preacher's Wife, The (1996)",
    "Michael (1996)",
    "Lion King, The (1994)",
    "Father of the Bride Part II (1995)",
    "Sleepless in Seattle (1993)",
    "101 Dalmatians (1996)",
    "Bridges of Madison County, The (1995)",
    "Rudy (1993)",
    "Jack (1996)"
  ]
}

Pronto! Você criou um back-end para recomendar filmes com base em um ID de usuário.

8. Etapa 3: criar o app do Flutter para Android e iOS

O back-end está pronto. Comece a enviar solicitações a ele para consultar recomendações de filmes no app Flutter.

O app de front-end é bastante simples. Ela tem apenas um TextField que recebe o ID do usuário e envia a solicitação (na função recommend()) ao back-end que você acabou de criar. Depois de receber a resposta, a interface do app exibe os filmes recomendados em uma ListView.

  • Adicione este código à função recommend() no arquivo step3/frontend/lib/main.dart:
final response = await http.post(
  Uri.parse('http://' + _server + ':5000/recommend'),
  headers: <String, String>{
    'Content-Type': 'application/json',
  },
  body: jsonEncode(<String, String>{
    'user_id': _userIDController.text,
  }),
);

Depois que o app receber a resposta do back-end, você vai atualizar a interface para exibir a lista de filmes recomendados para o usuário especificado.

  • Adicione este código logo abaixo do código acima:
if (response.statusCode == 200) {
  return List<String>.from(jsonDecode(response.body)['movies']);
} else {
  throw Exception('Error response');
}

Executar

  1. Clique em a19a0c68bc4046e6.png Start debugging e aguarde o app carregar.
  2. Insira um ID do usuário (por exemplo, 42) e selecione Recomendar.

badb59d8b96959ae.png a0d2d4020aebfb0a.png

9. Etapa 4: executar o app do Flutter nas plataformas para computador

Além do Android e iOS, o Flutter também oferece suporte a plataformas de computador, incluindo Linux, Mac e Windows.

Linux

  1. Verifique se o dispositivo de destino está definido como 86cba523de82b4f9.png na barra de status do VSCode.
  2. Clique em a19a0c68bc4046e6.png Start debugging e aguarde o app carregar.
  3. Insira um ID do usuário (por exemplo, 42) e selecione Recomendar.

2665514231033f1.png

Mac

  1. No Mac, você precisa configurar os direitos apropriados, já que o app vai enviar solicitações HTTP para o back-end. Consulte Direitos e aplicativos sandbox para mais detalhes.

Adicione este código a step4/frontend/macOS/Runner/DebugProfile.entitlements e step4/frontend/macOS/Runner/Release.entitlements, respectivamente:

<key>com.apple.security.network.client</key>
<true/>
  1. Verifique se o dispositivo de destino está definido como eb4b0b5563824138.png na barra de status do VSCode.
  2. Clique em a19a0c68bc4046e6.png Start debugging e aguarde o app carregar.
  3. Insira um ID do usuário (por exemplo, 42) e selecione Recomendar.

860d523a7ac537e0.png

Windows

  1. Verifique se o dispositivo de destino está definido como 9587be1bb375bc0f.png na barra de status do VSCode.
  2. Clique em a19a0c68bc4046e6.png Start debugging e aguarde o app carregar.
  3. Insira um ID do usuário (por exemplo, 42) e selecione Recomendar.

7d77c1e52a5927fc.png

10. Etapa 5: executar o app do Flutter na plataforma da Web

Mais uma coisa que você pode fazer é adicionar suporte da Web ao app Flutter. Por padrão, a plataforma da Web é ativada automaticamente para apps Flutter, portanto, tudo o que você precisa fazer é iniciá-la.

  1. Verifique se o dispositivo de destino está definido como 71db93efa928d15d.png na barra de status do VSCode.
  2. Clique em a19a0c68bc4046e6.png Start debugging e aguarde o app carregar no navegador Chrome.
  3. Insira um ID do usuário (por exemplo, 42) e selecione Recomendar.

9376e1e432c18bef.png

11. Parabéns

Você criou um app de pilha completa para recomendar filmes aos usuários.

Embora o app recomende apenas filmes, você aprendeu o fluxo de trabalho geral para criar um mecanismo eficiente de recomendação e dominou a habilidade para consumir as recomendações em um app do Flutter. Você pode aplicar o que aprendeu facilmente a outros cenários (por exemplo, comércio eletrônico, culinária e vídeos curtos).

Saiba mais