Hệ khuyến nghị 6 — Xếp hạng & Đánh giá
Vì sao đánh giá recommender lại khó
Ở bài 3 — Matrix Factorization và các bài trước, ta hay tối ưu RMSE (root mean squared error) hoặc MAE (mean absolute error) trên điểm rating: mô hình dự đoán khách chấm 4.2 sao, thực tế 4.0 sao, sai số 0.2. Nghe hợp lý — nhưng đây là một cái bẫy tư duy lớn.
Thực tế, hệ khuyến nghị không hiển thị một con số điểm cho khách. Nó hiển thị một danh sách xếp hạng (ranking) top-N sản phẩm. Khách chỉ nhìn 3–10 gợi ý đầu tiên. Vì vậy điều quan trọng không phải "dự đoán điểm chính xác đến từng chữ số thập phân", mà là đặt đúng những item liên quan lên đầu danh sách.
Một mô hình có RMSE thấp hơn hoàn toàn có thể tạo ra ranking tệ hơn: nó dự đoán điểm mượt mà, chính xác trung bình, nhưng nhầm thứ tự đúng ở top. Ngược lại, một mô hình RMSE cao hơn lại có thể xếp đúng item số 1 lên đầu. RMSE đo sai lệch tuyệt đối; ranking metric đo thứ tự — và thứ tự mới là thứ khách trải nghiệm.
Do đó, tiêu chuẩn hiện đại là chuyển hẳn từ rating prediction sang top-N ranking / recommendation: cho một khách, sinh ra top-N item và đo chất lượng danh sách đó.
Cốt lõi: đừng hỏi "mô hình dự đoán điểm sai bao nhiêu?" mà hỏi "trong 5 gợi ý đầu, có bao nhiêu cái khách thực sự tương tác, và chúng có nằm ở vị trí cao không?".
Nhóm 1 — Độ đo ranking offline (accuracy)
Đây là các độ đo tính trên dữ liệu lịch sử, so top-N gợi ý với tập item mà khách thực sự tương tác (relevant items — item liên quan). Ký hiệu @k nghĩa là "chỉ xét k vị trí đầu".
Precision@k và Recall@k
- Precision@k: trong k gợi ý đầu, tỷ lệ item thực sự liên quan. $$\text{Precision@}k = \frac{|\text{item liên quan trong top-}k|}{k}$$
- Recall@k: trong toàn bộ item liên quan của khách, bao nhiêu phần được bắt vào top-k. $$\text{Recall@}k = \frac{|\text{item liên quan trong top-}k|}{|\text{tổng item liên quan}|}$$
Precision hỏi "gợi ý có đúng không", recall hỏi "có bỏ sót không". Cả hai đều không quan tâm thứ tự bên trong top-k — đây là điểm yếu khiến ta cần các độ đo tinh vi hơn.
MAP — Mean Average Precision
MAP thưởng cho việc đặt item liên quan lên sớm trong danh sách. Với một khách, Average Precision (AP) là trung bình của precision tại mỗi vị trí có item liên quan; MAP là trung bình AP trên toàn bộ khách. Item liên quan càng ở vị trí cao, AP càng lớn. MAP nhạy với thứ tự nhưng chỉ dùng nhãn nhị phân (liên quan / không).
NDCG — Normalized Discounted Cumulative Gain (phổ biến nhất)
NDCG là độ đo được dùng rộng rãi nhất cho ranking. Ý tưởng ba tầng:
- Gain: mỗi item có mức liên quan $rel_i$ (nhị phân 0/1, hoặc nhiều mức: mua = 3, thêm giỏ = 2, click = 1).
- Discounted: vị trí càng thấp thì đóng góp càng bị chiết khấu bằng $\log_2(i+1)$ — đặt item hay ở vị trí 1 quý hơn ở vị trí 10.
- Normalized: chia cho DCG của ranking lý tưởng (IDCG) để đưa về khoảng $[0, 1]$, so sánh được giữa các khách.
$$DCG@k = \sum_{i=1}^{k} \frac{rel_i}{\log_2(i+1)}, \qquad NDCG@k = \frac{DCG@k}{IDCG@k}$$
NDCG vừa nhạy thứ tự, vừa hỗ trợ nhiều mức liên quan — nên là lựa chọn mặc định khi báo cáo chất lượng ranking.
MRR — Mean Reciprocal Rank
MRR chỉ quan tâm vị trí của item liên quan ĐẦU TIÊN: nếu nó ở vị trí $r$, điểm là $1/r$. MRR trung bình trên toàn bộ khách. Rất hợp khi bài toán chỉ cần "một câu trả lời đúng ở gần đầu" — ví dụ gợi ý một hành động tiếp theo (next best action).
Hit Rate và Coverage cơ bản
- Hit Rate@k: tỷ lệ khách có ít nhất 1 item liên quan trong top-k. Đơn giản, dễ giải thích cho nghiệp vụ.
- Coverage (cơ bản): tỷ lệ catalog xuất hiện trong các gợi ý — sẽ nói kỹ ở nhóm 2.
| Độ đo | Nhạy thứ tự? | Nhiều mức liên quan? | Khi nào dùng |
|---|---|---|---|
| Precision@k | Không | Không | Đo "đúng trong top-k" |
| Recall@k | Không | Không | Đo "không bỏ sót" |
| MAP | Có | Không | Ranking, nhãn nhị phân |
| NDCG@k | Có | Có | Mặc định, báo cáo chính |
| MRR | Có (item đầu) | Không | Cần 1 đáp án đúng gần đầu |
| Hit Rate@k | Không | Không | Báo cáo nghiệp vụ dễ hiểu |
Nhóm 2 — Beyond accuracy (rất quan trọng, hay bị bỏ quên)
Một hệ chỉ tối ưu accuracy sẽ nhanh chóng trở nên nhàm chán và thiên lệch: nó gợi ý mãi vài sản phẩm phổ biến vì "an toàn về precision". Trải nghiệm thật đòi hỏi nhiều hơn. Các độ đo beyond accuracy đo phần này:
- Coverage (catalog coverage): tỷ lệ sản phẩm trong toàn catalog từng được gợi ý cho ai đó. Coverage thấp nghĩa là hệ chỉ đẩy một góc nhỏ danh mục, bỏ quên đuôi dài (long tail).
- Diversity (đa dạng): mức khác biệt giữa các item TRONG một danh sách top-N (thường đo bằng 1 − độ tương đồng trung bình từng cặp). Danh sách toàn "tài khoản tiết kiệm" 5 loại na ná nhau có diversity thấp, dễ gây nhàm.
- Novelty (mới lạ): mức độ item ít phổ biến / khách chưa từng thấy. Novelty cao giúp khách khám phá cái mới thay vì lặp lại thứ đã biết.
- Serendipity (bất ngờ thú vị): gợi ý vừa bất ngờ vừa hữu ích — thứ khách không tự nghĩ tới nhưng lại thích. Khó đo nhất, thường xấp xỉ bằng "liên quan nhưng khác kỳ vọng".
- Popularity bias: xu hướng chỉ gợi ý sản phẩm phổ biến. Cần theo dõi và giảm thiểu, vì nó bóp nghẹt long tail và tạo vòng lặp "giàu càng giàu".
- Fairness (công bằng): gợi ý có thiên lệch theo nhóm khách (giới, vùng, thu nhập) hoặc theo nhà cung cấp sản phẩm không? Đặc biệt nhạy cảm trong ngân hàng.
Nguyên tắc thực chiến: accuracy và diversity thường đánh đổi nhau. Tối ưu mù NDCG dễ đẩy popularity bias lên. Nên đặt accuracy làm mục tiêu chính nhưng ràng buộc coverage/diversity ở ngưỡng tối thiểu — đây là bài toán cân bằng, không phải tối ưu một chiều.
Nhóm 3 — Protocol đánh giá offline
Chọn đúng độ đo chưa đủ; cách chia dữ liệu quyết định kết quả có đáng tin không.
Chia train/test theo THỜI GIAN, không random
Đây là sai lầm phổ biến nhất. Hành vi khách có trục thời gian, giống chuỗi thời gian (time series). Nếu chia ngẫu nhiên, bạn có thể train trên tương tác tháng 6 rồi test trên tháng 3 — rò rỉ tương lai (data leakage): mô hình "biết trước" điều chưa xảy ra, cho metric offline cao ảo. Đúng chuẩn: chọn một mốc thời gian, train trên trước mốc, test trên sau mốc (temporal split).
Leave-one-out
Với mỗi khách, giữ lại tương tác cuối cùng (theo thời gian) làm test, phần còn lại làm train. Mô hình phải xếp item bị giấu này lên cao trong top-N. Đơn giản, phổ biến, nhưng lưu ý vẫn phải tôn trọng thứ tự thời gian (giấu cái mới nhất, không giấu ngẫu nhiên).
Negative sampling khi đánh giá
Catalog có thể hàng nghìn sản phẩm; xếp hạng toàn bộ với mọi khách rất tốn. Kỹ thuật phổ biến: với mỗi item dương (khách đã tương tác), lấy mẫu một số item âm (chưa tương tác), rồi đo mô hình có xếp item dương cao hơn nhóm âm không (ví dụ 1 dương + 99 âm, tính NDCG/MRR trên 100 item). Cảnh báo: cách lấy negative ảnh hưởng lớn đến con số — cần cố định và minh bạch để so sánh công bằng giữa các mô hình.
Nhóm 4 — Offline vs Online: metric offline không luôn khớp online
Đây là bài học đắt giá nhất trong vận hành recommender: NDCG offline cao KHÔNG bảo đảm khách click/mua nhiều hơn. Lý do:
- Offline chỉ đo trên hành vi đã xảy ra dưới hệ CŨ; nó không biết khách phản ứng thế nào với gợi ý MỚI mà họ chưa từng thấy.
- Có feedback loop & position bias: khách click item ở vị trí 1 nhiều hơn không phải vì nó hay hơn, mà vì nó ở trên. Log lịch sử vì thế thiên lệch, và mô hình học lại chính thiên lệch đó.
Nguyên tắc vàng: dùng offline để SÀNG LỌC sơ bộ, dùng online A/B để RA QUYẾT ĐỊNH cuối.
| Giai đoạn | Mục tiêu | Độ đo | Rủi ro |
|---|---|---|---|
| Offline | Loại mô hình tệ nhanh, rẻ | NDCG, MAP, Recall@k, coverage | Rò rỉ, position bias, không khớp online |
| Online (A/B) | Quyết định triển khai | CTR, conversion, doanh thu, engagement | Chậm, tốn traffic, cần đủ mẫu |
Metric online
- CTR (click-through rate): tỷ lệ click trên số lần hiển thị — tín hiệu tương tác sớm.
- Conversion: tỷ lệ dẫn tới hành động mục tiêu (mở sản phẩm, nộp hồ sơ).
- Doanh thu / giá trị vòng đời: thước đo kinh doanh cuối cùng.
- Engagement: thời lượng, số phiên, quay lại.
- Guardrail metric (chỉ số bảo vệ): các chỉ số KHÔNG được phép xấu đi (tỷ lệ khiếu nại, hủy dịch vụ, độ trễ, phàn nàn spam). Một mô hình tăng CTR nhưng phá guardrail thì vẫn bị loại.
Việc thiết kế và đọc A/B test đúng cách (kích thước mẫu, ý nghĩa thống kê, tránh peeking) là cả một chủ đề riêng — xem Thống kê 7 — A/B testing. Đọc thêm về thí nghiệm & tăng trưởng để nối metric với quyết định kinh doanh.
Ví dụ tính NDCG (minh hoạ)
Giả sử hệ gợi ý 5 sản phẩm cho một khách; nhãn liên quan (mua=3, click=1, không tương tác=0) theo vị trí là [3, 0, 1, 0, 2].
$$DCG@5 = \frac{3}{\log_2 2} + \frac{0}{\log_2 3} + \frac{1}{\log_2 4} + \frac{0}{\log_2 5} + \frac{2}{\log_2 6}$$ $$= 3.000 + 0 + 0.500 + 0 + 0.774 = 4.274$$
Ranking lý tưởng sắp giảm dần theo liên quan: [3, 2, 1, 0, 0]:
$$IDCG@5 = \frac{3}{\log_2 2} + \frac{2}{\log_2 3} + \frac{1}{\log_2 4} + 0 + 0 = 3.000 + 1.262 + 0.500 = 4.762$$
$$NDCG@5 = \frac{4.274}{4.762} \approx 0.898$$
Đọc kết quả: 0.898 nghĩa là ranking khá tốt nhưng chưa tối ưu — item "mua" (rel=2) bị đặt ở vị trí 5 thay vì gần đầu, kéo điểm xuống. Nếu ta đảo nó lên vị trí 2, NDCG sẽ tiến gần 1.0. Đây chính là cách NDCG "thưởng" cho việc đặt item liên quan lên cao.
Đoạn minh hoạ tính toán (KHÔNG phải SQL sandbox, chỉ để minh hoạ logic):
import numpy as np
def dcg(rels):
rels = np.asarray(rels, dtype=float)
discounts = np.log2(np.arange(2, len(rels) + 2))
return np.sum(rels / discounts)
def ndcg_at_k(rels, k):
ideal = sorted(rels, reverse=True)
return dcg(rels[:k]) / dcg(ideal[:k])
print(round(ndcg_at_k([3, 0, 1, 0, 2], 5), 3)) # -> 0.898 (minh hoạ)
Use case thực tế
Bối cảnh NCB: đội dữ liệu triển khai module "Gợi ý sản phẩm tiếp theo" trên app ngân hàng số cho ~800.000 khách hoạt động, catalog 42 sản phẩm (tiết kiệm, thẻ tín dụng, vay tiêu dùng, bảo hiểm, đầu tư...). Cần đánh giá 3 mô hình ứng viên: popularity baseline, matrix factorization, two-tower deep model.
Bước 1 — Offline (2 tuần). Chia dữ liệu 12 tháng theo temporal split: 10 tháng train, 2 tháng cuối test. Leave-one-out lấy tương tác sản phẩm cuối cùng của mỗi khách làm nhãn dương, negative sampling 1 dương + 99 âm. Kết quả:
| Mô hình | NDCG@10 | Recall@10 | Coverage | Diversity |
|---|---|---|---|---|
| Popularity | 0.31 | 0.28 | 12% | 0.15 |
| Matrix Factorization | 0.44 | 0.41 | 48% | 0.52 |
| Two-tower | 0.49 | 0.45 | 61% | 0.58 |
Popularity có NDCG thấp và coverage chỉ 12% (chỉ đẩy vài sản phẩm hot, popularity bias nặng) — loại. Two-tower thắng offline nhưng chỉ hơn MF ~10%, nên chưa vội kết luận.
Bước 2 — Online A/B (4 tuần). Chia 3 nhánh: control (rule cũ), MF, two-tower, mỗi nhánh ~200.000 khách. Guardrail: tỷ lệ opt-out nhận gợi ý không tăng quá 0.5 điểm phần trăm. Kết quả: two-tower nâng CTR gợi ý từ 4.1% lên 5.3% (+29%), conversion mở sản phẩm +18%, doanh thu phí sản phẩm/khách +11%, guardrail giữ nguyên. MF chỉ +12% CTR.
Quyết định. Two-tower thắng cả offline lẫn online, chênh lệch có ý nghĩa thống kê (p < 0.01, xem stat-07) → rollout toàn bộ, giữ 5% traffic làm holdout để theo dõi lâu dài. Điểm mấu chốt: đội KHÔNG dừng ở NDCG offline mà chốt bằng tác động kinh doanh online, đồng thời theo dõi diversity để gợi ý không nhàm và không thiên lệch nhóm khách.
Chi tiết phần phục vụ mô hình sau khi chọn được ứng viên nằm ở bài 7 — Production Serving, và cách áp dụng cho bài toán next-best-action ngân hàng ở bài 8.
Ghi nhớ
- Gợi ý là bài toán xếp hạng top-N, không phải dự đoán điểm — bỏ RMSE/MAE, chuyển sang ranking metric.
- NDCG là mặc định: nhạy thứ tự + hỗ trợ nhiều mức liên quan. MAP nhạy thứ tự (nhãn nhị phân); MRR khi cần một đáp án đúng gần đầu; precision@k/recall@k đơn giản nhưng bỏ qua thứ tự.
- Beyond accuracy rất quan trọng: coverage, diversity, novelty, serendipity, popularity bias, fairness. Accuracy và diversity thường đánh đổi — ràng buộc ngưỡng tối thiểu.
- Protocol: chia train/test theo thời gian (không random, tránh rò rỉ tương lai), leave-one-out, negative sampling minh bạch và cố định.
- Offline chỉ để sàng lọc; online A/B mới ra quyết định cuối. NDCG offline cao không bảo đảm CTR/doanh thu tăng.
- Coi chừng feedback loop & position bias: log lịch sử thiên lệch vì khách click cái ở trên; đừng để mô hình học lại chính thiên lệch đó.
- Metric online: CTR, conversion, doanh thu, engagement, và guardrail không được phép xấu đi.
- Trong ngân hàng: đánh giá gợi ý sản phẩm phải cân cả đúng, đa dạng và phù hợp, và luôn chốt bằng tác động kinh doanh đo qua A/B.
Bài viết liên quan
Phân biệt AI/ML/DL, các kiểu học máy, quy trình ML end-to-end và thuật ngữ nền tảng.
Chất lượng dữ liệu, xử lý thiếu/ngoại lai, mã hoá, chuẩn hoá, tạo đặc trưng và tránh data leakage.
Mô hình ngôn ngữ lớn hoạt động ra sao, token, context window, tham số sinh, và kỹ thuật viết prompt.
Retrieval-Augmented Generation, vector database, tool calling, agent và MCP để xây ứng dụng LLM thực tế.