Bài thứ năm kết thúc ở một dòng rất gọn: thứ model nhận không phải văn bản, mà là input_ids = [8812, 13, 7021, ...]. Bài này trả lời câu hỏi ngay sau đó - một dãy số nguyên như vậy thì tính toán được gì.
Câu trả lời ngắn là: không gì cả, chừng nào chúng còn là số nguyên.
Token ID 8812 không lớn hơn ID 13 theo bất kỳ nghĩa nào có ích. Nó cũng không gần ID 8813 hơn ID 42. Những con số đó là chỗ ngồi được đánh số trong một danh sách mà tokenizer đã chốt từ trước, và thứ tự của danh sách ấy phần lớn là ngẫu nhiên. Cộng, trừ hay so sánh chúng đều vô nghĩa.
Nhưng phép tính bên trong Transformer - nhân ma trận, cộng vector, softmax - lại chỉ làm việc với số thực. Giữa hai thế giới đó phải có một bước chuyển. Bước đó gọi là embedding, và nó là cửa vào duy nhất của model.
Sơ đồ ở đầu bài (Hình 1) là toàn bộ chặng đường: ID thành vector, vector cộng thêm thông tin vị trí, đi qua các block, rồi được chiếu ngược trở lại vocabulary.
01Embedding là gì, nói cho đúng
Định nghĩa ngắn nhất: embedding là một phép tra bảng.
Có một ma trận E với V hàng và d cột. V là kích thước vocabulary - số token mà tokenizer biết. d là số chiều của model. Token ID chính là số hàng.
E có V hàng, d cột
id = 8812 -> E[8812] -> [0.21, -1.04, 0.77, ..., 0.03]
(d số thực)
Thế thôi. Không có phép biến đổi phức tạp nào ở đây. id là chỉ mục, E[id] là hàng thứ id.
Điều làm nó thú vị không nằm ở phép tra, mà ở chỗ E là tham số. Nó được khởi tạo ngẫu nhiên và được cập nhật bởi gradient descent, hệt như mọi ma trận weight khác trong model. Không ai nạp sẵn nghĩa của từ vào đó.
1.1 Ba từ hay bị dùng lẫn
Trước khi đi tiếp, cần tách ba thứ mà tiếng Anh lẫn tiếng Việt đều gọi chung là “embedding”:
| Cách dùng | Nó thật sự là gì |
|---|---|
| Embedding layer | phép tra bảng ở lớp 0, biến ID thành vector |
| Embedding matrix | ma trận E kích thước V × d, là tham số của model |
| Embedding vector | một hàng cụ thể, hoặc - gây nhầm nhất - vector ở lớp cuối |
Ba thứ này liên quan nhau nhưng không đồng nghĩa. Phần lớn hiểu lầm về embedding đến từ việc trộn cái thứ nhất với cái thứ ba, và bài này sẽ quay lại điểm đó nhiều lần.
1.2 Vì sao phải là vector, không phải số
Giả sử ta bướng bỉnh và giữ nguyên số nguyên. Model sẽ phải học một hàm nhận đầu vào là 8812. Nhưng một số nguyên chỉ cho model đúng một chiều thông tin, và chiều đó lại mang thứ tự sai: 8812 nằm giữa 8811 và 8813, trong khi ba token ấy chẳng liên quan gì đến nhau.
Vector d chiều thì khác. Nó cho model d con số để mô tả một token, và quan trọng hơn, nó cho phép hai token gần nhau theo nhiều hướng khác nhau cùng lúc. Hai từ có thể giống nhau về loại từ, khác nhau về sắc thái, lại cùng thuộc một lĩnh vực - và không gian nhiều chiều đủ chỗ để mã hoá đồng thời những quan hệ đó.
Số nguyên là một cái tên. Vector là một vị trí. Model học được từ vị trí, không học được từ tên.
02Vì sao không ai nhân one-hot thật
Trong sách giáo khoa, embedding hay được viết như một phép nhân ma trận. Token được biểu diễn bằng vector one-hot: một vector dài V, toàn số 0, trừ đúng một số 1 ở vị trí id.
V = 8, id = 3
one-hot = [0, 0, 0, 1, 0, 0, 0, 0]
Nhân vector đó với E:
(1 × V) · (V × d) -> (1 × d)
Kết quả là gì? Mỗi hàng của E được nhân với phần tử tương ứng của one-hot. Bảy hàng nhân 0 và biến mất. Một hàng nhân 1 và sống sót. Kết quả đúng bằng E[3].
Vậy nên hai cách nói không mâu thuẫn. Nhưng không framework nào nhân one-hot thật, vì lý do rất thực dụng.
Với V = 128.000 và một sequence 8.192 token, riêng việc dựng ma trận one-hot đã cần hơn một tỷ số. Toàn bộ chúng, trừ 8.192 số, đều bằng 0. Phép nhân sau đó là hàng tỷ phép nhân với 0.
Phép gather làm đúng việc cần làm: đọc d số ở đúng hàng cần đọc.
2.1 Hệ quả thật sự nằm ở gradient
Điểm này quan trọng hơn chuyện tiết kiệm phép tính, và nó sẽ quay lại ở phần 09 và phần 14.
Vì embedding là phép chọn hàng, gradient cũng chỉ chảy ngược về những hàng đã được chọn. Một token không xuất hiện trong batch thì hàng của nó nhận gradient bằng 0, và giá trị không đổi một chút nào.
batch chạm 4.000 hàng khác nhau
E có 128.000 hàng
-> 124.000 hàng đứng yên trong bước cập nhật này
Đây gọi là sparse gradient, và nó là lý do các framework có cài đặt riêng cho embedding thay vì dùng chung đường với các layer dày đặc.
03Bảng embedding lớn đến mức nào
Hai con số quyết định toàn bộ bảng, và cả hai đều đã bị chốt trước khi training bắt đầu.
V đến từ tokenizer. Nếu tokenizer có 128.000 token, bảng phải có đúng 128.000 hàng. d là chiều của residual stream - con số dùng chung cho toàn bộ model, sẽ nói kỹ ở phần 08.
Nhân hai con số lại:
V = 128.000
d = 4.096
V × d = 524.288.000 tham số
Hơn 500 triệu tham số, chỉ riêng cho bảng vào.
3.1 Tỷ lệ thay đổi theo kích thước model
Con số tuyệt đối trên là cố định, nhưng ý nghĩa của nó phụ thuộc phần còn lại của model.
| Kích thước model | Embedding chiếm khoảng |
|---|---|
| vài trăm triệu tham số | phần rất lớn, đôi khi quá nửa |
| vài tỷ tham số | một phần đáng kể |
| hàng chục tỷ trở lên | tỷ lệ nhỏ, vì layer áp đảo |
Ở model nhỏ, bảng embedding có thể là thành phần nặng nhất. Đây là một trong những lý do các model nhỏ hay dùng vocabulary gọn hơn, hoặc buộc chung bảng vào với bảng ra - kỹ thuật ở phần 11.
Ở model rất lớn, V × d gần như không đáng kể so với hàng chục layer, và cân nhắc lại đi theo hướng khác.
3.2 Vì sao đổi tokenizer là chuyện lớn
Vì V xác định số hàng, đổi tokenizer nghĩa là đổi toàn bộ ý nghĩa của từng hàng. Hàng thứ 8812 của tokenizer cũ và hàng thứ 8812 của tokenizer mới không liên quan gì đến nhau.
Không có cách nào chỉ thay tokenizer mà giữ nguyên bảng embedding cũ. Đó là lý do bài Tokenization gọi tokenizer là quyết định gần như không thể đảo ngược.
04Khoảng cách giữa hai vector mã hoá điều gì
Đây là phần dễ bị lãng mạn hoá nhất, nên hãy nói thẳng: không gian embedding học từ phân bố, không học từ định nghĩa.
Không ai nói cho model biết mèo là động vật. Model chỉ thấy token mèo xuất hiện cạnh những token nào, trong hàng nghìn tỷ vị trí. Gradient kéo những token dùng được ở cùng chỗ lại gần nhau. Cấu trúc trong không gian là sản phẩm của việc đó.
4.1 Vì sao dùng cosine
Cách đo phổ biến nhất là cosine similarity - cosine của góc giữa hai vector:
cos(a, b) = (a · b) / (|a| × |b|)
Nó chỉ xét hướng và bỏ hoàn toàn độ dài. Lý do rất thực tế: độ dài của một vector embedding tương quan mạnh với tần suất của token đó trong corpus, chứ không với ý nghĩa. Token phổ biến được cập nhật nhiều lần nên vector của chúng có xu hướng dài hơn.
Nếu dùng khoảng cách Euclid thẳng, ta sẽ vô tình so sánh tần suất thay vì so sánh nội dung. Bỏ độ dài đi giúp token hiếm và token phổ biến còn đặt cạnh nhau được.
4.2 Hai chỗ trực giác đi sai
Từ trái nghĩa thường rất gần nhau. nóng và lạnh xuất hiện trong gần như cùng một tập ngữ cảnh: cùng đi với nước, thời tiết, quá, hơi. Xét theo phân bố, chúng thay thế được cho nhau, nên vector của chúng gần nhau. Không gian mã hoá “dùng được ở cùng chỗ”, và điều đó không đồng nghĩa với “nghĩa giống nhau”.
Phép loại suy không chắc chắn như tiếng đồn. Ví dụ kinh điển vua - đàn ông + đàn bà ≈ nữ hoàng là thật, nhưng nó phụ thuộc nhiều vào cách chuẩn hoá, cách đo và việc có loại bỏ ba từ gốc khỏi kết quả hay không. Nó là một tính chất thú vị, không phải một phép toán đáng tin.
Và cũng đừng tìm trục nào có tên. Không có chiều thứ 317 mang nghĩa “mức độ trang trọng”. Thông tin nằm rải trên nhiều chiều cùng lúc.
05Embedding tĩnh và embedding theo ngữ cảnh
Đây là chỗ phân biệt quan trọng nhất của cả bài.
Trước Transformer, word2vec và GloVe cho mỗi từ đúng một vector, cố định sau khi train xong. Tra bảng là hết. Từ đá trong hòn đá, đá bóng và nước đá nhận cùng một vector.
Trong một LLM, câu chuyện khác. E[id] vẫn là một vector tĩnh - đó là điểm xuất phát. Nhưng ngay khi vector đó đi qua block attention đầu tiên, nó bắt đầu trộn thông tin từ các vị trí xung quanh. Sau vài chục layer, vector ở vị trí đó đã mang dấu vết của toàn bộ ngữ cảnh đứng trước.
Câu 1: "hòn đá nặng" -> vector tại vị trí "đá" = v1
Câu 2: "đá bóng rất hay" -> vector tại vị trí "đá" = v2
Câu 3: "cho thêm nước đá" -> vector tại vị trí "đá" = v3
v1 ≠ v2 ≠ v3, dù cả ba đều bắt đầu từ cùng E[id]
5.1 Vì sao điều này quan trọng
Embedding tĩnh phải nhét mọi nghĩa của một từ vào một điểm duy nhất. Kết quả là một vector trung bình, không đúng hẳn với nghĩa nào. Với từ đa nghĩa, đó là giới hạn không vượt qua được bằng cách thêm dữ liệu.
Embedding theo ngữ cảnh không có vấn đề đó, vì nó không cố mô tả một từ - nó mô tả một vị trí trong một câu cụ thể.
5.2 Nhưng bảng E không biến mất
Một nhầm lẫn hay gặp là kết luận rằng LLM “không có embedding tĩnh”. Nó có. Bảng E vẫn nằm đó, vẫn là lớp 0, và mọi vector ngữ cảnh đều khởi đầu từ đúng một hàng của nó.
Cái thay đổi là: hàng đó không còn là câu trả lời cuối cùng, nó là điều kiện ban đầu.
06Vì sao model phải được cho biết vị trí
Có một tính chất của self-attention dễ bị bỏ qua: nó không biết thứ tự.
Attention tính điểm giữa từng cặp query và key. Phép tính đó không tham chiếu đến chỉ số vị trí ở bất kỳ đâu. Nếu ta hoán vị các token đầu vào, đầu ra cũng chỉ hoán vị theo đúng cách đó - giá trị không đổi. Thuật ngữ cho tính chất này là permutation equivariant.
Cụ thể, nếu chỉ có embedding token và không có gì khác:
"mèo đuổi chuột" -> tập {mèo, đuổi, chuột}
"chuột đuổi mèo" -> tập {chuột, đuổi, mèo}
Hai tập giống hệt nhau.
Model sẽ không có cách nào phân biệt ai đuổi ai. Đây không phải lỗi cài đặt mà là tính chất toán học của phép tính.
RNN không gặp vấn đề này vì nó đọc tuần tự - thứ tự nằm sẵn trong cách nó chạy. Transformer đọc mọi vị trí cùng lúc, và đó chính là lý do nó nhanh. Cái giá phải trả là thứ tự phải được cộng vào một cách tường minh.
6.1 Cái thật sự cần là khoảng cách
Một nhận xét dẫn tới toàn bộ thiết kế hiện đại: quan hệ giữa hai token phụ thuộc vào việc chúng cách nhau bao xa, chứ không phải vào chỉ số tuyệt đối của chúng.
Hai token liền kề có quan hệ chặt, dù chúng đứng ở vị trí 5 và 6 hay 5.000 và 5.001. Mã hoá được ý đó thì model tổng quát hoá tốt hơn nhiều.
07Bốn cách đưa vị trí vào model
Các cách mã hoá vị trí chia thành hai họ, khác nhau ở chỗ chúng can thiệp.
Sinusoidal là cách của Transformer gốc năm 2017. Mỗi vị trí có một vector tính bằng các hàm sin và cos ở nhiều tần số khác nhau, cộng thẳng vào embedding token. Không có tham số nào phải học.
Learned là cách của GPT-2 và nhiều model sau đó. Đơn giản hơn nữa: có một bảng thứ hai, mỗi vị trí một hàng, học y như bảng token.
đầu vào lớp 0 = E[token_id] + P[position]
Cách này dễ hiểu và chạy tốt, nhưng có một hạn chế cứng. Nếu bảng P chỉ có 1.024 hàng, vị trí 1.025 đơn giản là không tồn tại. Đó là lý do context window của các model đời đó là một con số chốt chặt.
RoPE - Rotary Position Embedding - đổi cách tiếp cận. Thay vì cộng gì vào vector đầu vào, nó xoay query và key một góc tỷ lệ với vị trí, ngay bên trong phép tính attention. Điều hay là sau phép xoay, tích vô hướng giữa query ở vị trí m và key ở vị trí n chỉ còn phụ thuộc vào hiệu m - n.
Nói cách khác, RoPE mã hoá đúng thứ ta cần: khoảng cách, không phải chỉ số.
ALiBi đi theo cùng tinh thần nhưng thô hơn: cộng thẳng một khoản phạt tỷ lệ với khoảng cách vào điểm attention, khiến token càng xa càng bị giảm trọng số.
7.1 Vì sao RoPE thắng
Hầu hết model mở hiện nay dùng RoPE. Lý do là nó xử lý câu dài tốt hơn hẳn: vì công thức chỉ phụ thuộc khoảng cách, model không gặp “vị trí chưa từng thấy” theo cách mà learned gặp.
Cần nói rõ một điều hay bị phóng đại: RoPE không cho phép mở rộng context vô hạn miễn phí. Vượt xa độ dài đã train, chất lượng vẫn giảm, và các kỹ thuật nới như điều chỉnh tần số hay fine-tune thêm trên câu dài vẫn cần thiết. RoPE làm cho việc nới khả thi, không làm cho nó tự động.
08Residual stream: chỗ vector thật sự sống
Để hiểu vì sao d xuất hiện ở khắp nơi, cần một mô hình tư duy về cách vector di chuyển qua model.
Hãy hình dung mỗi vị trí token giữ đúng một vector d chiều, chạy suốt từ lớp 0 đến lớp cuối. Vector đó gọi là residual stream.
Điểm mấu chốt: các block không thay thế vector đó. Chúng đọc nó, tính ra một phần đóng góp, rồi cộng phần đó vào:
x0 = E[id] + vị trí
x1 = x0 + attention(x0)
x2 = x1 + mlp(x1)
x3 = x2 + attention(x2)
...
Đây là ý nghĩa của chữ “residual” trong residual connection. Hệ quả trực tiếp là embedding ban đầu không biến mất - nó vẫn còn trong tổng, chỉ là bị phủ thêm nhiều lớp thông tin khác.
8.1 Vì sao d có mặt ở mọi nơi
Vì mọi block đều nhận d chiều và trả về d chiều, d trở thành ràng buộc chung:
- bảng
Ephải có đúngdcột, nếu không thì không cộng vào được; - mọi attention head cộng lại phải cho ra
dchiều; - MLP nở ra rồi phải co lại đúng
d; - bảng ra phải nhận
dchiều.
Đổi d nghĩa là đổi gần như toàn bộ hình dạng của model.
8.2 Vector ở lớp cuối không phải embedding của token đó
Đây là chỗ cần nói thật rõ, vì nó là nguồn gốc của rất nhiều nhầm lẫn.
Vector ở vị trí t tại lớp cuối không mô tả token đứng ở vị trí t. Nó đã hấp thụ toàn bộ ngữ cảnh đứng trước, và nó được huấn luyện để phục vụ đúng một việc: đoán token tiếp theo.
vector tại vị trí t, lớp cuối
-> không phải "token t là gì"
-> mà là "token t+1 nên là gì"
Lấy vector đó ra và đọc như embedding của token hiện tại là hiểu sai mục đích của nó.
09Bảng embedding được học như thế nào
Không có thuật toán riêng nào cho embedding. Nó nhận gradient từ đúng hàm loss next-token đã mô tả ở bài Dataset, qua đúng cơ chế backpropagation như mọi weight khác.
Điều đáng chú ý là cấu trúc ngữ nghĩa là sản phẩm phụ. Không có bước nào trong training nói “hãy đặt các từ cùng chủ đề gần nhau”. Chỉ có một sức ép duy nhất: đoán đúng token kế tiếp. Hoá ra cách hiệu quả nhất để làm việc đó là sắp xếp các token dùng được ở cùng chỗ vào cùng vùng không gian - nên model tự làm vậy.
9.1 Tần suất quyết định chất lượng
Vì gradient thưa, số lần một hàng được cập nhật bằng đúng số lần token đó xuất hiện trong training.
token phổ biến ("của", "là", "the")
-> chạm hàng triệu lần
-> vector được nắn rất kỹ
token hiếm
-> chạm vài lần
-> vector còn gần giá trị khởi tạo
Đây là lý do trực tiếp dẫn tới hiện tượng ở phần 14.
10Unembedding: đường quay về vocabulary
Model kết thúc với một vector d chiều. Nhưng thứ ta cần là một token. Phải có bước đi ngược.
Bước đó là unembedding: nhân vector d chiều với một ma trận d × V, cho ra V số - mỗi token một điểm. Những điểm này gọi là logits.
vector (1 × d) · ma trận ra (d × V) -> logits (1 × V)
Nhìn kỹ hơn: điểm của token thứ i chính là tích vô hướng giữa vector cuối và hàng thứ i của ma trận ra. Nghĩa là hình học ở đây có ý nghĩa rất trực tiếp - vector cuối càng cùng hướng với một hàng thì token đó điểm càng cao.
Sinh văn bản, xét cho cùng, là bài toán tìm hàng gần nhất theo hướng.
10.1 Softmax và phần nằm ngoài model
Softmax biến V điểm số thành một phân bố xác suất cộng lại bằng 1. Sau đó mới đến bước chọn token.
Điều đáng nhớ: model chỉ trả về logits. Nó không tự chọn. Temperature, top-k, top-p đều thao tác trên phân bố đã có, và đổi chúng không đổi một tham số nào của model. Đây là ranh giới giữa “model” và “cách ta dùng model”, và bài Transformer từ A đến Z đã đi qua phần sampling này kỹ hơn.
11Weight tying: dùng chung một ma trận cho cả hai đầu
Để ý hình dạng của hai bảng:
bảng vào E : V × d
bảng ra U : d × V
Chúng là chuyển vị của nhau về kích thước. Nên có một câu hỏi tự nhiên: dùng chung một ma trận được không?
Được, và kỹ thuật đó gọi là weight tying. Nó tiết kiệm đúng V × d tham số - với con số ở phần 03 là hơn 500 triệu.
11.1 Vì sao nó hợp lý về mặt trực giác
Có một lập luận đẹp cho việc buộc chung. Nếu hàng của E mô tả token mèo, và logit của mèo là tích vô hướng giữa vector cuối với hàng tương ứng của U, thì việc dùng chung một hàng nghĩa là: model sinh ra token mèo khi vector cuối trỏ về đúng hướng mà mèo đại diện.
Điều đó nghe rất tự nhiên, và trong thực tế weight tying hoạt động tốt, đặc biệt ở model nhỏ.
11.2 Nhưng nó không miễn phí
Cái giá là hai vai trò khác nhau bị ép dùng chung một biểu diễn:
- hàng của
Etrả lời: token này trông như thế nào khi đi vào model; - hàng của
Utrả lời: khi nào thì nên sinh ra token này.
Hai câu hỏi đó liên quan nhưng không đồng nhất. Ở model đủ lớn, khi V × d không còn là khoản đáng kể, nhiều recipe chọn tách riêng trở lại để mỗi ma trận tự do làm việc của nó.
12Chọn d bằng bao nhiêu
d không phải một con số tuỳ ý. Nó bị ràng buộc từ nhiều phía cùng lúc.
| Ràng buộc | Vì sao |
|---|---|
| Chia hết cho số attention head | mỗi head lấy d / n_heads chiều |
| Đủ lớn để chứa thông tin | residual stream là băng thông duy nhất |
| Không quá lớn | chi phí mọi layer tăng theo d |
| Hợp với phần cứng | bội của 64 hoặc 128 chạy nhanh hơn |
Vì vậy các giá trị thực tế gần như luôn là những con số tròn: 768, 1.024, 2.048, 4.096, 8.192.
Có một cách nghĩ hữu ích: d là băng thông của model. Mọi thứ mà một vị trí cần mang theo - token gốc là gì, nó đứng ở đâu, ngữ cảnh nói gì, model đang định làm gì - đều phải chen vào cùng d con số đó. Tăng d cho model nhiều chỗ hơn để giữ thông tin, nhưng làm mọi phép tính đắt lên.
Và như Chinchilla đã chỉ ra ở khía cạnh khác, tăng kích thước mà không tăng dữ liệu tương ứng thì phần capacity thêm vào không được dùng hết.
13Embedding của LLM khác embedding cho retrieval
Khi làm RAG hay semantic search, ta gặp một thứ cũng tên là embedding: đưa một câu vào model, nhận về một vector, rồi cất vào vector database. Đây không phải cùng một thứ với embedding bên trong LLM.
Ba khác biệt đáng kể:
Đơn vị khác nhau. LLM cho một vector trên mỗi vị trí token. Embedding model cho một vector trên cả đoạn. Muốn đi từ token sang đoạn thì phải gộp lại, và cách gộp - lấy trung bình, lấy token cuối, dùng một token đặc biệt - là một lựa chọn thiết kế có ảnh hưởng thật.
Mục tiêu huấn luyện khác nhau. LLM tối ưu cho next-token prediction. Embedding model thường được train bằng mục tiêu contrastive: kéo cặp câu liên quan lại gần và đẩy cặp không liên quan ra xa. Hai sức ép đó nắn không gian theo hai cách khác nhau.
Vai trò khác nhau. Trong LLM, embedding là trạng thái trung gian của một phép tính lớn hơn. Với retrieval, vector chính là sản phẩm.
Đây là lý do lấy hidden state của một LLM đem đi làm semantic search thường cho kết quả kém hơn một embedding model được train riêng, dù LLM lớn hơn nhiều lần. Bài RAG không cứu được dữ liệu bẩn nói thêm về chỗ này ở tầng hệ thống.
14Những token mà vector của chúng chưa từng được học
Ghép hai điều đã nói - gradient thưa ở phần 09 và tokenizer được train riêng ở phần 03 - ta được một hệ quả kỳ lạ nhưng có thật.
Tokenizer thường được train trên một corpus khác với corpus pretraining. Nó có thể sinh ra token cho những chuỗi ký tự về sau gần như không gặp lại - một tên người dùng trên diễn đàn, một chuỗi rác trong dữ liệu crawl, một mẩu mã bị lặp.
Những token đó tồn tại trong vocabulary, nên chúng có hàng riêng trong E. Nhưng vì gần như không bao giờ xuất hiện trong training, hàng của chúng giữ nguyên giá trị khởi tạo ngẫu nhiên suốt cả run.
Kết quả là những vector nhiễu nằm lệch hẳn khỏi mọi vùng có nghĩa. Khi model gặp chúng lúc inference, hành vi trở nên khó đoán - model có thể lảng tránh, lặp lại, hoặc trả lời hoàn toàn lạc đề. Cộng đồng gọi chúng là glitch token, và ví dụ nổi tiếng nhất là chuỗi SolidGoldMagikarp tìm thấy trong vocabulary của GPT-2 và GPT-3.
Cách xử lý không nằm ở model mà ở dữ liệu và tokenizer: cắt bớt phần đuôi vocabulary, train tokenizer trên đúng corpus sẽ dùng để pretrain, hoặc kiểm tra tần suất từng token trước khi chốt.
Một token có mặt trong vocabulary không có nghĩa là model đã học được gì về nó.
15Đa ngôn ngữ và đa phương thức
Hai mở rộng đáng nói, vì cả hai đều là hệ quả trực tiếp của những gì ở trên.
15.1 Nhiều ngôn ngữ, một không gian
Model đa ngôn ngữ dùng chung một bảng E cho mọi ngôn ngữ. Không có bảng riêng cho tiếng Việt và bảng riêng cho tiếng Anh.
Điều thú vị là các khái niệm tương đương giữa các ngôn ngữ có xu hướng nằm gần nhau trong không gian, dù không ai ép chúng phải vậy. Lý do vẫn là phân bố: dog và chó xuất hiện trong những ngữ cảnh có cấu trúc tương tự, nên gradient nắn chúng về những vùng tương tự.
Nhưng sự chia sẻ đó không đều. Ngôn ngữ chiếm tỷ lệ nhỏ trong corpus sẽ có ít token riêng hơn, tần suất mỗi token thấp hơn, và vì phần 09, vector kém được nắn hơn. Đây là chỗ vấn đề data mixture quay lại dưới dạng chất lượng biểu diễn.
15.2 Ảnh không có ID để tra
Model đa phương thức không thể tra bảng cho ảnh - ảnh không có token ID. Thay vào đó, một encoder biến mảnh ảnh thành vector d chiều trực tiếp.
Nhưng điểm mấu chốt là những vector đó được đưa vào cùng residual stream, cùng số chiều d, xen kẽ với vector của token văn bản. Từ góc nhìn của các block phía sau, không có gì phân biệt “vector đến từ chữ” và “vector đến từ ảnh”.
[vector ảnh] [vector ảnh] [E[id]] [E[id]] [E[id]] ...
cùng d chiều, cùng một residual stream
Cách một model xử lý được nhiều phương thức, vì vậy, không phải là có nhiều model bên trong. Nó chỉ là nhiều cách khác nhau để tạo ra vector d chiều cho một băng thông duy nhất.
16Những hiểu lầm phổ biến
| Hiểu lầm | Thực tế |
|---|---|
| “Embedding lưu nghĩa của từ” | nó lưu vị trí học được từ phân bố đồng hiện; nghĩa là cách ta diễn giải vị trí đó |
| “Vector gần nhau thì nghĩa giống nhau” | gần nhau nghĩa là dùng được ở cùng chỗ, nên từ trái nghĩa thường rất gần nhau |
| “Embedding của LLM dùng được cho semantic search” | khác đơn vị và khác mục tiêu train; model chuyên cho retrieval thường tốt hơn |
| “Vector ở lớp cuối là embedding của token đó” | nó mang cả ngữ cảnh và được train để đoán token kế tiếp, không để mô tả token hiện tại |
| “One-hot nhân ma trận là cách embedding chạy” | về toán thì đúng, nhưng cài đặt là gather; khác nhau hàng tỷ phép tính |
| “Model biết thứ tự từ vì nó đọc từ trái sang phải” | self-attention không có thứ tự; vị trí phải được cộng vào tường minh |
| “RoPE cho context dài vô hạn” | nó ngoại suy tốt hơn learned, nhưng vượt xa độ dài train vẫn cần hiệu chỉnh |
| “Mỗi chiều embedding có một ý nghĩa” | thông tin nằm rải trên nhiều chiều; không có trục nào mang tên một khái niệm |
| “Token nào trong vocabulary cũng được học như nhau” | gradient thưa nên token hiếm có thể giữ nguyên vector khởi tạo |
| “Buộc chung bảng vào và bảng ra luôn tốt hơn” | tiết kiệm tham số nhưng ép hai vai trò khác nhau dùng chung biểu diễn |
Embedding là chỗ ngôn ngữ trở thành hình học
Có một khoảnh khắc chuyển pha trong toàn bộ pipeline, và nó nằm đúng ở đây.
Trước embedding, mọi thứ còn là ký hiệu: ký tự, token, số hiệu. Ta có thể so sánh chúng bằng nhau hay khác nhau, nhưng không thể hỏi “cái này gần cái kia bao nhiêu”. Sau embedding, mọi thứ là điểm trong một không gian có khoảng cách, có hướng, có phép cộng. Từ chỗ này trở đi, câu hỏi về ngôn ngữ trở thành câu hỏi về hình học - và hình học thì tính được bằng gradient descent.
Những gì nên mang theo:
- embedding là phép tra bảng, và bảng đó là tham số học được, không phải từ điển;
- cấu trúc trong không gian đến từ phân bố đồng hiện, không từ định nghĩa;
- gần nhau nghĩa là thay thế được cho nhau, nên trái nghĩa thường rất gần;
- vị trí không tự có, nó phải được cộng vào, và cái đáng mã hoá là khoảng cách;
- residual stream là băng thông
dchiều dùng chung, nêndràng buộc cả model; - vector ở lớp cuối phục vụ việc đoán token kế tiếp, không mô tả token hiện tại;
- gradient của embedding rất thưa, nên tần suất quyết định chất lượng vector;
- embedding trong LLM và embedding cho retrieval là hai thứ khác nhau.
Và thứ mà một token đã đi qua trong bài này:
"đá" -> id 7021 -> E[7021] -> cộng vị trí
-> residual stream qua N block
-> vector d chiều mang cả ngữ cảnh
-> logits trên V token
Ở bài tiếp theo, ta dừng lại đúng ở đoạn giữa - phần mà bài này cố tình gọi gọn là “qua các block”. Đó là chỗ attention quyết định mỗi vị trí được đọc những vị trí nào, và vì sao cơ chế đó lại là thứ làm Transformer khác hẳn mọi kiến trúc trước nó.
Tài liệu tham khảo
- Stanford CS336 — Language Modeling from Scratch
- Vaswani et al. — Attention Is All You Need
- Mikolov et al. — Efficient Estimation of Word Representations in Vector Space
- Pennington et al. — GloVe: Global Vectors for Word Representation
- Peters et al. — Deep Contextualized Word Representations
- Press and Wolf — Using the Output Embedding to Improve Language Models
- Su et al. — RoFormer: Enhanced Transformer with Rotary Position Embedding
- Press et al. — Train Short, Test Long: Attention with Linear Biases
- Elhage et al. — A Mathematical Framework for Transformer Circuits
- Hoffmann et al. — Training Compute-Optimal Large Language Models
- Rumbelow and Watkins — SolidGoldMagikarp: anomalous tokens
- Ethayarajh — How Contextual are Contextualized Word Representations?