Trực quan hóa attention: trái tim của Transformer [Video]
(3blue1brown.com)- Attention trong Transformer là cơ chế cập nhật embedding của token theo ngữ cảnh, khiến cùng một từ cũng được dịch chuyển thành vector mang ý nghĩa khác nhau tùy theo các từ xung quanh
- Một attention head tạo các vector query/key/value từ mỗi token, rồi tính attention pattern — trọng số mức độ liên quan giữa các từ — bằng tích vô hướng key-query và softmax
- Mô hình tự hồi quy kiểu GPT áp dụng masking để token phía sau không ảnh hưởng đến token phía trước; vì kích thước attention pattern tăng theo bình phương độ dài ngữ cảnh nên việc mở rộng context window lớn là gánh nặng
- Trong ví dụ GPT-3, mỗi ma trận key/query có 1.572.864 tham số, còn value map được chia thành phép biến đổi hạng thấp, tạo ra khoảng 6,3 triệu tham số cho mỗi head
- Transformer lặp lại nhiều attention head và block để học nhiều cách cập nhật ngữ cảnh khác nhau; một trụ cột lớn của thành công là khả năng song song hóa, cho phép xử lý nhanh lượng tính toán lớn trên GPU
Vai trò của attention trong Transformer
- Transformer dùng văn bản đầu vào để dự đoán token tiếp theo; đầu vào trước hết được token hóa thành các từ hoặc mảnh từ
- Mỗi token được chuyển thành một embedding, tức một vector nhiều chiều
- Các hướng trong không gian embedding này có thể tương ứng với ý nghĩa
- Ví dụ, dịch chuyển theo một hướng nhất định có thể đưa embedding của danh từ giống đực sang embedding của danh từ giống cái tương ứng
- Mục tiêu của attention là dần điều chỉnh embedding ban đầu để nó chứa không chỉ thông tin của từng từ riêng lẻ mà còn cả ý nghĩa theo ngữ cảnh phong phú hơn
Vì sao cùng một từ thay đổi theo ngữ cảnh
- Trong “American shrew mole”, “One mole of carbon dioxide”, “Take a biopsy of the mole”, mole có các nghĩa khác nhau
- Ở bước embedding đầu tiên, vector của mole gần giống như lấy từ một lookup table không xét ngữ cảnh, nên giống nhau trong cả ba trường hợp
- Ở bước tiếp theo, attention block, các embedding xung quanh có thể truyền thông tin vào embedding của mole để cập nhật giá trị của nó
- Một mô hình được huấn luyện tốt liên kết các nghĩa khác nhau của mole với các hướng khác nhau trong không gian embedding, rồi tính xem cần cộng gì vào embedding chung tùy theo ngữ cảnh
- Như “Eiffel tower” và “miniature Eiffel tower”, embedding của một từ có thể được cập nhật không chỉ bằng các từ ở gần mà còn bằng thông tin đến từ những token ở xa
- Vì chỉ vector cuối cùng được dùng cho dự đoán từ tiếp theo, embedding của từ cuối trong đầu vào dài phải phần nào chứa toàn bộ thông tin ngữ cảnh cần thiết cho dự đoán
Luồng tính toán của một attention head đơn
- Phần giải thích cơ bản dựa trên single head of attention
- Với câu ví dụ “A fluffy blue creature roamed the verdant forest.”, ta giả định tình huống các tính từ cập nhật embedding ban đầu của danh từ tương ứng
- Ví dụ này nhằm minh họa một hành vi mà attention head có thể thực hiện
- Hành vi thực tế của head khó diễn giải, vì đó là kết quả của việc nhiều tham số được điều chỉnh để giảm hàm chi phí
- Embedding ban đầu chứa cả thông tin từ lẫn thông tin vị trí, được ký hiệu là
\vec{E} - Mục tiêu là tạo embedding mới
\vec{E}'phản ánh ngữ cảnh từ embedding hiện có -
Query
- Ở bước đầu tiên, nhân embedding của mỗi token với query matrix
W_Qđể tạo vector query\vec{Q} - Có thể hình dung danh từ đặt câu hỏi kiểu “có tính từ nào đứng phía trước không?”
- Các phần tử của
W_Qlà tham số mô hình được học, và trên thực tế rất khó diễn giải một head cụ thể đang làm gì - Về mặt minh họa, có thể xem nó như ánh xạ embedding của danh từ sang hướng “tìm tính từ ở vị trí trước đó”
- Ở bước đầu tiên, nhân embedding của mỗi token với query matrix
-
Key
- Đồng thời, nhân mỗi embedding với key matrix
W_kđể tạo vector key\vec{K} - Key có thể được xem là câu trả lời tiềm năng cho query, và nằm trong cùng một không gian có số chiều nhỏ hơn như query
- Mức độ căn chỉnh giữa key và query được đo bằng tích vô hướng
- Tích vô hướng càng lớn thì hai vector càng căn chỉnh mạnh
- Nếu key của fluffy và blue khớp tốt với query của creature, chúng sẽ có giá trị dương lớn
- Khi tính tích vô hướng cho mọi cặp key-query, ta thu được một lưới điểm số cho biết từ nào liên quan đến việc cập nhật ý nghĩa của từ khác đến mức nào
- Đồng thời, nhân mỗi embedding với key matrix
Attention pattern và softmax
- Vì điểm tích vô hướng có thể nhận giá trị từ
-\inftyđến\infty, ta áp dụng softmax cho từng cột để chuẩn hóa về giá trị từ 0 đến 1 - Lưới đã chuẩn hóa được gọi là attention pattern
- Mỗi cột có thể được xem là các trọng số cho biết từ bên trái liên quan đến việc cập nhật từ phía trên đến mức nào
- Bài báo Transformer gốc ký hiệu điều này gọn hơn
QvàKlà toàn bộ mảng vector query và keyK^TQbiểu diễn lưới tất cả các tích vô hướng key-query có thể có- Trong ký hiệu của bài báo, query và key được đặt theo hàng và viết dưới dạng
QK^T, nên hình dạng bị lật theo hướng đường chéo so với hình minh họa được giải thích ở đây
- Để ổn định số học, có thêm hạng chia cho
\sqrt{d_k}, căn bậc hai của số chiều không gian key-query - Softmax bao bọc toàn bộ biểu thức, nhưng về mặt ý nghĩa được áp dụng theo từng cột
Masking và giới hạn kích thước context
- Trong quá trình huấn luyện, mô hình không chỉ dự đoán một token tiếp theo duy nhất từ văn bản đã cho, mà còn đồng thời dự đoán token tiếp theo khả dĩ sau từng chuỗi con
- Một ví dụ văn bản hoạt động như nhiều ví dụ huấn luyện, làm tăng hiệu quả
- Trong ví dụ GPT, nếu token phía sau ảnh hưởng đến token phía trước thì có thể làm lộ đáp án token tiếp theo, nên masking được dùng
- Trước softmax, giá trị ở vị trí tương ứng được đặt thành âm vô cực
- Sau softmax, vị trí đó trở thành 0, còn cột vẫn được chuẩn hóa
- Không phải mọi attention đều luôn áp dụng masking, nhưng trong ví dụ GPT, nó luôn được dùng để token phía sau không ảnh hưởng đến token phía trước
- Kích thước attention pattern bằng bình phương của context size
- Vì vậy context size có thể trở thành một giới hạn quan trọng của các mô hình ngôn ngữ lớn
- Đã xuất hiện các biến thể làm cơ chế attention dễ mở rộng hơn cho context window lớn hơn, nhưng ở đây chỉ đề cập dạng cơ bản
Cách dùng Value để thực sự cập nhật embedding
- Attention pattern cung cấp trọng số cho biết từ nào sẽ cập nhật từ nào; bước tiếp theo là tạo ra lượng thay đổi thực tế của embedding
- Nhân mỗi embedding với value matrix
W_Vđể tạo vector value- Vector value nằm trong cùng không gian nhiều chiều như embedding
- Nó biểu thị thay đổi cụ thể nào cần được cộng thêm khi một từ liên quan điều chỉnh ý nghĩa của từ khác
- Trong mỗi cột, nhân vector value với trọng số tương ứng trong attention pattern rồi cộng tất cả lại, ta được lượng thay đổi
\Delta \vec{E} - Cộng lượng thay đổi này vào embedding gốc sẽ tạo ra embedding mới
\vec{E}'phản ánh ngữ cảnh- Trong ví dụ, creature hấp thụ thông tin từ fluffy và blue, nên chứa ý nghĩa gần với “fluffy blue creature”
- Áp dụng cùng quy trình cho mọi cột, ta thu được các embedding đã được tinh chỉnh cho toàn bộ chuỗi token ở đầu ra của attention block
- Một attention head đơn được tham số hóa bằng ba loại ma trận tham số học được: key matrix, query matrix, value matrix
Tính toán tham số theo GPT-3
- Trong ví dụ GPT-3, các ma trận key và query mỗi ma trận có 12.288 cột tương ứng với số chiều embedding và 128 hàng tương ứng với số chiều không gian key-query
- Mỗi ma trận có 1.572.864 tham số
- Nếu đặt value matrix là ma trận vuông 12.288×12.288, nó sẽ thêm 150.994.944 tham số, lớn hơn key/query rất nhiều
- Trên thực tế, hiệu quả hơn là phân rã value map thành hai ma trận nhỏ để đưa số tham số về mức tương tự key/query
- Ma trận thứ nhất hạ không gian embedding lớn xuống một không gian nhỏ như 128 chiều
- Ma trận thứ hai nâng từ không gian nhỏ trở lại không gian embedding
- Theo góc nhìn đại số tuyến tính, điều này giới hạn toàn bộ value map thành một phép biến đổi hạng thấp
- Trong phần giải thích này, hai ma trận được gọi là
Value_\downarrow,Value_\uparrow, nhưng đây không phải tên gọi theo quy ước - Gộp bốn ma trận lại, một attention head có khoảng 6,3 triệu tham số
Self-attention và cross-attention
- Cấu trúc đến đây, nói chính xác hơn, tương ứng với self-attention head
- cross-attention head xuất hiện trong các mô hình xử lý hai tập dữ liệu khác nhau
- Ví dụ trong mô hình dịch, key có thể đến từ một ngôn ngữ còn query đến từ ngôn ngữ khác
- Attention pattern có thể cho thấy từ trong một ngôn ngữ tương ứng với từ trong ngôn ngữ kia như thế nào
- Trong cross-attention, điểm khác với self-attention là key map và query map tác động lên các tập dữ liệu khác nhau
- Trong bối cảnh như dịch máy, thường không có masking vì không có khái niệm token phía sau ảnh hưởng đến token phía trước
Multi-headed attention và các block lặp lại
- Attention block thực tế được cấu thành từ multi-headed attention, chạy nhiều head song song
- GPT-3 dùng 96 attention head trong mỗi block
- 96 ma trận key/query khác nhau tạo ra 96 attention pattern khác nhau
- Mỗi head tạo chuỗi vector value bằng các ma trận value riêng
- Ở mỗi vị trí token, cộng tất cả lượng thay đổi
\Delta \vec{E}do các head đề xuất rồi thêm vào embedding gốc
- Chạy nhiều head song song giúp mô hình có năng lực học nhiều cách ngữ cảnh làm thay đổi ý nghĩa
- Theo GPT-3, một multi-headed attention block với 96 head có khoảng 600 triệu tham số
- Trong bài báo và các triển khai thực tế, các ma trận tương ứng với
Value_\uparrowcủa từng head được gom thành một output matrix lớn và nối với toàn bộ multi-headed attention block- Thông thường, khi nói value matrix của một head cụ thể, người ta chỉ bước chiếu đầu tiên, ở đây được gọi là
Value_\downarrow
- Thông thường, khi nói value matrix của một head cụ thể, người ta chỉ bước chiếu đầu tiên, ở đây được gọi là
Cách ý nghĩa tích lũy trong Transformer sâu hơn
- Dữ liệu bên trong Transformer không chỉ đi qua một attention block, mà qua nhiều attention block và multi-layer perceptron
- Ngay cả sau khi embedding của một từ đã hấp thụ một phần ngữ cảnh, nó vẫn tiếp tục có cơ hội chịu ảnh hưởng từ các embedding xung quanh đã tinh chỉnh hơn
- Khi mạng sâu hơn, mỗi embedding tiếp nhận nhiều ý nghĩa hơn từ các embedding khác, và có năng lực mã hóa các đặc trưng trừu tượng cấp cao hơn như cảm xúc, tông giọng, hoặc liệu có phải thơ hay không
- GPT-3 có 96 layer, và các tham số liên quan đến key/query/value được mô tả là tổng cộng dưới 58 tỷ
- Con số này chiếm khoảng một phần ba tổng tham số của toàn mạng, phần lớn còn lại đến từ các block nằm giữa các attention
- Một phần lớn thành công của cơ chế attention không nằm ở một hành vi cụ thể nào, mà ở khả năng song song hóa cao, cho phép thực hiện nhiều phép tính trên GPU trong thời gian ngắn
- Bài học rằng mở rộng quy mô trong deep learning có thể đem lại cải thiện lớn về chất cho hiệu năng mô hình khiến các kiến trúc có thể song song hóa và cho phép mở rộng có lợi thế lớn
1 bình luận
Ý kiến trên Hacker News
Từ góc nhìn của một người từng làm về hóa học lượng tử và một phần machine learning, khi xem video này tôi thấy sự tương đồng giữa mô hình transformer và cơ học lượng tử khá nổi bật
Trong cơ học lượng tử, trạng thái của toàn bộ hệ vật lý được mã hóa dưới dạng một vector chuẩn hóa rất cao chiều, tức một tia trong không gian Hilbert, và sự biến đổi theo thời gian được đảm nhiệm bởi toán tử dịch thời gian, có thể xem xấp xỉ là ma trận unitary U = exp(-iHt)
Trong video, việc dự đoán token tiếp theo được quyết định bằng cách chỉ dùng vector embedding nhận biết ngữ cảnh cuối cùng để tính ra vector embedding nhận biết ngữ cảnh tiếp theo, nên trông giống như kết quả của việc áp dụng một hàm trạng thái tuyến tính lên vector cao chiều
Cảm giác khá giống với việc tạo offline Hamiltonian của toàn hệ từ dữ liệu huấn luyện, rồi tái tham số hóa một hệ con cụ thể là cửa sổ ngữ cảnh theo cơ sở phù hợp với Hamiltonian đó, áp dụng một bước dịch thời gian, rồi quay lại cơ sở ban đầu
Nhưng cũng có chuyện là với người nghiên cứu một lĩnh vực nào đó lâu năm thì mọi vấn đề đều dễ trông như cái đinh cho chiếc búa của lĩnh vực ấy, nên tôi cũng tò mò không biết người khác có thấy sự tương đồng này không hay là phép so sánh này quá gượng ép
Nếu mỗi lần áp dụng toán tử làm trạng thái vũ trụ tiến thêm đúng một khoảng thời gian Planck, thì tôi cũng tự hỏi liệu chúng ta có thể quan sát được sự khác biệt giữa một vũ trụ như vậy và một vũ trụ có thời gian liên tục hay không
Mãi đến giờ tôi mới nghĩ tới mối liên hệ với những gì đã xảy ra trong vật lý vào thời đó
Video YouTube của CodeEmporium dễ theo dõi hơn: https://www.youtube.com/watch?v=Nw_PJdmydZY
Transformer rất khó giải thích bằng ẩn dụ, mà thật ra cũng không có lời giải thích nào thật sự tốt về việc vì sao nó hoạt động, nên có lẽ cứ cho thấy cơ chế rồi để người xem tự diễn giải còn tốt hơn
Ngoài ra, giải thích tích vô hướng như việc các vector chiếu lên nhau cũng đơn giản hơn
Lý do sau “the cat sat on the ...” lại là “mat” là vì đó là từ xuất hiện thường xuyên nhất trong tập dữ liệu, và mạng nơ-ron là mô hình của các tần suất đó
Lý do nó có vẻ biết “London in UK” nhưng không biết “London in France” cũng là vì “UK” xuất hiện thường xuyên hơn rất nhiều trong tập dữ liệu
Bản thân thuật toán không làm điều gì đặc biệt thú vị ngoài việc sắp xếp phép tính sao cho phù hợp với phần cứng. Giá trị đến từ cấu trúc xác suất có điều kiện trong dữ liệu, mà cấu trúc đó lại là kết quả của việc con người sắp xếp từ ngữ một cách hữu ích để truyền đạt thông tin cho nhau
Tôi biết đây là một lời giải thích chưa đầy đủ, nhưng vẫn còn hơn là không có gì
Có một hình dung trực quan khá thuyết phục cho thấy LLM hoạt động thế nào khi xử lý các yêu cầu đơn giản: https://bbycroft.net/llm
Nó bổ sung rất tốt cho phần giải thích chi tiết của 3blue1brown
Video rất tuyệt. Nó cho thấy rõ vì sao phép nhân ma trận Q*K là nút thắt cổ chai. Nếu độ dài chuỗi, tức độ dài cửa sổ ngữ cảnh, là S thì phải lưu trong bộ nhớ một ma trận kích thước SxS là kết quả của mọi query với mọi key
Một ý tưởng tương đối mới để cải thiện nút thắt này là Ring Attention, và bài này giải thích rất hay: https://learnandburn.ai/p/how-to-build-a-10m-token-context
Tôi là người biên tập bài đó
Với Unsloth, nhờ Flash Attention mà mức dùng bộ nhớ tăng tuyến tính thay vì tăng bậc hai, fine-tuning nhanh gấp 2 lần, VRAM giảm 80% và suy luận cũng nhanh gấp 2 lần. Tuy vậy, lượng tính toán vẫn là O(N^2)
Với ngữ cảnh dài, bản phát hành mới nhất của Unsloth có thể chứa ngữ cảnh dài gấp 4 lần so với HF+FA2 chỉ với +1.9% overhead, đạt tới 228K ngữ cảnh trên H100
Bài trước đó là “But what is a GPT?” cũng rất hay: https://www.3blue1brown.com/lessons/gpt
Nhờ video này mà tôi nhận ra cơ chế attention gần với một loại siêu hàm hơn là một hàm cụ thể.
Nếu tôi hiểu đúng, Attention + các trọng số đã học cho phép transformer học một hàm khá tùy ý ở mức nào đó, và trong hàm đó có cơ chế khớp như scaled dot-product.
Vì thế tôi nghĩ linear attention khó có thể tiệm cận được năng lực của attention tiêu chuẩn. Hạng bậc hai duyệt mọi cặp đầu vào-đầu ra là một đặc tính thiết yếu.
Video này dễ tiếp thu phần lớn là nhờ hoạt ảnh. Cách nó phóng to, thu nhỏ và mở ra đúng theo nhịp lời thoại được làm cực kỳ tốt.
Tôi làm việc trong một lĩnh vực liên quan rất sát, và video này đã được đưa ngay vào tài liệu onboarding của nhóm chúng tôi.
Việc khá nhiều mã trực quan hóa đã được đưa lên GitHub cũng rất quan trọng: https://github.com/3b1b/videos/tree/master/_2024/transformers
Cuối cùng tôi cũng hiểu rồi. Không hiểu sao những video khác lại làm cho nó rối đến thế.
Tôi bắt đầu nghĩ rằng năng lực giảng dạy và năng lực nghiên cứu nhìn chung gần như là hai kỹ năng loại trừ lẫn nhau.
Thứ nhất, thuật ngữ tiêu chuẩn không hay. “attention” chỉ vừa đủ trực quan, “self-attention” còn tệ hơn, còn “key” và “value” thì khỏi nói.
Thứ hai, các bài báo cốt lõi như Attention is All You Need, bài báo BERT, v.v. không được viết hay. Không phải để hạ thấp thành tựu của chúng; một bài báo có ảnh hưởng chứa đựng đột phá lớn vẫn có thể giải thích kém, và tôi nghĩ đúng là đã như vậy.
Thứ ba, các kiến trúc này phần lớn được khám phá bằng cách thử đủ thứ rồi xem cái gì dính. Không phải là trước hết có một quá trình suy tư dẫn đến dự đoán rằng kiểu kiến trúc này sẽ hoạt động tốt rồi mới kiểm chứng bằng thực nghiệm; mà nó mang tính thực nghiệm từ đầu đến cuối.
Vì vậy chúng ta chưa hoàn toàn hiểu vì sao nó hoạt động tốt đến thế, mọi lời giải thích đều gần như là hợp lý hóa sau sự kiện, và gần đây cũng có những công trình gợi ý rằng nếu tinh chỉnh đủ nhiều thì các kiến trúc khác cũng có thể hoạt động gần tốt như vậy. Rất khó giải thích rõ điều mà chính mình chưa hiểu hoàn toàn.
Tôi muốn biết có tài liệu tham khảo nào giải thích kiến trúc hiện tại đã tiến hóa như thế nào không. Tôi muốn thấy dòng chảy từ các ý tưởng cốt lõi rất đơn giản đến bài báo nổi tiếng “all you need”.
Nếu không thì rất nhiều thành phần cứ như tự nhiên xuất hiện từ hư không, tính toán thì nhiều mà trực giác lại ít.
Jeremy Howard từng nói trên Twitter rằng ông đã nhiều lần thấy nhiều phiên bản khác nhau của ý tưởng này, điều đó khiến tôi có cảm giác đây là một ý tưởng khá tự nhiên. Nếu thấy ví dụ về cách ý tưởng này xuất hiện ở nơi khác, có lẽ sẽ giúp xây dựng trực giác.
Cách tiếp cận RNN/LSTM này có điểm yếu là biểu diễn kích thước cố định, và khó quyết định nên dùng phần nào của chuỗi đầu vào khi tạo ra một phần cụ thể của đầu ra. Bahdanau và cộng sự đã giải quyết điều đó bằng kiến trúc kết hợp cơ chế attention vào RNN encoder-decoder, cho phép nhìn vào toàn bộ các trạng thái quá khứ của RNN chứ không chỉ trạng thái cuối cùng.
RNN học kém hiệu quả, nên Jakob Uszkoreit muốn tìm cách tận dụng phần cứng song song quy mô lớn tốt hơn, và ông lưu ý rằng ngôn ngữ không chỉ có tính tuần tự mà còn có tính phân cấp. Ông đề xuất một kiến trúc phân tầng, trong đó ở mỗi tầng các token của các chuỗi con được xử lý song song, đồng thời giữ lại attention kiểu Bahdanau để các token tham chiếu lẫn nhau bằng self-attention nhằm dự đoán tầng tiếp theo.
Các bản triển khai ban đầu có hoạt động, nhưng không tốt hơn những cách tiếp cận khác thời đó như mạng tích chập; sau đó Noam Shazeer đã phát triển ý tưởng đó thành một kiến trúc hoạt động tốt hơn nhiều, rồi qua các thử nghiệm loại bỏ những thành phần không cần thiết thì trở thành transformer nguyên bản. Tôi không rõ ai là người nghĩ ra dạng attention dựa trên key trong kiến trúc cuối cùng.
Transformer nguyên bản trong bài báo Attention is All You Need có encoder và decoder tách biệt theo cách tiếp cận RNN trước đó, và cũng được dùng trong các mô hình đầu tiên như BERT của Google. Nhưng với mô hình ngôn ngữ thì điều này không bắt buộc, nên GPT của OpenAI chỉ dùng phần decoder, và hiện nay hầu như mọi người đều đi theo hướng đó. Trong transformer chỉ có decoder, câu đầu vào đi vào tầng thấp nhất, rồi được biến đổi dần qua từng tầng trước khi đi ra ở phía trên. Ở cuối chuỗi đầu vào có gắn một token kết thúc, và token đó được biến đổi thành token tiếp theo của chuỗi đầu ra, tức token cuối cùng.