Creare un sistema di consigli sui film completi

1. Prima di iniziare

Dal consigliare film o ristoranti all'evidenziare video divertenti, i motori per suggerimenti, noti anche come sistemi di raccomandazione, sono un'applicazione molto importante del machine learning. I sistemi di raccomandazione ti aiutano a mostrare agli utenti contenuti interessanti da un ampio pool di candidati. Ad esempio, il Google Play Store offre milioni di app da installare, mentre YouTube offre miliardi di video da guardare. Ogni giorno vengono aggiunti altri video e app.

In questo codelab imparerai a creare un sistema di raccomandazione full-stack utilizzando:

  • TensorFlow Recommenders per addestrare un modello di recupero e un modello di classificazione per i suggerimenti sui film
  • TensorFlow Serving per gestire i modelli
  • Flutter per creare un'app multipiattaforma per visualizzare i film consigliati

Prerequisiti

  • Conoscenza di base dello sviluppo Flutter con Dart
  • Conoscenza di base del machine learning con TensorFlow, ad esempio addestramento e deployment
  • Conoscenza di base dei sistemi di suggerimenti
  • Conoscenza di base di Python, terminali e Docker

Obiettivi didattici

  • Come addestrare modelli di recupero e classificazione utilizzando TensorFlow Recommenders
  • Come gestire i modelli di suggerimenti addestrati utilizzando TensorFlow Serving
  • Come creare un'app Flutter multipiattaforma per visualizzare gli articoli consigliati

Che cosa ti serve

2. Configura l'ambiente di sviluppo Flutter

Per lo sviluppo di Flutter, per completare questo codelab ti serviranno due software: l'SDK Flutter e un editor.

Puoi eseguire il frontend del codelab utilizzando uno qualsiasi di questi dispositivi:

  • Il simulatore iOS (richiede l'installazione degli strumenti Xcode).
  • L'emulatore Android (richiede la configurazione in Android Studio).
  • Un browser (Chrome è necessario per il debug).
  • Come applicazione desktop Windows, Linux o macOS. Devi sviluppare sulla piattaforma in cui prevedi di eseguire il deployment. Pertanto, se vuoi sviluppare un'app desktop Windows, devi svilupparla su Windows per accedere alla catena di build appropriata. Esistono requisiti specifici del sistema operativo trattati in dettaglio su docs.flutter.dev/desktop.

Per il backend, ti serviranno:

  • Un computer Linux o un Mac basato su Intel.

3. Configurazione

Per scaricare il codice per questo codelab:

  1. Vai al repository GitHub per questo codelab.
  2. Fai clic su Code > Download zip per scaricare tutto il codice di questo codelab.

2cd45599f51fb8a2.png

  1. Decomprimi il file ZIP scaricato per estrarre una cartella principale codelabs-main con tutte le risorse necessarie.

Per questo codelab, ti servono solo i file nella sottodirectory tfrs-flutter/ del repository, che contiene più cartelle:

  • Le cartelle da step0 a step5 contengono il codice iniziale su cui si basa ogni passaggio di questo codelab.
  • La cartella finished contiene il codice completato per l'app di esempio finita.
  • Ogni cartella contiene una sottocartella backend, che include il codice di backend del motore di suggerimenti, e una sottocartella frontend, che include il codice frontend di Flutter.

4. Scarica le dipendenze per il progetto

Backend

Utilizzeremo Flask per creare il nostro backend. Apri il terminale ed esegui questo comando:

pip install Flask flask-cors requests numpy

Frontend

  1. In VS Code, fai clic su File > Apri cartella e poi seleziona la cartella step0 dal codice sorgente che hai scaricato in precedenza.
  2. Apri il file step0/frontend/lib/main.dart. Se viene visualizzata una finestra di dialogo di VS Code che ti chiede di scaricare i pacchetti richiesti per l'app iniziale, fai clic su Scarica pacchetti.
  3. Se non vedi questa finestra di dialogo, apri il terminale ed esegui il comando flutter pub get nella cartella step0/frontend.

7ada07c300f166a6.png

5. Passaggio 0: esegui l'app iniziale

  1. Apri il file step0/frontend/lib/main.dart in VS Code, assicurati che l'emulatore Android o il simulatore iOS sia configurato correttamente e che venga visualizzato nella barra di stato.

Ad esempio, ecco cosa vedi quando utilizzi Pixel 5 con Android Emulator:

9767649231898791.png

Ecco cosa vedi quando utilizzi iPhone 13 con iOS Simulator:

95529e3a682268b2.png

  1. Fai clic su a19a0c68bc4046e6.png Avvia debug.

Eseguire ed esplorare l'app

L'app dovrebbe avviarsi sull'emulatore Android o sul simulatore iOS. L'interfaccia utente è piuttosto semplice. C'è un campo di testo che consente all'utente di digitare il testo come ID utente. L'app Flutter invierà la richiesta di query al backend, che esegue due modelli di suggerimento e restituisce un elenco classificato di consigli sui film. Dopo aver ricevuto la risposta, il frontend mostrerà il risultato nell'UI.

d21427db9587560f.png 73e8272a5ce8dfbc.png

Se fai clic su Consiglia ora, non succede nulla perché l'app non può ancora comunicare con il backend.

6. Passaggio 1: crea i modelli di recupero e ranking per il motore di suggerimenti

I motori per suggerimenti reali sono spesso composti da più fasi:

  1. La fase di recupero è responsabile della selezione di un insieme iniziale di centinaia di candidati tra tutti i possibili candidati. L'obiettivo principale di questo modello è eliminare in modo efficiente tutti i candidati che non interessano all'utente. Poiché il modello di recupero potrebbe dover gestire milioni di candidati, deve essere efficiente dal punto di vista computazionale.
  2. La fase di ranking prende gli output del modello di recupero e li perfeziona per selezionare il miglior numero possibile di consigli. Il suo compito è restringere l'insieme di elementi a cui l'utente potrebbe essere interessato a un elenco ristretto di probabili candidati nell'ordine delle centinaia.
  3. La fase post-ranking contribuisce a garantire diversità, freschezza ed equità e riorganizza gli elementi candidati in un insieme di consigli utili nell'ordine di decine.

70dfc0d7e989164f.png

Per questo codelab, addestrerai un modello di recupero e un modello di ranking utilizzando il popolare set di dati MovieLens. Puoi aprire il codice di addestramento riportato di seguito tramite Colab e seguire le istruzioni:

7. Passaggio 2: crea il backend del motore per suggerimenti

Ora che hai addestrato i modelli di recupero e ranking, puoi eseguirne il deployment e creare un backend.

Avvia TensorFlow Serving

Poiché devi utilizzare sia i modelli di recupero che quelli di ranking per generare l'elenco dei film consigliati, li implementi contemporaneamente utilizzando TensorFlow Serving.

  • Nel terminale, vai alla cartella step2/backend sul computer e avvia TensorFlow Serving con Docker:
docker run -t --rm -p 8501:8501 -p 8500:8500 -v "$(pwd)/:/models/" tensorflow/serving --model_config_file=/models/models.config

Docker scarica automaticamente l'immagine TensorFlow Serving, il che richiede un minuto. Dopodiché, TensorFlow Serving dovrebbe avviarsi. Il log dovrebbe avere l'aspetto seguente:

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

Crea un nuovo endpoint

Poiché TensorFlow Serving non supporta l'incatenamento di più modelli sequenziali, devi creare un nuovo servizio che colleghi i modelli di recupero e ranking.

  • Aggiungi questo codice alla funzione get_recommendations() nel file 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)

Avvia il servizio Flask

Ora puoi avviare il servizio Flask.

  • Nel terminale, vai alla cartella step2/backend/ ed esegui questo comando:
FLASK_APP=recommender.py FLASK_ENV=development flask run

Flask creerà un nuovo endpoint all'indirizzo http://localhost:5000/recommend. Dovresti vedere il log come di seguito:

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

Puoi inviare una richiesta di esempio all'endpoint per assicurarti che funzioni come previsto:

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

L'endpoint restituirà un elenco di film consigliati per l'utente 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)"
  ]
}

È tutto. Hai creato correttamente un backend per consigliare film in base a un ID utente.

8. Passaggio 3: crea l'app Flutter per Android e iOS

Il backend è pronto. Puoi iniziare a inviare richieste per interrogare i consigli sui film dall'app Flutter.

L'app frontend è piuttosto semplice. Ha solo un TextField che accetta l'ID utente e invia la richiesta (nella funzione recommend()) al backend che hai appena creato. Dopo aver ricevuto la risposta, la UI dell'app mostra i film consigliati in una ListView.

  • Aggiungi questo codice alla funzione recommend() nel file 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,
  }),
);

Una volta ricevuta la risposta dal backend, l'app aggiorna la UI per visualizzare l'elenco dei film consigliati per l'utente specificato.

  • Aggiungi questo codice subito sotto il codice precedente:
if (response.statusCode == 200) {
  return List<String>.from(jsonDecode(response.body)['movies']);
} else {
  throw Exception('Error response');
}

Esegui

  1. Fai clic su a19a0c68bc4046e6.png Avvia debug e attendi il caricamento dell'app.
  2. Inserisci un ID utente (ad es. 42) e poi seleziona Consiglia.

badb59d8b96959ae.png a0d2d4020aebfb0a.png

9. Passaggio 4: esegui l'app Flutter sulle piattaforme desktop

Oltre ad Android e iOS, Flutter supporta anche piattaforme desktop, tra cui Linux, Mac e Windows.

Linux

  1. Assicurati che il dispositivo di destinazione sia impostato su 86cba523de82b4f9.png nella barra di stato di VSCode.
  2. Fai clic su a19a0c68bc4046e6.png Avvia debug e attendi il caricamento dell'app.
  3. Inserisci un ID utente (ad es. 42) e poi seleziona Consiglia.

2665514231033f1.png

Mac

  1. Per Mac, devi configurare i diritti appropriati, poiché l'app invierà richieste HTTP al backend. Per ulteriori dettagli, consulta Diritti e sandbox dell'app.

Aggiungi questo codice a step4/frontend/macOS/Runner/DebugProfile.entitlements e step4/frontend/macOS/Runner/Release.entitlements rispettivamente:

<key>com.apple.security.network.client</key>
<true/>
  1. Assicurati che il dispositivo di destinazione sia impostato su eb4b0b5563824138.png nella barra di stato di VSCode.
  2. Fai clic su a19a0c68bc4046e6.png Avvia debug e attendi il caricamento dell'app.
  3. Inserisci un ID utente (ad es. 42) e poi seleziona Consiglia.

860d523a7ac537e0.png

Windows

  1. Assicurati che il dispositivo di destinazione sia impostato su 9587be1bb375bc0f.png nella barra di stato di VSCode.
  2. Fai clic su a19a0c68bc4046e6.png Avvia debug e attendi il caricamento dell'app.
  3. Inserisci un ID utente (ad es. 42) e poi seleziona Consiglia.

7d77c1e52a5927fc.png

10. Passaggio 5: esegui l'app Flutter sulla piattaforma web

Un'altra cosa che puoi fare è aggiungere il supporto web all'app Flutter. Per impostazione predefinita, la piattaforma web è attivata automaticamente per le app Flutter, quindi devi solo avviarla.

  1. Assicurati che il dispositivo di destinazione sia impostato su 71db93efa928d15d.png nella barra di stato di VSCode.
  2. Fai clic su a19a0c68bc4046e6.png Avvia debug e poi attendi che l'app venga caricata nel browser Chrome.
  3. Inserisci un ID utente (ad es. 42) e poi seleziona Consiglia.

9376e1e432c18bef.png

11. Complimenti

Hai creato un'app full stack per consigliare film ai tuoi utenti.

Sebbene l'app consigli solo film, hai imparato il flusso di lavoro generale per creare un potente motore di consigli e hai acquisito la capacità di utilizzare i consigli in un'app Flutter. Puoi applicare facilmente ciò che hai imparato ad altri scenari (ad es. e-commerce, cibo e video brevi).

Scopri di più