Chuyển tới nội dung chính

Cơ chế chú ý và Transformer

Phần lớn các hệ thống AI đang định hình công nghệ hôm nay, từ trợ lý lập trình tới các mô hình ngôn ngữ lớn, đều dựa trên một kiến trúc duy nhất: transformer. Bài này dựng một bản đồ trực giác để hiểu nó, đi từ học sâu cổ điển, qua cách biểu diễn từ bằng vector, tới cơ chế chú ý (attention) và lý do transformer thay thế các mạng tuần tự. Ta cố ý giữ mức trực giác, chính xác và không phóng đại; phần toán nặng được bỏ qua.

Thử ngay: trọng số chú ý trong một câu

Cơ chế chú ý, nói gọn, là việc mỗi từ trong câu tự quyết định nên nhìn vào những từ nào khác để hiểu chính mình, và nhìn mỗi từ đó nhiều hay ít; mức nhiều ít ấy gọi là trọng số chú ý. Hãy thử trực tiếp ngay bây giờ. Bấm chọn một từ truy vấn để xem nó chú ý tới các từ khác nhiều hay ít, và quan sát ma trận chú ý bên dưới. Trọng số ở đây do người soạn đặt để minh hoạ khái niệm, không phải số lấy từ mô hình thật.

Cơ chế chú ý: chọn một từ truy vấnminh hoạ khái niệm
Bấm vào một từ để xem nó "chú ý" tới các từ khác nhiều hay ít. Ô càng đậm thì trọng số chú ý càng cao.
"nó" là đại từ nhập nhằng: ở đây chú ý mạnh tới "thảm" và "mèo", hai ứng viên mà nó có thể trỏ về.
Ma trận chú ý (hàng = query, cột = key)
q \ kconmèongồitrênthảmấm
con0.350.400.080.040.050.020.030.03
mèo0.180.350.220.050.100.020.050.03
ngồi0.050.300.200.150.220.020.030.03
trên0.020.080.180.200.420.020.040.04
thảm0.030.100.120.200.300.030.070.15
0.030.060.050.050.080.180.300.25
0.040.250.050.060.340.040.120.10
ấm0.020.080.040.060.300.050.250.20
Lưu ý: mọi trọng số ở đây do người soạn đặt để minh hoạ khái niệm, không phải số lấy từ một mô hình thật. Chú ý cho phép mỗi từ nhìn mọi từ khác và gộp thông tin theo trọng số; trọng số cao không phải bằng chứng rằng mô hình "hiểu" từ đó.

Từ học máy cổ điển tới học sâu hiện đại

Các mô hình cổ điển như cây quyết định hay hồi quy tuyến tính có một đặc điểm chung: con người phải tự chọn đặc trưng (feature) đưa vào mô hình. Muốn dự đoán giá nhà, ta tự nghĩ ra các đặc trưng diện tích, số phòng, khoảng cách tới trung tâm. Chất lượng mô hình phụ thuộc nhiều vào công đoạn thủ công này, thường gọi là kỹ thuật đặc trưng (feature engineering).

Học sâu (deep learning) thay đổi cách làm đó. Thay vì người tự thiết kế đặc trưng, mạng nơ-ron nhiều tầng tự học cách biểu diễn dữ liệu qua từng tầng: tầng thấp bắt các nét đơn giản, tầng cao ghép lại thành khái niệm phức tạp hơn. Với ảnh, tầng đầu có thể bắt cạnh và góc, tầng giữa bắt mắt và mũi, tầng cao bắt cả khuôn mặt. Đây là điểm mấu chốt: học sâu tự học biểu diễn thay vì chờ con người cung cấp.

Hai yếu tố biến học sâu từ ý tưởng cũ thành công cụ thực dụng là dữ liệu lớnsức tính toán. Thuật toán lan truyền ngược đã có từ thập niên 1980, nhưng phải tới khi có tập dữ liệu hàng triệu ảnh và bộ xử lý đồ hoạ (GPU) đủ mạnh thì các mạng sâu mới huấn luyện được trong thời gian chấp nhận được. Cột mốc thường được nhắc tới là năm 2012, khi một mạng tích chập (CNN) thắng áp đảo cuộc thi nhận dạng ảnh ImageNet, mở ra làn sóng học sâu.

So sánh nhanh

Khác biệt cốt lõi giữa học máy cổ điển và học sâu nằm ở chỗ ai chọn đặc trưng. Cổ điển: con người thiết kế đặc trưng rồi mô hình học trên đó, chạy tốt khi dữ liệu ít và thường dễ giải thích. Học sâu: mạng tự học biểu diễn từ dữ liệu thô (ảnh, âm thanh, văn bản), đổi lại cần nhiều dữ liệu và nhiều tính toán hơn, và khó giải thích hơn.

Đây là so sánh xu hướng chứ không phải ranh giới tuyệt đối: nhiều bài toán thực tế vẫn dùng mô hình cổ điển vì chúng nhẹ, dễ giải thích và chạy tốt khi dữ liệu ít.

Biểu diễn từ bằng vector

Máy tính chỉ làm việc với số, nên muốn cho mạng nơ-ron xử lý ngôn ngữ ta phải biến từ thành số. Cách ngây thơ nhất là gán mỗi từ một chỉ số rồi dùng vector một nóng (one-hot): vector dài bằng số từ trong từ điển, đúng một vị trí bằng 1, còn lại bằng 0. Cách này có hai nhược điểm lớn:

  • Vector rất dài và thưa khi từ điển có hàng chục nghìn từ.
  • Mọi từ cách đều nhau, nên máyô tô xa nhau y như máychuối, dù về nghĩa thì hai từ đầu gần nhau hơn nhiều.

Biểu diễn từ bằng vector (word embedding) giải quyết cả hai vấn đề. Mỗi từ được gán một vector số thực ngắn, ví dụ từ 100 tới 300 chiều, học được từ một kho văn bản lớn. Ý tưởng nền tảng là một từ được hiểu qua các từ thường đứng cạnh nó: những từ xuất hiện trong ngữ cảnh giống nhau sẽ có vector gần nhau. Nhờ vậy, các từ gần nghĩa nằm gần nhau trong không gian vector, và ta đo được độ tương tự bằng góc giữa hai vector.

Định nghĩa

Biểu diễn từ bằng vector là phép gán mỗi từ một vector số thực số chiều cố định, sao cho khoảng cách hình học giữa các vector phản ánh mức độ gần nhau về ngữ nghĩa. Vector này được học tự động từ thống kê đồng xuất hiện của từ trong kho văn bản lớn.

Một quan sát thú vị là các quan hệ ngữ nghĩa đôi khi hiện ra dưới dạng phép cộng trừ vector. Ví dụ kinh điển từ mô hình Word2Vec: lấy vector của vua trừ đàn ông rồi cộng đàn bà, kết quả nằm rất gần vector của nữ hoàng. Viết gọn:

vector("vua") - vector("đàn ông") + vector("đàn bà") ~ vector("nữ hoàng")

Điều này cho thấy embedding không chỉ lưu nghĩa của từng từ mà còn nắm được một phần cấu trúc quan hệ giữa chúng.

Đo độ tương tự bằng cosine

Cách phổ biến để đo hai vector embedding gần nhau tới đâu là độ tương tự cosine: cosine của góc giữa hai vector. Giá trị nằm trong khoảng từ -1 tới 1; càng gần 1 thì hai từ càng gần nghĩa. Đoạn mã dưới đây minh hoạ ý tưởng với vài vector tự đặt (trong thực tế chúng được tra từ một mô hình đã huấn luyện).

import numpy as np

# Pretend embeddings are looked up from a trained model
def cosine_similarity(u, v):
# Returns a value in [-1, 1]; higher means more similar
return (u @ v) / (np.linalg.norm(u) * np.linalg.norm(v))

vec_may = np.array([0.21, -0.04, 0.88]) # "may" (machine)
vec_oto = np.array([0.19, -0.02, 0.81]) # "o to" (car)
vec_chuoi = np.array([-0.70, 0.55, 0.10]) # "chuoi" (banana)

print(cosine_similarity(vec_may, vec_oto)) # close to 1
print(cosine_similarity(vec_may, vec_chuoi)) # close to 0
Embedding cũng kế thừa định kiến

Embedding học từ dữ liệu nên cũng kế thừa định kiến trong dữ liệu. Nếu kho văn bản gắn một số nghề với một giới tính, vector từ sẽ phản ánh đúng định kiến đó. Đây là một nguồn gốc của thiên lệch (bias) cần lưu ý khi dùng AI cho các quyết định ảnh hưởng tới con người.

Cơ chế chú ý

Embedding cho mỗi từ một vector cố định, nhưng nghĩa của một từ lại phụ thuộc ngữ cảnh. Trong câu con chuột cắn dâycon chuột máy tính, từ chuột mang hai nghĩa khác nhau. Để hiểu đúng, mô hình cần nhìn các từ xung quanh. Cơ chế chú ý (attention) ra đời để làm việc này: khi xử lý một từ, mô hình tính xem nên chú ý bao nhiêu tới từng từ khác trong câu, rồi tổng hợp thông tin theo trọng số chú ý đó.

Query, key, value

Có thể hình dung attention như một phép tra cứu mềm. Mỗi từ phát ra một câu hỏi (query), mỗi từ khác mang một khoá (key) và một giá trị (value):

  • Từ đang xét so query của mình với key của mọi từ để biết từ nào liên quan.
  • Mức liên quan đó được biến thành trọng số chú ý, các trọng số dương và cộng lại bằng 1.
  • Kết quả là trung bình có trọng số các value tương ứng: từ liên quan nhiều thì đóng góp nhiều.

Đầu ra là một biểu diễn mới của từ, đã được pha trộn thông tin ngữ cảnh. Ví dụ khi xử lý từ chuột trong câu con chuột máy tính, mô hình có thể phân bổ trọng số như sau:

con -> 0.10
chuột -> 0.45 (chính nó)
máy -> 0.30
tính -> 0.15

Trọng số lớn ở máytính kéo nghĩa của chuột về phía thiết bị máy tính chứ không phải con vật. Các trọng số này không do con người đặt mà do mô hình tự học từ dữ liệu.

Thuật ngữ cần nắm
Giữ ở mức trực giác

Ta cố ý bỏ qua phần công thức của attention. Ở mức nhập môn, chỉ cần nắm trực giác: attention cho phép mỗi từ nhìn và chọn lọc thông tin từ những từ liên quan trong câu, qua bộ ba query, key, value.

Chú ý đa đầu

Một lớp chú ý duy nhất chỉ học được một kiểu quan hệ giữa các từ. Nhưng trong một câu thường có nhiều loại quan hệ chồng lên nhau: quan hệ ngữ pháp (chủ ngữ đi với động từ nào), quan hệ ngữ nghĩa (một đại từ trỏ về danh từ nào), quan hệ vị trí gần (từ liền trước, liền sau). Ép một phép chú ý duy nhất gánh hết mọi quan hệ này là quá tải. Transformer giải quyết bằng chú ý đa đầu (multi-head attention): thay vì tính một phép chú ý, mô hình tính nhiều phép chú ý song song, mỗi phép gọi là một đầu (head).

Mỗi đầu có bộ query, key, value riêng nên học một kiểu quan hệ riêng. Một đầu có thể chuyên bám sát từ liền kề, một đầu khác chuyên nối động từ với chủ ngữ ở xa, đầu khác nữa lại theo dõi quan hệ đồng tham chiếu. Kết quả của các đầu được ghép lại rồi trộn thêm một lần thành biểu diễn cuối cho từ. Nhờ chạy song song nhiều đầu, một lớp chú ý nắm được đồng thời nhiều mặt của ngữ cảnh thay vì bị buộc chọn một mặt duy nhất.

Kiến trúc transformer

Transformer, công bố năm 2017, là kiến trúc xếp chồng nhiều lớp chú ý như trên, đan xen với các tầng nơ-ron thường. Qua mỗi lớp, biểu diễn của từng từ lại được làm giàu thêm bằng ngữ cảnh, nên các lớp sâu nắm được những quan hệ ngày càng tinh tế trong câu.

Biểu diễn một từ được làm giàu qua transformer
Nhúng từ
mỗi từ thành một vector
Lớp chú ý
gom ngữ cảnh qua query, key, value
Tầng nơ-ron thường
biến đổi thêm biểu diễn
Xếp chồng nhiều lớp
quan hệ ngày càng tinh tế
Biểu diễn giàu ngữ cảnh
đầu ra của từ

Mã hoá vị trí

Vì transformer xử lý mọi từ cùng lúc chứ không đọc lần lượt, bản thân cơ chế chú ý không hề biết từ nào đứng trước từ nào. Nếu ta xáo trộn thứ tự các từ đầu vào, phép chú ý cho ra đúng tập kết quả cũ chỉ hoán vị lại. Nhưng thứ tự lại mang nghĩa: chó cắn người khác hẳn người cắn chó dù dùng y hệt các từ. Bỏ hồi quy để được song song hoá, ta đánh mất thông tin thứ tự vốn có sẵn trong cách RNN đọc từng từ.

Để bù lại, transformer cộng thêm vào mỗi embedding một mã hoá vị trí (positional encoding): một vector chỉ phụ thuộc vào vị trí của từ trong câu. Sau khi cộng, vector của một từ mang cả thông tin nghĩa lẫn thông tin vị trí, nên mô hình phân biệt được người đứng đầu câu với người đứng cuối câu. Có nhiều cách tạo mã hoá vị trí, từ các hàm sin và cosin cố định cho tới vector vị trí học được cùng mô hình, nhưng ý tưởng chung đều là tiêm thông tin thứ tự vào đầu vào để cơ chế chú ý có cái mà dựa vào.

Vì sao thay RNN

Trước transformer, văn bản thường được xử lý bằng các mạng tuần tự như RNN hay LSTM: đọc từ trái sang phải, lần lượt từng từ, mỗi bước cập nhật một bộ nhớ trạng thái. Cách này có hai điểm yếu:

  • Khó song song hoá: vì phải xử lý từ này xong mới tới từ sau, không tận dụng tốt khả năng tính song song của GPU, nên huấn luyện chậm trên dữ liệu lớn.
  • Khó nắm quan hệ xa: thông tin từ đầu câu phải đi qua nhiều bước mới tới cuối câu, dễ bị pha loãng dần.

Transformer xử lý mọi từ trong câu cùng lúc thay vì lần lượt. Nhờ vậy nó huấn luyện song song được trên GPU và mở rộng tốt khi tăng dữ liệu cùng số tham số. Cơ chế chú ý cũng cho phép một từ nối thẳng tới bất kỳ từ nào khác trong một bước, nên quan hệ xa được nắm trực tiếp hơn. Đó là lý do phần lớn các mô hình ngôn ngữ hiện đại đều dựa trên transformer.

Cái giá phải trả cho việc cho mọi từ nhìn thẳng tới mọi từ là chi phí tính toán tăng theo bình phương độ dài chuỗi. Với câu có n từ, một lớp chú ý phải tính mức liên quan cho n nhân n cặp từ, nên gấp đôi độ dài câu thì chi phí phần chú ý gấp bốn. Đây là lý do các mô hình có một giới hạn độ dài ngữ cảnh, và là một hướng nghiên cứu sôi động nhằm tìm biến thể chú ý rẻ hơn cho chuỗi rất dài.

Hiểu nhầm thường gặp

Nhiều người xem trọng số chú ý cao ở một từ là bằng chứng rằng mô hình đã hiểu từ đó quan trọng, rồi dùng bản đồ chú ý như một lời giải thích chắc chắn cho quyết định của mô hình. Thực ra trọng số chú ý chỉ cho biết thông tin được gom từ đâu ở một lớp, không phải bằng chứng về suy luận. Một mô hình có nhiều lớp và nhiều đầu, thông tin bị pha trộn qua lại phức tạp, nên đọc riêng một bản đồ chú ý dễ dẫn tới kết luận sai về lý do mô hình quyết định như vậy.

Lưu ý về quy mô

Transformer không phải là phép màu. Khả năng mạnh mẽ của các mô hình ngôn ngữ lớn đến từ kiến trúc transformer cộng với lượng dữ liệu và tính toán rất lớn. Bản thân kiến trúc chỉ là điều kiện cần; phần còn lại là dữ liệu, tính toán và công sức huấn luyện.

Bài tập thực hành

Bài tập 1: vì sao one-hot không nắm được ngữ nghĩa

Giải thích bằng lời vì sao biểu diễn một nóng (one-hot) không nắm được quan hệ ngữ nghĩa giữa các từ, trong khi embedding thì có. Cho một cặp từ gần nghĩa và một cặp từ xa nghĩa.

Gợi ý

Với one-hot, mọi cặp từ khác nhau đều cách nhau đúng như nhau, nên khoảng cách không mang thông tin nghĩa: máyô tô xa nhau y hệt máychuối. Embedding gán vector học từ ngữ cảnh, nên máyô tô (cùng xuất hiện cạnh các từ về phương tiện, máy móc) có vector gần nhau, còn máychuối thì xa nhau.

Bài tập 2: tìm từ gần nghĩa nhất bằng cosine

Dựa trên hàm cosine_similarity ở trên, viết một hàm nhận một vector truy vấn và một danh sách các cặp (từ, vector), rồi trả về từ có độ tương tự cosine cao nhất với truy vấn. Kiểm thử với vài vector tự đặt.

Gợi ý
def tu_gan_nhat(truy_van, danh_sach):
# danh_sach: list of (word, vector)
tot_nhat = None
diem_cao_nhat = -2.0 # cosine is always >= -1
for tu, vec in danh_sach:
diem = cosine_similarity(truy_van, vec)
if diem > diem_cao_nhat:
diem_cao_nhat = diem
tot_nhat = tu
return tot_nhat

Gọi thử với truy_van = vec_may và danh sách gồm ("o to", vec_oto) cùng ("chuoi", vec_chuoi); kết quả phải là o to.

Bài tập 3: mô tả attention cho một từ đa nghĩa

Dùng cách hình dung query, key, value, hãy mô tả bằng lời cơ chế chú ý xác định nghĩa của từ chuột trong câu con chuột máy tính bị hỏng. Từ nào nên nhận trọng số chú ý cao và vì sao.

Gợi ý

Khi xử lý chuột, mô hình so query của nó với key của các từ còn lại. Các từ máy, tínhhỏng gợi ngữ cảnh thiết bị, nên nhận trọng số chú ý cao; chúng kéo nghĩa của chuột về phía thiết bị máy tính chứ không phải con vật. Đầu ra là biểu diễn mới của chuột đã pha trộn ngữ cảnh này.

Tự kiểm tra

Khác biệt cốt lõi giữa học máy cổ điển và học sâu là gì?

Nằm ở chỗ ai chọn đặc trưng. Cổ điển: con người thiết kế đặc trưng thủ công rồi mô hình học trên đó, chạy tốt khi dữ liệu ít và thường dễ giải thích. Học sâu: mạng tự học biểu diễn từ dữ liệu thô, đổi lại cần nhiều dữ liệu, nhiều tính toán và khó giải thích hơn.

Attention làm gì, và transformer khác RNN ra sao?

Attention cho phép mỗi từ nhìn và chọn lọc thông tin từ các từ liên quan trong câu, qua bộ ba query, key, value với các trọng số chú ý do mô hình tự học. Transformer xếp chồng nhiều lớp chú ý và xử lý mọi từ cùng lúc, nên song song hoá tốt trên GPU và nắm quan hệ xa trực tiếp hơn các mạng tuần tự như RNN, vốn xử lý từng từ lần lượt.

Vì sao transformer cần mã hoá vị trí, còn chú ý đa đầu để làm gì?

Vì transformer xử lý mọi từ cùng lúc nên cơ chế chú ý không tự biết thứ tự các từ; xáo trộn đầu vào vẫn cho cùng kết quả hoán vị lại. Mã hoá vị trí cộng vào mỗi từ một vector phụ thuộc vị trí để tiêm lại thông tin thứ tự, nhờ đó chó cắn người khác người cắn chó. Chú ý đa đầu chạy nhiều phép chú ý song song, mỗi đầu có query, key, value riêng nên học một kiểu quan hệ riêng (ngữ pháp, đồng tham chiếu, vị trí gần), giúp một lớp nắm nhiều mặt của ngữ cảnh cùng lúc.

Câu hỏi tự kiểm

Kiểm tra nhanh: chú ý và Transformer0/4 đúngchưa trả lời
  1. 1Trong cơ chế chú ý, trọng số chú ý được dùng để làm gì?
  2. 2Vì sao transformer cần mã hoá vị trí?
  3. 3Chi phí tính toán của một lớp chú ý tăng thế nào theo độ dài chuỗi n?
  4. 4Phát biểu nào đúng về trọng số chú ý cao ở một từ?
Ghi nhớ

Học sâu tự học biểu diễn thay cho kỹ thuật đặc trưng thủ công. Embedding gán mỗi từ một vector sao cho từ gần nghĩa nằm gần nhau, đo bằng độ tương tự cosine. Cơ chế chú ý cho mỗi từ gom ngữ cảnh từ các từ liên quan qua bộ ba query, key, value. Transformer xếp chồng cơ chế này, xử lý mọi từ cùng lúc nên thay được RNN và là nền tảng của các mô hình ngôn ngữ hiện đại.