Tworzenie systemu rekomendacji filmów typu fullstack

1. Zanim zaczniesz

Systemy rekomendacji to bardzo ważne zastosowanie systemów uczących się – od polecania filmów lub restauracji po wyróżnianie zabawnych filmów. Usługi polecające pomagają prezentować Twoim użytkownikom atrakcyjne treści pochodzące od dużej liczby kandydatów. Na przykład Sklep Google Play oferuje do zainstalowania miliony aplikacji, a YouTube zapewnia dostęp do miliardów filmów do obejrzenia. Codziennie dodajemy kolejne aplikacje i filmy.

Z tego ćwiczenia w Codelabs dowiesz się, jak utworzyć usługę polecającą typu fullstack za pomocą:

  • Usługi polecające TensorFlow trenują pobieranie i model rankingowy na potrzeby rekomendacji filmów
  • TensorFlow Serving (udostępnianie TensorFlow) do obsługi modeli
  • Flutter tworzy aplikację wieloplatformową do wyświetlania polecanych filmów

Wymagania wstępne

  • Podstawowa wiedza o rozwoju technologii Flutter w Dart
  • Podstawowa wiedza na temat systemów uczących się z wykorzystaniem TensorFlow, np. do trenowania i wdrażania
  • Podstawowa znajomość systemów rekomendacji
  • Podstawowa znajomość Pythona, terminali i Dockera

Czego się nauczysz

  • Jak trenować modele pobierania i wyznaczania pozycji w rankingu za pomocą usług polecających TensorFlow
  • Jak udostępniać wytrenowane modele rekomendacji za pomocą TensorFlow Serving
  • Jak utworzyć wieloplatformową aplikację Flutter do wyświetlania zalecanych elementów

Czego potrzebujesz

2. Konfigurowanie środowiska programistycznego Flutter

Do programowania w technologii Flutter potrzebujesz 2 programów do ukończenia ćwiczenia – pakietu SDK Flutter i edytora.

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

  • Symulator iOS (wymaga zainstalowania narzędzi Xcode).
  • Emulator Androida (wymaga skonfigurowania Android Studio).
  • Przeglądarka (do debugowania wymagany jest Chrome).
  • Aplikacja komputerowa w systemie Windows, Linux lub macOS Programowanie należy tworzyć na platformie, na której zamierzasz wdrożyć usługę. Jeśli więc chcesz opracować aplikację komputerową dla systemu Windows, musisz to zrobić w tym systemie, aby uzyskać dostęp do odpowiedniego łańcucha kompilacji. Istnieją wymagania związane z konkretnymi systemami operacyjnymi, które zostały szczegółowo omówione na stronie docs.flutter.dev/desktop.

Co będzie potrzebne do korzystania z backendu:

  • Komputer z systemem Linux lub Mac z procesorem Intel.

3. Konfiguracja

Aby pobrać kod do tego ćwiczenia z programowania:

  1. Aby przeprowadzić ten moduł, przejdź do repozytorium GitHub.
  2. Kliknij Kod > Pobierz plik ZIP, aby pobrać cały kod do tego ćwiczenia z programowania.

2cd45599f51fb8a2.png

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

Aby wykonać te ćwiczenia w Codelabs, potrzebujesz tylko plików w podkatalogu tfrs-flutter/ repozytorium, które zawiera wiele folderów:

  • Foldery od step0 do step5 zawierają kod startowy, który powstał w każdym kroku tego ćwiczenia z programowania.
  • Folder finished zawiera kompletny kod gotowej przykładowej aplikacji.
  • Każdy folder zawiera podfolder backend zawierający kod backendu systemu rekomendacji oraz podfolder frontend zawierający kod frontendu Flutter

4. Pobierz zależności w projekcie

Backend

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

pip install Flask flask-cors requests numpy

Frontend

  1. W sekcji VS Code kliknij File (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 pakietów wymaganych do aplikacji startowej, kliknij Pobierz pakiety.
  3. Jeśli nie widzisz tego okna, otwórz terminal i 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. Sprawdź, czy emulator Androida lub symulator iOS są prawidłowo skonfigurowane i wyświetlają się na pasku stanu.

Na przykład podczas używania Pixela 5 z emulatorem Androida możesz zobaczyć takie elementy:

9767649231898791.png

Oto, co możesz zobaczyć, używając iPhone'a 13 za pomocą symulatora iOS:

95529e3a682268b2.png

  1. Kliknij a19a0c68bc4046e6.png Rozpocznij debugowanie.

Uruchamianie i poznawanie aplikacji

Aplikacja powinna się uruchomić w emulatorze Androida lub symulatorze iOS. Interfejs jest dość prosty. Dostępne jest 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 uruchamia 2 modele rekomendacji i zwraca uporządkowaną listę rekomendacji filmów. Po otrzymaniu odpowiedzi frontend wyświetli wynik w interfejsie użytkownika.

d21427db9587560f.png 73e8272a5ce8dfbc.png

Jeśli teraz klikniesz Polecaj, 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

Rzeczywiste systemy rekomendacji często składają się z wielu etapów:

  1. Etap pobierania odpowiada za wybranie początkowego zestawu setek propozycji spośród wszystkich możliwych. Głównym celem tego modelu jest skuteczne usuwanie wszystkich kandydatów, którymi użytkownik nie jest zainteresowany. Model pobierania może obejmować miliony kandydatów, dlatego musi być wydajny pod względem obliczeń.
  2. Na etapie tworzenia rankingu analizuje dane wyjściowe modelu pobierania i dostosowuje je, aby wybrać najlepszą możliwą grupę rekomendacji. Jego zadaniem jest zawężenie listy pozycji, które mogą zainteresować użytkownika, do opartej na kilkuset krótkiej liście prawdopodobnych kandydatów.
  3. Etap po rankingu pomaga zapewnić różnorodność, aktualność i obiektywność, a także reorganizuje kandydujące elementy w zestaw przydatnych rekomendacji w kolejności dziesiątek.

70dfc0d7e989164f.png

Na potrzeby tego ćwiczenia w Codelabs wytrenujesz model pobierania i model rankingowy, korzystając z popularnego zbioru danych MovieLens. Możesz otworzyć w Colab poniższy kod trenowania i postępować zgodnie z instrukcjami:

7. Krok 2. Utwórz backend systemu rekomendacji

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

Rozpocznij udostępnianie TensorFlow

Do wygenerowania zalecanej listy filmów musisz używać obu modeli pobierania i modelowania rankingu, więc wdrażasz je jednocześnie przy użyciu TensorFlow Serving.

  • W terminalu otwórz folder step2/backend na komputerze i uruchom TensorFlow Serving with Docker:
docker run -t --rm -p 8501:8501 -p 8500:8500 -v "$(pwd)/:/models/" tensorflow/serving --model_config_file=/models/models.config

Docker automatycznie pobiera najpierw obraz TensorFlow Serving, co zajmuje minutę. Następnie powinna uruchomić się usługa TensorFlow Serving. Dziennik powinien wyglądać tak:

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

Utwórz nowy punkt końcowy

Ponieważ TensorFlow Serving nie obsługuje „łańcuchów” wielu modeli sekwencyjnych, musisz utworzyć nową usługę, która łączy modele pobierania 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)

Uruchamianie usługi 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 ustawi nowy punkt końcowy na http://localhost:5000/recommend. Dziennik powinien wyświetlić się poniżej:

 * 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ć przykładowe żądanie do punktu końcowego, aby sprawdzić, czy 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ę filmów polecanych 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)"
  ]
}

Znakomicie. 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 niej żądania, aby otrzymywać z aplikacji Flutter zapytania o rekomendacje filmów.

Aplikacja frontendu jest dość prosta. Zawiera tylko pole TextField, które pobiera identyfikator użytkownika i wysyła żądanie (w funkcji recommend()) do właśnie utworzonego backendu. Po otrzymaniu odpowiedzi interfejs aplikacji wyświetli 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, zaktualizujesz interfejs, aby wyświetlić listę polecanych filmów dla określonego użytkownika.

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

Uruchom

  1. Kliknij a19a0c68bc4046e6.png Rozpocznij debugowanie i poczekaj na wczytanie aplikacji.
  2. Wpisz identyfikator użytkownika (np. 42) a następnie wybierz Polecaj.

badb59d8b96959ae.png a0d2d4020aebfb0a.png

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

Oprócz Androida i iOS Flutter obsługuje także platformy komputerowe, takie jak Linux, Mac i Windows.

Linux

  1. Upewnij się, że urządzenie docelowe na pasku stanu VSCode jest ustawione na 86cba523de82b4f9.png.
  2. Kliknij a19a0c68bc4046e6.png Rozpocznij debugowanie i poczekaj na wczytanie aplikacji.
  3. Wpisz identyfikator użytkownika (np. 42) a następnie wybierz Polecaj.

2665514231033f1.png

Mac

  1. W przypadku Maca 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 odpowiednio do step4/frontend/macOS/Runner/DebugProfile.entitlements i step4/frontend/macOS/Runner/Release.entitlements:

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

860d523a7ac537e0.png

Windows

  1. Upewnij się, że urządzenie docelowe na pasku stanu VSCode jest ustawione na 9587be1bb375bc0f.png.
  2. Kliknij a19a0c68bc4046e6.png Rozpocznij debugowanie i poczekaj na wczytanie aplikacji.
  3. Wpisz identyfikator użytkownika (np. 42) a następnie wybierz Polecaj.

7d77c1e52a5927fc.png

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

Możesz też dodać obsługę sieci do aplikacji Flutter. Domyślnie platforma internetowa jest automatycznie włączona dla aplikacji Flutter, więc wystarczy ją uruchomić.

  1. Upewnij się, że urządzenie docelowe na pasku stanu VSCode jest ustawione na 71db93efa928d15d.png.
  2. Kliknij a19a0c68bc4046e6.png Rozpocznij debugowanie i poczekaj na wczytanie aplikacji w przeglądarce Chrome.
  3. Wpisz identyfikator użytkownika (np. 42) a następnie wybierz Polecaj.

9376e1e432c18bef.png

11. Gratulacje

Udało Ci się stworzyć aplikację fullstack do polecania filmów Twoim użytkownikom.

Chociaż aplikacja tylko poleca filmy, znasz już ogólny przepływ pracy związany z tworzeniem zaawansowanego systemu rekomendacji i opanujesz umiejętność korzystania z rekomendacji w aplikacji Flutter. Zdobytą wiedzę możesz z łatwością wykorzystać w innych scenariuszach (np. w branży e-commerce, jedzenia czy krótkich filmów).

Więcej informacji