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
- SDK do Flutter (em inglês)
- Configuração do Android e iOS para o Flutter
- Configuração de computadores para o Flutter
- Configuração da Web para o Flutter
- Configuração do Visual Studio Code (VS Code) para Flutter e Dart
- Docker
- Bash
- Python 3.7 ou superior
- Acesso ao Colab
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:
- Navegue até o repositório do GitHub deste codelab.
- Clique em Code > Download zip para fazer o download de todo o código para este codelab.
- 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
astep5
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 subpastafrontend
, 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
- No VS Code, clique em File > Open Folder e selecione a pasta
step0
no código-fonte que você salvou anteriormente. - 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. - Se a caixa de diálogo não aparecer, abra o terminal e execute o comando
flutter pub get
na pastastep0/frontend
.
5. Etapa 0: executar o app inicial
- 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:
Veja o que você verá ao usar o iPhone 13 com o iOS Simulator:
- Clique em 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.
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:
- 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.
- 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.
- 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.
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 arquivostep2/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 arquivostep3/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
- Clique em Start debugging e aguarde o app carregar.
- Insira um ID do usuário (por exemplo, 42) e selecione Recomendar.
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
- Verifique se o dispositivo de destino está definido como na barra de status do VSCode.
- Clique em Start debugging e aguarde o app carregar.
- Insira um ID do usuário (por exemplo, 42) e selecione Recomendar.
Mac
- 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/>
- Verifique se o dispositivo de destino está definido como na barra de status do VSCode.
- Clique em Start debugging e aguarde o app carregar.
- Insira um ID do usuário (por exemplo, 42) e selecione Recomendar.
Windows
- Verifique se o dispositivo de destino está definido como na barra de status do VSCode.
- Clique em Start debugging e aguarde o app carregar.
- Insira um ID do usuário (por exemplo, 42) e selecione Recomendar.
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.
- Verifique se o dispositivo de destino está definido como na barra de status do VSCode.
- Clique em Start debugging e aguarde o app carregar no navegador Chrome.
- Insira um ID do usuário (por exemplo, 42) e selecione Recomendar.
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).