Bài 4: TikTok, YouTube, Netflix biết bạn thích gì? Thuật toán gợi ý hoạt động ra sao

Bạn vừa xem vài video lập trình, và TikTok, YouTube lập tức gợi ý thêm hàng loạt video tương tự. Theo chính các kỹ sư Netflix, khoảng 80% số giờ xem trên nền tảng này chịu ảnh hưởng từ hệ thống gợi ý. Hãy cùng xem các "cỗ máy đọc vị" ấy hoạt động thế nào – bắt đầu từ một công thức hình học lớp 10.

Bài thứ tư của chuyên mục "Thuật toán trong đời sống". Chúng ta sẽ tự viết một hệ thống gợi ý mini bằng lọc cộng tác (collaborative filtering), rồi tìm hiểu cách YouTube và TikTok làm ở quy mô hàng tỷ người dùng.
1. Ý tưởng: "người giống bạn thích gì?"
Hệ thống gợi ý cổ điển nhất là lọc cộng tác: nếu An và Bình thường thích cùng những video, thì video An thích mà Bình chưa xem có lẽ cũng hợp với Bình. Để làm được việc đó, ta cần đo hai người giống nhau đến mức nào.
Biểu diễn sở thích bằng vector
Mỗi người dùng là một hàng trong bảng đánh giá, mỗi cột là một video:
| Dijkstra | Quy hoạch động | Đồ thị | Nấu ăn | Bóng đá | |
|---|---|---|---|---|---|
| An | 5 | 4 | 5 | – | 1 |
| Bình | 4 | 5 | 4 | 1 | – |
| Chi | 1 | – | 1 | 5 | 4 |
| Dũng | 5 | ? | ? | ? | 1 |
Mỗi hàng là một vector. Hai người có sở thích giống nhau thì hai vector "cùng hướng". Ta đo bằng độ tương đồng cosine – chính là cos của góc giữa hai vector mà bạn học trong hình học:
Điểm dự đoán của Dũng cho một video = trung bình có trọng số các điểm của người khác, với trọng số là độ tương đồng.
Code: hệ thống gợi ý mini
Code C++ và Python
#include <bits/stdc++.h>
using namespace std;
double cosine(const vector<double>& a, const vector<double>& b){
double dot = 0, na = 0, nb = 0;
for(size_t i = 0; i < a.size(); i++){ dot += a[i]*b[i]; na += a[i]*a[i]; nb += b[i]*b[i]; }
return (na == 0 || nb == 0) ? 0 : dot / (sqrt(na) * sqrt(nb));
}
int main(){
vector<string> videos = {"Dijkstra", "Quy hoach dong", "Do thi", "Nau an", "Bong da"};
vector<vector<double>> R = {{5,4,5,0,1}, {4,5,4,1,0}, {1,0,1,5,4}, {5,0,0,0,1}};
int me = 3; // người dùng "Dũng"
for(size_t j = 0; j < videos.size(); j++){
if(R[me][j] != 0) continue;
double num = 0, den = 0;
for(size_t v = 0; v < R.size(); v++){
if((int)v == me || R[v][j] == 0) continue;
double s = cosine(R[me], R[v]);
num += s * R[v][j]; den += s;
}
if(den > 0) printf("%s: %.2f\n", videos[j].c_str(), num / den);
}
}import math
# Hàng = người dùng, cột = video; số = điểm đánh giá (0 = chưa xem)
videos = ["Dijkstra", "Quy hoạch động", "Đồ thị", "Nấu ăn", "Bóng đá"]
R = {
"An": [5, 4, 5, 0, 1],
"Bình": [4, 5, 4, 1, 0],
"Chi": [1, 0, 1, 5, 4],
"Dũng": [5, 0, 0, 0, 1], # Dũng mới xem 2 video
}
def cosine(a, b):
dot = sum(x * y for x, y in zip(a, b))
na = math.sqrt(sum(x * x for x in a))
nb = math.sqrt(sum(y * y for y in b))
return dot / (na * nb) if na and nb else 0
def recommend(user):
sims = {v: cosine(R[user], R[v]) for v in R if v != user}
scores = {}
for j, name in enumerate(videos):
if R[user][j] == 0: # chỉ gợi ý video chưa xem
num = sum(sims[v] * R[v][j] for v in sims)
den = sum(sims[v] for v in sims if R[v][j] > 0)
if den:
scores[name] = num / den
return sorted(scores.items(), key=lambda x: -x[1])
for name, sc in recommend("Dũng"):
print(f"{name}: {sc:.2f}")Kết quả: Dũng (người thích video Dijkstra) được gợi ý Quy hoạch động (4,45 điểm) và Đồ thị (3,87) lên đầu, còn Nấu ăn (2,37) xếp cuối – dù chẳng ai "dạy" máy rằng Dijkstra liên quan đến đồ thị. Máy tự suy ra từ hành vi của An và Bình.
2. Netflix Prize: 1 triệu USD cho 10% chính xác hơn
Ngày 2/10/2006, Netflix mở cuộc thi Netflix Prize: ai cải thiện độ chính xác dự đoán đánh giá phim của họ thêm 10% sẽ nhận 1 triệu USD. Dữ liệu gồm hơn 100 triệu lượt đánh giá từ khoảng 500.000 khách hàng cho hơn 17.000 bộ phim.
- Sau gần 3 năm, đội BellKor's Pragmatic Chaos đạt mức cải thiện 10,06%.
- Đội The Ensemble đạt kết quả tương đương, nhưng BellKor nộp bài sớm hơn 20 phút – và thắng giải (công bố tháng 9/2009).
Kỹ thuật chủ chốt của đội thắng là phân rã ma trận (matrix factorization). Trong bài báo năm 2009 trên tạp chí IEEE Computer, Yehuda Koren, Robert Bell và Chris Volinsky giải thích: mỗi người dùng và mỗi bộ phim được biểu diễn bằng một vector "đặc trưng ẩn" (ví dụ: mức độ hành động, mức độ hài hước…), và điểm dự đoán chính là tích vô hướng của hai vector đó. Các vector được học bằng gradient descent hoặc bình phương tối thiểu luân phiên (ALS).
3. YouTube: lọc qua hai tầng
Với hàng triệu video, không thể tính điểm cho tất cả mỗi khi bạn mở app. Bài báo của Google tại hội nghị RecSys 2016 mô tả YouTube dùng hai giai đoạn:
- Sinh ứng viên (candidate generation): từ hàng triệu video, lọc nhanh ra khoảng vài trăm video có khả năng phù hợp.
- Xếp hạng (ranking): dùng mô hình phức tạp hơn để chấm điểm từng ứng viên – theo bài báo, mục tiêu là dự đoán thời gian xem dự kiến, chứ không chỉ khả năng bấm vào.
Đây là tư duy "lọc thô rồi lọc tinh" rất quen thuộc trong tin học: giống như chặt nhị phân thu hẹp khoảng tìm kiếm trước khi xét kỹ, hay cắt tỉa nhánh trong quay lui.
4. TikTok: cập nhật theo từng phút
Năm 2022, ByteDance (công ty mẹ của TikTok) công bố bài báo về hệ thống gợi ý thời gian thực Monolith. Một số điểm thú vị về thuật toán:
- Bảng băm không va chạm: mỗi người dùng, mỗi video có một vector đặc trưng (embedding). Thay vì băm nhiều ID vào cùng một ô (gây "trộn lẫn thông tin" giữa các ID), Monolith dùng bảng băm dựa trên Cuckoo hashing để mỗi ID có chỗ riêng.
- Tiết kiệm bộ nhớ: ID chỉ được thêm vào bảng khi xuất hiện đủ số lần, và các embedding lâu không dùng sẽ hết hạn.
- Học trực tuyến: phản hồi của người dùng được đưa vào huấn luyện liên tục; theo bài báo, các tham số được đồng bộ sang hệ thống phục vụ vài phút một lần. Đó là lý do bạn xem vài video là "gu" của app thay đổi rất nhanh.
5. Mặt trái: "bong bóng lọc"
Hệ thống gợi ý tối ưu cho việc bạn xem lâu hơn, nên dễ chỉ đưa cho bạn những thứ giống hệt điều bạn đã thích. Hiểu cách thuật toán hoạt động giúp bạn chủ động hơn: tìm kiếm có mục đích, đa dạng hóa nội dung, và nhớ rằng "được gợi ý nhiều" không có nghĩa là "đúng" hay "quan trọng".
6. Bạn học được gì từ đây?
- Vector và tích vô hướng trong hình học là nền tảng của hệ thống gợi ý và cả AI hiện đại (embedding).
- Bảng băm – cấu trúc dữ liệu bạn dùng hằng ngày qua
unordered_map– xuất hiện ngay trong hệ thống của TikTok. - Tư duy lọc thô – lọc tinh giúp xử lý dữ liệu khổng lồ trong thời gian thực.
Thử thách: thêm một người dùng "Em" thích cả Nấu ăn và Bóng đá vào bảng, rồi chạy code để xem Dũng được gợi ý gì. Hãy chia sẻ kết quả trong phần bình luận!

Nguồn tham khảo
- Gomez-Uribe & Hunt (2015) – The Netflix Recommender System (ACM TMIS)
- Wikipedia – Netflix Prize
- Koren, Bell, Volinsky (2009) – Matrix Factorization Techniques for Recommender Systems
- Covington, Adams, Sargin (2016) – Deep Neural Networks for YouTube Recommendations
- ByteDance (2022) – Monolith: Real Time Recommendation System With Collisionless Embedding Table
- Không biết học gì trước, học gì sau, học lan man nên kiến thức bị hổng.
- Bí bài không ai gỡ, ngồi cả buổi vẫn không ra rồi bỏ cuộc.
- Code chạy được nhưng không đủ điểm, không biết sai ở đâu, chậm ở đâu.
- Không có đề thi thử và người chấm, nên không biết mình đang ở mức nào.
- Dễ nản giữa chừng khi không có ai theo sát.
- Lộ trình 111 buổi video sắp sẵn từ dòng code đầu tiên đến đề HSG thật của các tỉnh.
- Thầy trực tiếp gỡ bí, chữa bài cho từng em qua nhóm Zalo riêng.
- Hệ thống chấm bài tự động 24/7 và thi thử HSG hằng tuần để biết chính xác mình đang ở đâu.
- Đóng học phí một lần, thầy kèm lâu dài: từ thi chuyên Tin đến HSG quốc gia và cả khi lên đại học.
Nhận xét
Đăng nhận xét