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 machine learning. Os recomendadores ajudam você a mostrar conteúdo atraente de um grande pool de candidatos aos seus usuários. Por exemplo, a Google Play Store oferece milhões de apps para instalar, enquanto o YouTube fornece bilhões de vídeos para assistir. E mais apps e vídeos são adicionados todos os dias.

Neste codelab, você vai aprender a criar um recomendador full-stack usando:

  • TensorFlow Recommenders para treinar um modelo de recuperação e classificação para recomendações de filmes
  • TensorFlow Serving para veicular os modelos
  • Flutter para criar um app multiplataforma que mostre 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
  • Conhecimento básico de 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 veicular 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 o desenvolvimento em Flutter, você precisa de dois softwares para concluir este codelab: o SDK do Flutter e um editor.

É 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ê vai precisar do seguinte:

  • Um computador Linux ou um Mac baseado em 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 baixado para descompactar uma pasta raiz codelabs-main com todos os recursos necessários.

Neste codelab, você só precisará 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 o 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 e 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 ao usuário digitar o texto como ID de usuário. O app Flutter vai enviar a solicitação de consulta ao back-end, que executa dois modelos de recomendação e retorna uma lista classificada de recomendações de filmes. O front-end vai mostrar o resultado na interface depois de receber a resposta.

d21427db9587560f.png 73e8272a5ce8dfbc.png

Se você clicar em Recomendar agora, nada vai acontecer porque o app ainda não consegue 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 geralmente são compostos de várias etapas:

  1. A etapa de recuperação é responsável por selecionar um conjunto inicial de centenas de candidatos entre todos os possíveis. O principal objetivo desse modelo é eliminar de forma eficiente todos os candidatos que não interessam ao usuário. Como o modelo de recuperação pode lidar com milhões de candidatos, ele precisa ser eficiente em termos de computação.
  2. A etapa de classificação usa as saídas do modelo de recuperação e as ajusta para selecionar as melhores recomendações possíveis. A tarefa dele é reduzir o conjunto de itens em que o usuário pode ter interesse a uma lista restrita de prováveis candidatos na ordem de centenas.
  3. A etapa pós-ranking ajuda a garantir diversidade, novidade e justiça, além de reorganizar os itens candidatos em um conjunto de recomendações úteis na ordem de dezenas.

70dfc0d7e989164f.png

Neste codelab, você treina um modelo de recuperação e um modelo de classificação usando o conjunto de dados MovieLens. Abra o código de treinamento abaixo no Colab e siga 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 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 endpoint

Como o TensorFlow Serving não é compatível com o encadeamento de vários modelos sequenciais, é necessário 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)

Iniciar o serviço do Flask

Agora você pode iniciar o serviço do Flask.

  • No 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 -

Envie uma solicitação de amostra ao endpoint para garantir que ele esteja funcionando como 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 Flutter para Android e iOS

O back-end está pronto. Você pode começar a enviar solicitações para consultar recomendações de filmes no app Flutter.

O app de front-end é bem simples. Ele só tem um TextField que recebe o ID do usuário e envia a solicitação (na função recommend()) para o back-end que você acabou de criar. Depois de receber a resposta, a interface do app mostra 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 recebe a resposta do back-end, você atualiza a interface para mostrar 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 de usuário (por exemplo, 42) e selecione Recomendar.

badb59d8b96959ae.png a0d2d4020aebfb0a.png

9. Etapa 4: executar o app 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 de usuário (por exemplo, 42) e selecione Recomendar.

2665514231033f1.png

Mac

  1. Para Mac, você precisa configurar os direitos apropriados porque o app envia 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 de 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 de usuário (por exemplo, 42) e selecione Recomendar.

7d77c1e52a5927fc.png

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

Outra coisa que você pode fazer é adicionar suporte da Web ao app Flutter. Por padrão, a plataforma da Web é ativada automaticamente para apps do 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 de 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 de criação de um mecanismo de recomendação eficiente e dominou a habilidade de consumir as recomendações em um app Flutter. É fácil aplicar o que você aprendeu a outros cenários (por exemplo, e-commerce, comida e vídeos curtos).

Saiba mais