App: recommendation engine end-to-end
Xây engine gợi ý hoàn chỉnh: content-based, collaborative filtering user và item, matrix factorization, xử lý cold start, đo precision và đa dạng.
Chuyên giaThuật toán ~120 phút
Ôn lại trước khi học
Giới thiệu
Bài này xây máy gợi ý phim và sản phẩm. Người cũ gợi theo gu, người mới gợi theo top phổ biến.
Kiến thức cần nhớ
Content-based theo metadata
- Vector hóa thể loại và mô tả bằng TF-IDF.
- Profile user là trung bình vector các item đã thích.
- Gợi ý bằng cosine giữa profile và item chưa xem.
- Ví dụ đời thường: thích phim hành động thì gợi thêm phim hành động.
Collaborative filtering theo đám đông
- User-based: người giống bạn thích gì thì gợi nấy.
- Item-based: ai thích món này cũng thích món kia.
- Cần đủ rating chung mới tin, ít quá thì rất nhiễu.
- Ví dụ đời thường: bạn cùng gu khen hay thì bạn cũng thấy hay.
Matrix factorization và cold start
- Phân rã ma trận rating thành 2 ma trận latent user và item.
- Dự đoán bằng tích vô hướng 2 vector latent.
- User mới thì gợi phổ biến cộng theo thể loại đăng ký.
- Item mới chỉ có metadata thì đi nhánh content-based.
| Mô hình | Cần gì | Mạnh khi nào |
|---|---|---|
| Content-based | Metadata item | Item mới, user ít lịch sử |
| CF | Rating chung | User cũ đông |
| Factorization | Nhiều rating | Gu ẩn phức tạp |
Ví dụ
- Input: user mê hành động, hỏi top-10. Output: trên 60% phim hành động, không chứa phim đã xem.
- Giải thích: cosine đẩy phim cùng thể loại lên đầu, bộ lọc bỏ phim đã xem.
- Input: user mới tinh vừa đăng ký. Output: danh sách phổ biến theo thể loại đã chọn.
- Giải thích: chưa có lịch sử nên đi nhánh cold start.
💻 Bài tập
Ngôn ngữ: Python 3. Dùng code ngày 58, 59, 91. Dữ liệu MovieLens 1M (hoặc 100K). Nộp vào day-131-recsys/.
Bài 1: Pipeline dữ liệu
- Nạp rating, phim, người dùng. Kiểm tra dữ liệu: rating ngoài 1-5, id trùng, phim thiếu thể loại.
- Chia theo thời gian: mỗi user, 80% rating cũ là train, 20% mới là test.
- Lưu dữ liệu đã xử lý ra Parquet. Pipeline chạy lại cho cùng kết quả.
Bài 2: Ba mô hình và bộ điều phối
| Mô hình | Dùng khi |
|---|---|
PopularityModel | User mới, 0 rating |
ContentModel (ngày 58) | User có 1-9 rating, hoặc phim mới chưa ai chấm |
MFModel (ngày 91) | User có từ 10 rating |
class Recommender:
def recommend(self, user_id: int, n: int = 10, exclude_seen: bool = True) -> list[tuple[int, float, str]]:
"""Trả (movie_id, score, lý_do). Lý do ví dụ: "Vì bạn thích Toy Story" hoặc "Phổ biến tuần này"."""
Ràng buộc: không gợi phim user đã xem. Luôn trả đủ n phim (bù bằng phổ biến nếu thiếu).
Bài 3: Đánh giá và API (nâng cao)
- Tính cho từng nhóm user (0, 1-9, 10+ rating): precision@10, recall@10, NDCG@10, coverage (tỉ lệ phim từng được gợi ý), độ đa dạng thể loại.
- So bộ điều phối với từng mô hình đơn lẻ.
- Viết API
GET /recommend?user_id=..&n=..bằng FastAPI. Độ trễ p99 dưới 50 ms (tính trước vector, dùng numpy cho tích vô hướng). README.md: sơ đồ pipeline, cách chạy, bảng kết quả.
✅ Tiêu chí hoàn thành
- Pipeline tất định, chạy lại cho cùng file Parquet.
- User mới vẫn nhận đủ 10 gợi ý có lý do.
- Bảng metric theo nhóm user có số thật.
- API chạy, có số đo p99.
❓ Câu hỏi ôn tập
- Content-based tính điểm gợi ý thế nào?
- CF user-based khác item-based ở điểm gì?
- Factorization học gu ẩn bằng cách nào?
- Cold start xử lý user và item mới ra sao?
🌕 Bạn đã hoàn thành ngày 131. Làm hết bài tập phía trên rồi sang ngày tiếp theo.