Matrix factorization, cold start và mô hình lai

Nhân tử ẩn, Netflix Prize, cold start, sparsity, ảnh hưởng xã hội hai mặt và mô hình lai tiến hóa.
KhóThuật toán ~60 phút

Giới thiệu

Bài này học gợi ý bằng nhân tử ẩn và mô hình lai. Dùng để gợi ý phim, món ăn khi dữ liệu thưa.

Kiến thức cần nhớ

Phân rã ma trận

  • Định nghĩa: nén mỗi người và mỗi món thành vector ngắn.
  • Điểm dự đoán = độ khớp hai vector + thiên lệch.
  • Ví dụ đời thường: như đoán khẩu vị từ vài món tủ.
  • Học bằng cách chỉnh vector cho khớp điểm đã biết.
  • Chịu thưa tốt hơn tìm láng giềng trực tiếp.

Cold start và dữ liệu thưa

  • Cold start: người mới hoặc món mới chưa có dữ liệu.
  • Sửa bằng gợi phổ biến và hỏi sở thích lúc đầu.
  • Dữ liệu thưa: mỗi người chỉ chấm vài món.
  • Sửa bằng tín hiệu ngầm như lượt xem, lượt click.
Vấn đềDấu hiệuCách sửa
Cold userNgười mới, chưa chấm gìHỏi sở thích, gợi hot
Cold itemMón mới, chưa ai chấmDùng mô tả nội dung
ThưaMa trận rỗng > 99%Phân rã, tín hiệu ngầm

Mô hình lai

  • Định nghĩa: kết hợp nhiều mô hình gợi ý với nhau.
  • Lai song song: trộn điểm các mô hình lại.
  • Lai nối tiếp: mô hình trước lọc, mô hình sau xếp hạng.
  • Ví dụ đời thường: như hỏi nhiều bạn rồi chốt lại.

Giới hạn khác của hệ gợi ý

  • Cần metadata tốt: thiếu mô tả món thì content-based không có gì để so.
  • Ảnh hưởng xã hội là con dao hai lưỡi: gợi theo đám đông làm món nổi càng nổi, món ngách khó được thấy.
  • Gu người dùng trôi theo thời gian, cần huấn luyện lại định kỳ.

Ví dụ

  • Input: người mới chưa chấm gì -> Output: gợi top phim hot.
  • Giải thích: collaborative câm nên dùng phổ biến và nội dung.
# Dự đoán điểm bằng vector ẩn
pred = sum(u * v for u, v in zip(user, item)) + bias
print(pred)  # điểm gợi ý

💻 Bài tập

Ngôn ngữ: Python 3 với NumPy. Dữ liệu MovieLens 100K. Dùng lại baseline ngày 59. Nộp vào day-091/.

Bài 1: Matrix factorization bằng SGD

class MF:
    def __init__(self, k=20, lr=0.01, reg=0.05, epochs=30, seed=0): ...
    def fit(self, ratings: list[tuple[int, int, float]], val=None): ...
    def predict(self, u, i) -> float: ...     # mu + b_u + b_i + P[u] . Q[i], kẹp vào [1, 5]

Mỗi rating (u, i, r): e = r - predict, cập nhật b_u, b_i, P[u], Q[i] với regularization. Xáo trộn thứ tự rating mỗi epoch.

Sau 30 epoch: RMSE train giảm đều mỗi epoch
RMSE test < item-based CF ngày 59
k = 0 (chỉ bias) -> vẫn thắng global mean

Vẽ RMSE train và validation theo epoch.

Bài 2: Cold start và sparsity

  1. Tách 50 user có ít nhất 50 rating. Giả làm user mới: chỉ giữ 0, 1, 3, 5, 10 rating của họ trong train. Đo RMSE trên phần còn lại cho từng mức.
  2. Chiến lược cho user 0 rating: gợi top phim theo b_i (phổ biến và được chấm cao). Đo precision@10.
  3. Chiến lược "hỏi sở thích": user chọn 3 thể loại, gợi top phim các thể loại đó. So precision@10.

Bài 3: Mô hình lai (nâng cao)

  1. Lai song song: score = a * MF + (1 - a) * content (ngày 58). Quét a từ 0 tới 1, chọn theo precision@10 trên validation.
  2. Lai nối tiếp: content-based lọc 200 ứng viên, MF xếp hạng lấy top 10.
  3. Lai chuyển đổi: user có dưới 5 rating dùng content, còn lại dùng MF.
chiến_lược        RMSE    precision@10    recall@10
MF                ...
content           ...
lai song song     ...
lai nối tiếp      ...
lai chuyển đổi    ...

✅ Tiêu chí hoàn thành

  • MF thắng baseline và CF, có hình RMSE theo epoch.
  • Bảng RMSE theo số rating của user mới.
  • Bảng 5 chiến lược có số thật.
  • Giải thích được vì sao MF chịu thưa tốt hơn tìm láng giềng.

❓ Câu hỏi ôn tập

  • Phân rã ma trận là gì?
  • Cold start user khác cold item thế nào?
  • Vì sao ma trận điểm luôn thưa?
  • Lai song song khác lai nối tiếp ra sao?

🌕 Bạn đã hoàn thành ngày 91. Làm hết bài tập phía trên rồi sang ngày tiếp theo.

Bớt paste mù, hiểu sâu từng dòng mình viết.

180 Days Challenge. 180 ngày cai nghiện vibe code.