Xây dựng hệ thống đề xuất phim fullstack

1. Trước khi bắt đầu

Từ đề xuất phim hoặc nhà hàng cho đến giới thiệu video giải trí, công cụ đề xuất (còn gọi là công cụ đề xuất) là một ứng dụng rất quan trọng của công nghệ học máy. Các tính năng đề xuất giúp bạn hiển thị những nội dung hấp dẫn từ một nhóm lớn các đề xuất cho người dùng. Ví dụ: Cửa hàng Google Play cung cấp hàng triệu ứng dụng để cài đặt, trong khi YouTube cung cấp hàng tỷ video để xem. Và thậm chí nhiều ứng dụng và video hơn được thêm vào mỗi ngày.

Trong lớp học lập trình này, bạn sẽ tìm hiểu cách tạo trình đề xuất cho fullstack bằng cách sử dụng:

  • Dịch vụ đề xuất của TensorFlow huấn luyện hoạt động truy xuất và mô hình xếp hạng để đề xuất phim
  • TensorFlow phục vụ cho các mô hình
  • Flutter tạo một ứng dụng đa nền tảng để hiển thị các phim đề xuất

Điều kiện tiên quyết

  • Kiến thức cơ bản về cách phát triển Flutter bằng Dart
  • Kiến thức cơ bản về công nghệ học máy với TensorFlow, chẳng hạn như huấn luyện so với triển khai
  • Hiểu biết cơ bản về các hệ thống đề xuất
  • Kiến thức cơ bản về Python, Terminal và Docker

Kiến thức bạn sẽ học được

  • Cách huấn luyện các mô hình truy xuất và xếp hạng bằng tính năng Đề xuất TensorFlow
  • Cách phân phát các mô hình đề xuất đã qua đào tạo bằng tính năng Phân phát TensorFlow
  • Cách tạo một ứng dụng Flutter đa nền tảng để hiển thị các mặt hàng được đề xuất

Bạn cần có

2. Thiết lập môi trường phát triển Flutter

Để phát triển Flutter, bạn cần có 2 phần mềm để hoàn thành lớp học lập trình này: Flutter SDKtrình chỉnh sửa.

Bạn có thể chạy giao diện người dùng của lớp học lập trình này bằng bất kỳ thiết bị nào sau đây:

  • Trình mô phỏng iOS (yêu cầu cài đặt công cụ Xcode).
  • Trình mô phỏng Android (yêu cầu thiết lập trong Android Studio).
  • Trình duyệt (cần có Chrome để gỡ lỗi).
  • Dưới dạng ứng dụng Windows, Linux hoặc macOS. Bạn phải phát triển trên nền tảng mà bạn dự định triển khai. Vì vậy, nếu muốn phát triển một ứng dụng Windows dành cho máy tính, bạn phải phát triển trên Windows để truy cập vào chuỗi bản dựng phù hợp. Có các yêu cầu cụ thể theo hệ điều hành được đề cập chi tiết trên docs.flutter.dev/desktop.

Đối với phần phụ trợ, bạn sẽ cần:

  • Máy Linux hoặc máy Mac sử dụng chip Intel.

3. Bắt đầu thiết lập

Cách tải mã nguồn cho lớp học lập trình này:

  1. Chuyển đến kho lưu trữ GitHub cho lớp học lập trình này.
  2. Nhấp vào Mã > Tải tệp zip xuống để tải tất cả mã nguồn cho lớp học lập trình này.

2cd45599f51fb8a2.pngS

  1. Giải nén tệp zip đã tải xuống để giải nén thư mục gốc codelabs-main cùng tất cả tài nguyên bạn cần.

Đối với lớp học lập trình này, bạn chỉ cần các tệp trong thư mục con tfrs-flutter/ trong kho lưu trữ, nơi chứa nhiều thư mục:

  • Các thư mục step0 đến step5 chứa mã khởi đầu mà bạn sẽ xây dựng cho từng bước trong lớp học lập trình này.
  • Thư mục finished chứa mã nguồn đã hoàn tất cho ứng dụng mẫu đã hoàn thiện.
  • Mỗi thư mục chứa một thư mục con backend, trong đó có mã phụ trợ của công cụ đề xuất và một thư mục con frontend, trong đó có mã giao diện người dùng Flutter

4. Tải các phần phụ thuộc cho dự án xuống

Phần phụ trợ

Chúng ta sẽ dùng Flask để tạo phần phụ trợ. Mở terminal và chạy như sau:

pip install Flask flask-cors requests numpy

Giao diện người dùng

  1. Trong VS Code, hãy nhấp vào File > (Tệp >) Mở thư mục rồi chọn thư mục step0 trong mã nguồn mà bạn đã tải xuống trước đó.
  2. Mở tệp step0/frontend/lib/main.dart. Nếu thấy hộp thoại VS Code nhắc bạn tải các gói bắt buộc xuống cho ứng dụng khởi đầu, hãy nhấp vào Get package (Tải gói).
  3. Nếu bạn không thấy hộp thoại này, hãy mở cửa sổ dòng lệnh rồi chạy lệnh flutter pub get trong thư mục step0/frontend.

7ada07c300f166a6.pngS

5. Bước 0: Chạy ứng dụng khởi đầu

  1. Mở tệp step0/frontend/lib/main.dart trong VS Code, đảm bảo rằng Trình mô phỏng Android hoặc Trình mô phỏng iOS được thiết lập đúng cách và xuất hiện trong thanh trạng thái.

Ví dụ: dưới đây là những gì bạn thấy khi sử dụng Pixel 5 với Trình mô phỏng Android:

9767649231898791.pngS

Sau đây là những gì bạn thấy khi sử dụng iPhone 13 với Trình mô phỏng iOS:

95529e3a682268b2.pngS

  1. Nhấp vào a19a0c68bc4046e6.png Bắt đầu gỡ lỗi.

Chạy và khám phá ứng dụng

Ứng dụng phải chạy trên Trình mô phỏng Android hoặc Trình mô phỏng iOS. Giao diện người dùng khá đơn giản. Có một trường văn bản cho phép người dùng nhập văn bản dưới dạng mã nhận dạng người dùng. Ứng dụng Flutter sẽ gửi yêu cầu truy vấn đến phần phụ trợ. Chương trình này sẽ chạy 2 mô hình đề xuất và trả về một danh sách đề xuất phim được xếp hạng theo thứ hạng. Giao diện người dùng sẽ hiển thị kết quả trong giao diện người dùng sau khi nhận được phản hồi.

d21427db9587560f.png 73e8272a5ce8dfbc.png.

Nếu bây giờ bạn nhấp vào Đề xuất thì sẽ không có gì xảy ra do ứng dụng chưa thể giao tiếp với phần phụ trợ.

6. Bước 1: Tạo mô hình truy xuất và xếp hạng cho công cụ đề xuất

Các công cụ đề xuất trong thực tế thường bao gồm nhiều giai đoạn:

  1. Giai đoạn truy xuất chịu trách nhiệm chọn tập hợp ban đầu gồm hàng trăm đề xuất từ tất cả các đề xuất có thể có. Mục tiêu chính của mô hình này là loại bỏ một cách hiệu quả tất cả các đề xuất mà người dùng không quan tâm. Vì mô hình truy xuất có thể xử lý hàng triệu đề xuất nên phải có hiệu quả tính toán.
  2. Giai đoạn xếp hạng lấy kết quả của mô hình truy xuất và tinh chỉnh chúng để chọn một số đề xuất tốt nhất có thể. Nhiệm vụ của ứng dụng là thu hẹp tập hợp các mục mà người dùng có thể quan tâm thành một danh sách rút gọn gồm hàng trăm ứng viên.
  3. Giai đoạn sau khi xếp hạng giúp đảm bảo tính đa dạng, độ mới và công bằng, đồng thời sắp xếp lại các mục đề xuất thành một nhóm các đề xuất hữu ích theo thứ tự hàng chục đề xuất.

70dfc0d7e989164f.png.

Đối với lớp học lập trình này, bạn sẽ huấn luyện một mô hình truy xuất và một mô hình xếp hạng bằng cách sử dụng tập dữ liệu MovieLens phổ biến. Bạn có thể mở mã huấn luyện dưới đây thông qua Colab và làm theo hướng dẫn:

7. Bước 2: Tạo phần phụ trợ cho công cụ đề xuất

Giờ đây, sau khi đã huấn luyện các mô hình truy xuất và xếp hạng, bạn có thể triển khai các mô hình này và tạo phần phụ trợ.

Bắt đầu phân phát TensorFlow

Vì cần dùng cả mô hình truy xuất và xếp hạng để tạo danh sách phim đề xuất, nên bạn phải triển khai cả hai mô hình này cùng lúc bằng tính năng Phân phát trên TensorFlow.

  • Trong dòng lệnh, hãy chuyển đến thư mục step2/backend trên máy tính rồi bắt đầu phân phát TensorFlow bằng Docker:
docker run -t --rm -p 8501:8501 -p 8500:8500 -v "$(pwd)/:/models/" tensorflow/serving --model_config_file=/models/models.config

Docker tự động tải hình ảnh Phục vụ TensorFlow xuống trước. Quá trình này mất ít phút. Sau đó, việc phân phát TensorFlow sẽ bắt đầu. Nhật ký sẽ có dạng như đoạn mã sau:

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

Tạo điểm cuối mới

Vì việc phân phát TensorFlow không hỗ trợ việc "tạo chuỗi" nhiều mô hình tuần tự, bạn cần phải tạo một dịch vụ mới kết nối các mô hình truy xuất và xếp hạng.

  • Thêm mã này vào hàm get_recommendations() trong tệp 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)

Khởi động dịch vụ Flask

Bây giờ, bạn có thể khởi động dịch vụ Flask.

  • Trong dòng lệnh, hãy chuyển đến thư mục step2/backend/ và chạy lệnh sau:
FLASK_APP=recommender.py FLASK_ENV=development flask run

Bình sẽ thiết lập một điểm cuối mới tại http://localhost:5000/recommend. Bạn sẽ thấy nhật ký như sau:

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

Bạn có thể gửi yêu cầu mẫu đến điểm cuối để đảm bảo điểm cuối hoạt động như mong đợi:

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

Điểm cuối sẽ trả về danh sách phim đề xuất cho người dùng 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)"
  ]
}

Vậy là xong! Bạn đã tạo thành công phần phụ trợ để đề xuất các phim dựa trên mã nhận dạng người dùng.

8. Bước 3: Tạo ứng dụng Flutter dành cho Android và iOS

Phần phụ trợ đã sẵn sàng. Bạn có thể bắt đầu gửi yêu cầu đến trang web đó để truy vấn các đề xuất phim từ ứng dụng Flutter.

Ứng dụng giao diện người dùng khá đơn giản. Lớp này chỉ có một TextField nhận mã nhận dạng người dùng và gửi yêu cầu (trong hàm recommend()) đến phần phụ trợ mà bạn vừa tạo. Sau khi nhận được phản hồi, giao diện người dùng của ứng dụng sẽ hiện các phim đề xuất trong ListView.

  • Thêm mã này vào hàm recommend() trong tệp 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,
  }),
);

Sau khi ứng dụng nhận được phản hồi từ phần phụ trợ, bạn sẽ cập nhật giao diện người dùng để cho thấy danh sách phim đề xuất cho người dùng đã chỉ định.

  • Thêm mã này ngay bên dưới mã ở trên:
if (response.statusCode == 200) {
  return List<String>.from(jsonDecode(response.body)['movies']);
} else {
  throw Exception('Error response');
}

Chạy ứng dụng

  1. Nhấp vào a19a0c68bc4046e6.png Start debugging (Bắt đầu gỡ lỗi) rồi chờ ứng dụng tải.
  2. Nhập mã nhận dạng người dùng (ví dụ: 42), rồi chọn Đề xuất.

badb59d8b96959ae.png a0d2d4020aebfb0a.png

9. Bước 4: Chạy ứng dụng Flutter trên nền tảng dành cho máy tính

Ngoài Android và iOS, Flutter cũng hỗ trợ các nền tảng dành cho máy tính như Linux, Mac và Windows.

Linux

  1. Hãy đảm bảo thiết bị mục tiêu được đặt thành 86cba523de82b4f9.pngS trong thanh trạng thái của VSCode.
  2. Nhấp vào a19a0c68bc4046e6.png Start debugging (Bắt đầu gỡ lỗi) rồi chờ ứng dụng tải.
  3. Nhập mã nhận dạng người dùng (ví dụ: 42), rồi chọn Đề xuất.

2665514231033f1.pngs

Mac

  1. Đối với máy Mac, bạn cần thiết lập các quyền thích hợp vì ứng dụng sẽ gửi yêu cầu HTTP đến phần phụ trợ. Vui lòng tham khảo bài viết Quyền và Hộp cát ứng dụng để biết thêm thông tin chi tiết.

Thêm mã này vào step4/frontend/macOS/Runner/DebugProfile.entitlementsstep4/frontend/macOS/Runner/Release.entitlements tương ứng:

<key>com.apple.security.network.client</key>
<true/>
  1. Hãy đảm bảo thiết bị mục tiêu được đặt thành eb4b0b5563824138.png trong thanh trạng thái của VSCode.
  2. Nhấp vào a19a0c68bc4046e6.png Start debugging (Bắt đầu gỡ lỗi) rồi chờ ứng dụng tải.
  3. Nhập mã nhận dạng người dùng (ví dụ: 42), rồi chọn Đề xuất.

860d523a7ac537e0.pngs

Windows

  1. Hãy đảm bảo thiết bị mục tiêu được đặt thành 9587be1bb375bc0f.png. trong thanh trạng thái của VSCode.
  2. Nhấp vào a19a0c68bc4046e6.png Start debugging (Bắt đầu gỡ lỗi) rồi chờ ứng dụng tải.
  3. Nhập mã nhận dạng người dùng (ví dụ: 42), rồi chọn Đề xuất.

7d77c1e52a5927fc.png.

10. Bước 5: Chạy ứng dụng Flutter trên nền tảng web

Một điều nữa bạn có thể làm là thêm tính năng hỗ trợ web vào ứng dụng Flutter. Theo mặc định, nền tảng web được tự động bật cho các ứng dụng Flutter, vì vậy, bạn chỉ cần khởi chạy nền tảng này.

  1. Hãy đảm bảo thiết bị mục tiêu được đặt thành 71db93efa928d15d.png. trong thanh trạng thái của VSCode.
  2. Nhấp vào a19a0c68bc4046e6.png Bắt đầu gỡ lỗi rồi đợi ứng dụng tải trong trình duyệt Chrome.
  3. Nhập mã nhận dạng người dùng (ví dụ: 42), rồi chọn Đề xuất.

9376e1e432c18bef.png.

11. Xin chúc mừng

Bạn đã tạo một ứng dụng fullstack để đề xuất phim cho người dùng!

Mặc dù ứng dụng này chỉ đề xuất phim, nhưng bạn đã học được quy trình làm việc tổng thể để xây dựng một công cụ đề xuất mạnh mẽ và thành thạo kỹ năng sử dụng các đề xuất trong một ứng dụng Flutter. Bạn có thể dễ dàng áp dụng những điều đã học vào các tình huống khác (ví dụ: Thương mại điện tử, ẩm thực và video ngắn).

Tìm hiểu thêm