Đọc câu "Con mèo ngồi trên tấm thảm vì nó mệt", ta biết "nó" là con mèo. Attention cho mô hình khả năng đó: mỗi token nhìn mọi token khác và tự quyết định nên chú ý vào đâu.
Mỗi token tạo ra ba vector (bằng phép nhân ma trận học được):
- Query (Q) — "mình đang tìm thông tin gì?"
- Key (K) — "mình chứa thông tin gì?"
- Value (V) — "thông tin mình đưa ra"
Độ hợp nhau giữa token i và j là tích vô hướng qᵢ·kⱼ. Softmax biến các điểm thành trọng số, đầu ra là trung bình có trọng số của V:
Attention(Q, K, V) = softmax(Q Kᵀ / √d) V
def attention(Q, K, V):
d = Q.shape[-1]
scores = Q @ K.T / np.sqrt(d) # (n, m): token i chấm điểm token j
weights = softmax(scores) # mỗi hàng tổng = 1
return weights @ V # (n, d_v)Vì sao chia √d? Tích vô hướng của hai vector d chiều có độ lớn tăng theo √d. Điểm quá lớn làm softmax gần như one-hot → gradient gần 0, mô hình khó học. Chia √d giữ phương sai của điểm ổn định.
Mặt nạ nhân quả (causal mask): mô hình sinh văn bản như GPT dự đoán token tiếp theo, nên token ở vị trí t không được nhìn tương lai. Ta đặt điểm của mọi cặp (i, j > i) thành −∞ trước softmax → trọng số tương ứng bằng 0.
Self-attention: Q, K, V đều sinh từ cùng một chuỗi X (Q = XWq, K = XWk, V = XWv). Cross-attention (trong dịch máy): Q từ câu đích, K và V từ câu nguồn.
?Trong causal self-attention với 4 token, token thứ 2 (đếm từ 1) được chú ý tới bao nhiêu token?
Luyện tập ngay
Viết code và chấm tự động — có trợ lý AI gợi ý khi bí.