Tworzenie systemu rekomendacji filmów typu fullstack

1. Zanim zaczniesz

Systemy rekomendacji, zwane też rekomendatorami, to bardzo ważne zastosowanie uczenia maszynowego. Mogą one polecać filmy lub restauracje albo wyróżniać ciekawe filmy. Systemy rekomendacji pomagają Ci wyświetlać użytkownikom atrakcyjne treści z dużej puli kandydatów. Na przykład w Sklepie Google Play możesz zainstalować miliony aplikacji, a w YouTube obejrzeć miliardy filmów. Każdego dnia dodajemy kolejne aplikacje i filmy.

Z tego ćwiczenia w Codelabs dowiesz się, jak utworzyć pełną usługę polecającą przy użyciu:

  • TensorFlow Recommenders do trenowania modelu pobierania i modelu rankingowego na potrzeby rekomendacji filmów.
  • TensorFlow Serving do udostępniania modeli.
  • Flutter do tworzenia aplikacji na wielu platformach, która wyświetla rekomendowane filmy

Wymagania wstępne

  • Podstawowa wiedza na temat tworzenia aplikacji w Flutterze za pomocą języka Dart.
  • Podstawowa wiedza o uczeniu maszynowym za pomocą TensorFlow, np. różnice między trenowaniem a wdrażaniem.
  • Podstawowa znajomość systemów rekomendacji
  • Podstawowa znajomość Pythona, terminali i Dockera

Czego się nauczysz

  • Jak trenować modele wyszukiwania i rankingu za pomocą biblioteki TensorFlow Recommenders
  • Jak obsługiwać wytrenowane modele rekomendacji za pomocą TensorFlow Serving
  • Tworzenie aplikacji Flutter na wielu platformach do wyświetlania polecanych produktów

Czego potrzebujesz

2. Konfigurowanie środowiska programistycznego Fluttera

Aby ukończyć to ćwiczenie, potrzebujesz 2 programów: pakietu SDK Flutteredytora.

Frontend ćwiczeń możesz uruchomić na dowolnym z tych urządzeń:

  • Symulator iOS (wymaga zainstalowania narzędzi Xcode).
  • Android Emulator (wymaga konfiguracji w Android Studio).
  • przeglądarka (do debugowania wymagana jest Chrome);
  • Jako aplikacja komputerowa na Windows, Linux lub macOS. Musisz tworzyć aplikację na platformie, na której zamierzasz ją wdrożyć. Jeśli chcesz opracować aplikację na komputery z systemem Windows, musisz to zrobić na komputerze z tym systemem, aby mieć dostęp do odpowiedniego łańcucha kompilacji. Istnieją wymagania dotyczące poszczególnych systemów operacyjnych, które są szczegółowo opisane na stronie docs.flutter.dev/desktop.

W przypadku backendu potrzebne są:

  • komputer z systemem Linux lub Mac z procesorem Intel;

3. Konfiguracja

Aby pobrać kod do tego ćwiczenia:

  1. Otwórz repozytorium GitHub tego ćwiczenia.
  2. Aby pobrać cały kod do tych ćwiczeń z programowania, kliknij Code > Download zip (Kod > Pobierz plik ZIP).

2cd45599f51fb8a2.png

  1. Rozpakuj pobrany plik ZIP, aby wyodrębnić folder główny codelabs-main ze wszystkimi potrzebnymi zasobami.

W tym module potrzebne są tylko pliki z podkatalogu tfrs-flutter/ w repozytorium, który zawiera kilka folderów:

  • Foldery step0step5 zawierają kod startowy, który będziesz rozwijać w kolejnych krokach tego ćwiczenia.
  • Folder finished zawiera gotowy kod ukończonej przykładowej aplikacji.
  • Każdy folder zawiera podfolder backend, który zawiera kod backendu silnika rekomendacji, oraz podfolder frontend, który zawiera kod frontendowy Fluttera.

4. Pobierz zależności projektu.

Backend

Do utworzenia backendu użyjemy Flaska. Otwórz terminal i uruchom to polecenie:

pip install Flask flask-cors requests numpy

Frontend

  1. W VS Code kliknij File > Open folder (Plik > Otwórz folder), a następnie wybierz folder step0 z pobranego wcześniej kodu źródłowego.
  2. Otwórz plik step0/frontend/lib/main.dart. Jeśli pojawi się okno VS Code z prośbą o pobranie wymaganych pakietów dla aplikacji startowej, kliknij Pobierz pakiety.
  3. Jeśli nie widzisz tego okna, otwórz terminal, a następnie uruchom polecenie flutter pub get w folderze step0/frontend.

7ada07c300f166a6.png

5. Krok 0. Uruchom aplikację startową

  1. Otwórz plik step0/frontend/lib/main.dart w VS Code i upewnij się, że emulator Androida lub symulator iOS jest prawidłowo skonfigurowany i wyświetla się na pasku stanu.

Oto przykład tego, co zobaczysz, gdy użyjesz Pixela 5 z emulatorem Androida:

9767649231898791.png

Oto co zobaczysz, gdy użyjesz iPhone'a 13 z symulatorem iOS:

95529e3a682268b2.png

  1. Kliknij a19a0c68bc4046e6.png Rozpocznij debugowanie.

Uruchamianie aplikacji i jej poznawanie

Aplikacja powinna się uruchomić w emulatorze Androida lub symulatorze iOS. Interfejs jest dość prosty. Jest tam pole tekstowe, w którym użytkownik może wpisać tekst jako identyfikator użytkownika. Aplikacja Flutter wyśle żądanie zapytania do backendu, który uruchomi 2 modele rekomendacji i zwróci uporządkowaną listę rekomendacji filmów. Po otrzymaniu odpowiedzi interfejs wyświetli wynik w interfejsie użytkownika.

d21427db9587560f.png 73e8272a5ce8dfbc.png

Jeśli teraz klikniesz Poleć, nic się nie stanie, ponieważ aplikacja nie może jeszcze komunikować się z backendem.

6. Krok 1. Utwórz modele pobierania i rankingu dla systemu rekomendacji

Systemy rekomendacji w rzeczywistości często składają się z kilku etapów:

  1. Etap pobierania odpowiada za wybranie początkowego zestawu setek kandydatów spośród wszystkich możliwych kandydatów. Głównym celem tego modelu jest skuteczne odfiltrowanie wszystkich kandydatów, którymi użytkownik nie jest zainteresowany. Model pobierania może mieć do czynienia z milionami kandydatów, dlatego musi być wydajny obliczeniowo.
  2. Na etapie rankingu dane wyjściowe modelu pobierania są dopracowywane w celu wybrania najlepszych rekomendacji. Jego zadaniem jest zawężenie zbioru produktów, które mogą zainteresować użytkownika, do krótkiej listy prawdopodobnych kandydatów w liczbie setek.
  3. Etap pozycjonowania pomaga zapewnić różnorodność, aktualność i uczciwość oraz reorganizuje kandydatów w zestaw przydatnych rekomendacji w liczbie kilkudziesięciu.

70dfc0d7e989164f.png

W tym ćwiczeniu w Codelabs wytrenujesz model wyszukiwania i model rankingowy przy użyciu popularnego zbioru danych MovieLens. Poniższy kod szkoleniowy możesz otworzyć w Colab i postępować zgodnie z instrukcjami:

7. Krok 2. Utwórz backend systemu rekomendacji

Po wytrenowaniu modeli wyszukiwania i rankingu możesz je wdrożyć i utworzyć backend.

Uruchamianie TensorFlow Serving

Aby wygenerować listę rekomendowanych filmów, musisz użyć zarówno modelu pobierania, jak i modelu rankingowego, więc wdrażasz je jednocześnie za pomocą TensorFlow Serving.

  • W terminalu przejdź do folderu step2/backend na komputerze i uruchom TensorFlow Serving za pomocą Dockera:
docker run -t --rm -p 8501:8501 -p 8500:8500 -v "$(pwd)/:/models/" tensorflow/serving --model_config_file=/models/models.config

Docker najpierw automatycznie pobierze obraz TensorFlow Serving, co zajmie minutę. Następnie powinna się uruchomić usługa TensorFlow Serving. Dziennik powinien wyglądać jak ten fragment kodu:

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

Tworzenie nowego punktu końcowego

TensorFlow Serving nie obsługuje „łączenia” wielu modeli sekwencyjnych, dlatego musisz utworzyć nową usługę, która połączy modele wyszukiwania i rankingu.

  • Dodaj ten kod do funkcji get_recommendations() w pliku 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)

Uruchom usługę Flask

Teraz możesz uruchomić usługę Flask.

  • W terminalu przejdź do folderu step2/backend/ i uruchom to polecenie:
FLASK_APP=recommender.py FLASK_ENV=development flask run

Flask utworzy nowy punkt końcowy pod adresem http://localhost:5000/recommend. Dziennik powinien wyglądać tak:

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

Możesz wysłać do punktu końcowego przykładowe żądanie, aby upewnić się, że działa on zgodnie z oczekiwaniami:

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

Punkt końcowy zwróci listę polecanych filmów dla użytkownika 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)"
  ]
}

To wszystko. Udało Ci się utworzyć backend do polecania filmów na podstawie identyfikatora użytkownika.

8. Krok 3. Utwórz aplikację Flutter na Androida i iOS

Backend jest gotowy. Możesz zacząć wysyłać do niego żądania, aby uzyskać rekomendacje filmów z aplikacji Flutter.

Aplikacja frontendowa jest dość prosta. Zawiera tylko pole tekstowe, które przyjmuje identyfikator użytkownika i wysyła żądanie (w funkcji recommend()) do utworzonego właśnie backendu. Po otrzymaniu odpowiedzi interfejs aplikacji wyświetla polecane filmy w widoku ListView.

  • Dodaj ten kod do funkcji recommend() w pliku 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,
  }),
);

Gdy aplikacja otrzyma odpowiedź z backendu, zaktualizuj interfejs, aby wyświetlić listę polecanych filmów dla określonego użytkownika.

  • Dodaj ten kod bezpośrednio pod powyższym kodem:
if (response.statusCode == 200) {
  return List<String>.from(jsonDecode(response.body)['movies']);
} else {
  throw Exception('Error response');
}

Uruchom

  1. Kliknij a19a0c68bc4046e6.png Rozpocznij debugowanie, a następnie poczekaj na wczytanie aplikacji.
  2. Wpisz identyfikator użytkownika (np. 42), a następnie kliknij Poleć.

badb59d8b96959ae.png a0d2d4020aebfb0a.png

9. Krok 4. Uruchom aplikację Flutter na platformach desktopowych

Oprócz Androida i iOS Flutter obsługuje też platformy desktopowe, takie jak Linux, Mac i Windows.

Linux

  1. Upewnij się, że na pasku stanu VSCode wybrane urządzenie docelowe to 86cba523de82b4f9.png.
  2. Kliknij a19a0c68bc4046e6.png Rozpocznij debugowanie, a następnie poczekaj na wczytanie aplikacji.
  3. Wpisz identyfikator użytkownika (np. 42), a następnie kliknij Poleć.

2665514231033f1.png

Mac

  1. W przypadku komputerów Mac musisz skonfigurować odpowiednie uprawnienia, ponieważ aplikacja będzie wysyłać żądania HTTP do backendu. Więcej informacji znajdziesz w artykule Uprawnienia i piaskownica aplikacji.

Dodaj ten kod do plików step4/frontend/macOS/Runner/DebugProfile.entitlementsstep4/frontend/macOS/Runner/Release.entitlements:

<key>com.apple.security.network.client</key>
<true/>
  1. Upewnij się, że na pasku stanu VSCode wybrane urządzenie docelowe to eb4b0b5563824138.png.
  2. Kliknij a19a0c68bc4046e6.png Rozpocznij debugowanie, a następnie poczekaj na wczytanie aplikacji.
  3. Wpisz identyfikator użytkownika (np. 42), a następnie kliknij Poleć.

860d523a7ac537e0.png

Windows

  1. Upewnij się, że na pasku stanu VSCode wybrane urządzenie docelowe to 9587be1bb375bc0f.png.
  2. Kliknij a19a0c68bc4046e6.png Rozpocznij debugowanie, a następnie poczekaj na wczytanie aplikacji.
  3. Wpisz identyfikator użytkownika (np. 42), a następnie kliknij Poleć.

7d77c1e52a5927fc.png

10. Krok 5. Uruchom aplikację Flutter na platformie internetowej

Możesz też dodać obsługę internetu do aplikacji Flutter. Platforma internetowa jest domyślnie włączona w przypadku aplikacji Flutter, więc wystarczy ją uruchomić.

  1. Upewnij się, że na pasku stanu VSCode wybrane urządzenie docelowe to 71db93efa928d15d.png.
  2. Kliknij a19a0c68bc4046e6.png Rozpocznij debugowanie, a następnie poczekaj, aż aplikacja wczyta się w przeglądarce Chrome.
  3. Wpisz identyfikator użytkownika (np. 42), a następnie kliknij Poleć.

9376e1e432c18bef.png

11. Gratulacje

Udało Ci się stworzyć aplikację fullstack, która rekomenduje filmy użytkownikom.

Chociaż aplikacja rekomenduje tylko filmy, poznałeś(-aś) ogólny przepływ pracy związany z tworzeniem zaawansowanego systemu rekomendacji i opanowałeś(-aś) umiejętność korzystania z rekomendacji w aplikacji Flutter. Możesz łatwo zastosować zdobytą wiedzę w innych scenariuszach (np. w e-commerce, w przypadku jedzenia i krótkich filmów).

Więcej informacji