Creare un sistema di consigli sui film completi

1. Prima di iniziare

I motori per i consigli, noti anche come motori per suggerimenti, sono un'applicazione molto importante del machine learning, che si tratti di consigliare film o ristoranti all'evidenziazione di video di intrattenimento. I motori per suggerimenti ti aiutano a far emergere contenuti interessanti da un ampio pool di candidati per i tuoi utenti. Ad esempio, il Google Play Store offre milioni di app da installare, mentre YouTube offre miliardi di video da guardare. Ogni giorno vengono aggiunti sempre più video e app.

In questo codelab, imparerai come creare un motore per suggerimenti fullstack utilizzando:

  • Motori per suggerimenti TensorFlow per addestrare un modello di recupero e ranking per i suggerimenti relativi ai film
  • TensorFlow Serving per fornire i modelli
  • Flutter per creare un'app multipiattaforma per mostrare 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
  • Familiarità di base con i sistemi di suggerimenti
  • Conoscenza di base di Python, terminali e Docker

Obiettivi didattici

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

Che cosa ti serve

2. Configura l'ambiente di sviluppo di Flutter

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

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

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

Per il backend, avrai bisogno di:

  • 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 Codice > Scarica il file ZIP per scaricare tutto il codice per questo codelab.

2cd45599f51fb8a2.png

  1. Decomprimi il file ZIP scaricato per aprire una cartella principale codelabs-main con tutte le risorse di cui hai bisogno.

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 che creerai per ogni passaggio in questo codelab.
  • La cartella finished contiene il codice completato per l'app di esempio completata.
  • Ogni cartella contiene una sottocartella backend, che include il codice backend del motore per 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 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, quindi seleziona la cartella step0 dal codice sorgente scaricato in precedenza.
  2. Apri il file step0/frontend/lib/main.dart. Se viene visualizzata una finestra di dialogo VS Code che ti chiede di scaricare i pacchetti richiesti per l'app iniziale, fai clic su Ottieni 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 appaia nella barra di stato.

Ad esempio, ecco cosa vedi quando usi Pixel 5 con l'emulatore Android:

9767649231898791.png

Ecco cosa vedi quando usi iPhone 13 con il Simulatore di iOS:

95529e3a682268b2.png

  1. Fai clic su a19a0c68bc4046e6.png Avvia debug.

Esegui ed esplora 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 consigli e restituisce un elenco classificato di consigli sui film. Il frontend mostrerà il risultato nella UI dopo aver ricevuto la risposta.

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 per suggerimenti

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

  1. La fase di recupero prevede la selezione di un insieme iniziale di centinaia di candidati tra tutti i possibili candidati. L'obiettivo principale di questo modello è escludere in modo efficiente tutti i candidati a cui l'utente non è interessato. Poiché il modello di recupero potrebbe avere a che fare con 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 maggior numero possibile di suggerimenti. Il suo compito è restringere l'insieme di elementi che l'utente potrebbe essere interessato a una lista di candidati probabili nell'ordine di centinaia.
  3. La fase di post-ranking contribuisce a garantire diversità, aggiornamento ed equità e riorganizza gli elementi candidati in una serie di consigli utili dell'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 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 la pubblicazione di TensorFlow

Poiché devi utilizzare entrambi i modelli di recupero e ranking per generare l'elenco di film consigliati, esegui il deployment di entrambi contemporaneamente utilizzando TensorFlow Serving.

  • Nel terminale, vai alla cartella step2/backend sul tuo 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 prima l'immagine di TensorFlow Serving, che richiede un minuto. Successivamente, verrà avviata la pubblicazione di TensorFlow. Il log dovrebbe essere simile al seguente snippet di codice:

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 il "chaining" è necessario 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 supporterà un nuovo endpoint alle ore http://localhost:5000/recommend. Il log dovrebbe essere visualizzato come segue:

 * 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 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 ottenere consigli sui film dall'app Flutter.

L'app frontend è piuttosto semplice. Ha solo un campo di testo che accetta l'ID utente e invia la richiesta (nella funzione recommend()) al backend che hai appena creato. Dopo aver ricevuto la risposta, l'interfaccia utente dell'app mostra i film consigliati in un 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,
  }),
);

Quando l'app riceve la risposta dal backend, aggiorni la UI in modo da visualizzare l'elenco di film consigliati per l'utente specificato.

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

Eseguilo

  1. Fai clic su a19a0c68bc4046e6.png Avvia debug, quindi attendi il caricamento dell'app.
  2. Inserisci un ID utente (ad es. 42) e 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 come 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, quindi attendi il caricamento dell'app.
  3. Inserisci un ID utente (ad es. 42) e seleziona Consiglia.

2665514231033f1.png

Mac

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

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

<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, quindi attendi il caricamento dell'app.
  3. Inserisci un ID utente (ad es. 42) e 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, quindi attendi il caricamento dell'app.
  3. Inserisci un ID utente (ad es. 42) e 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 è abilitata automaticamente per le app Flutter, quindi non devi fare altro che 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, quindi attendi il caricamento dell'app nel browser Chrome.
  3. Inserisci un ID utente (ad es. 42) e seleziona Consiglia.

9376e1e432c18bef.png

11. Complimenti

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

Anche se l'app consiglia solo film, hai appreso il flusso di lavoro generale per creare un potente motore per suggerimenti e padroneggiando 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 brevi video).

Scopri di più