BPE, WordPiece, SentencePiece — Cách AI 'đọc' text
Tokenization là gì? Giải thích BPE, WordPiece, SentencePiece — cách AI chuyển text thành số để xử lý, từ cơ chế nén dữ liệu đến ứng dụng trong ChatGPT và BERT.
AI không đọc được chữ. Nó chỉ nhận diện số. Vậy làm sao để một đoạn text như "tokenization" trở thành dãy số mà model có thể tính toán? Câu trả lời không đơn giản là "cắt ra từng chữ" hay "từng từ". Đó là một bài toán nén dữ liệu tinh vi — nơi mà "unhappiness" có thể bị tách thành ["un", "happiness"], và "ChatGPT" trở thành ["Chat", "G", "PT"].
Vấn đề
Neural network không thể nhận input là string "Hello world". Nó cần vector số. Vậy làm sao chuyển text thành số?
Cách đơn giản nhất là character-level: mỗi ký tự (a, b, c, dấu cách) là một token. Nhưng với đoạn văn dài, sequence sẽ trở nên cực kỳ dài (một câu 10 từ tiếng Anh thành 50+ ký tự), và model sẽ mất quá nhiều bước để nắm được ý nghĩa từ cấp độ cao hơn.
Cách ngược lại là word-level: mỗi từ là một token. Nhưng ngôn ngữ có hàng trăm nghìn từ, và vấn đề OOV (Out-Of-Vocabulary) sẽ giết chết model — làm sao xử lý từ mới như "Covid-19", tên riêng lạ, typo, hay từ đa ngữ (tiếng Nhật không có dấu cách)?
Cần một giải pháp ở giữa: subword tokenization — tách text thành các đơn vị nhỏ hơn từ nhưng lớn hơn chữ cái, sao cho tần suất xuất hiện cân bằng và không bao giờ gặp từ lạ.
Ý tưởng cốt lõi
Tokenization hiện đại không phải là "cắt chuỗi" theo quy tắc ngữ pháp. Nó là thuật toán nén dữ liệu học từ corpus — tìm ra cách biểu diễn ngắn nhất có thể cho toàn bộ ngôn ngữ.
BPE (Byte Pair Encoding) — thuật toán được GPT-2, GPT-3, ChatGPT sử dụng — hoạt động như sau:
- Bắt đầu với vocabulary là tập hợp tất cả ký tự đơn lẻ (a-z, dấu cách, dấu câu).
- Tìm cặp ký tự xuất hiện liên tiếp nhiều nhất trong training data (ví dụ: "t" và "h" trong "the", "this", "that").
- Merge cặp đó thành một token mới "th", thêm vào vocabulary.
- Lặp lại hàng nghìn lần cho đến khi vocabulary đạt kích thước mong muốn (thường 32k–100k tokens).
Kết quả: những từ phổ biến như "the", "ing", "tion" trở thành single token. Những từ hiếm như "tokenization" bị tách thành ["token", "ization"] — vẫn giữ được ý nghĩa cấu trúc ("ize" là hậu tố), và quan trọng nhất: không bao giờ gặp từ lạ, vì bất kỳ từ nào cũng có thể cấu thành từ ký tự gốc.
WordPiece (dùng trong BERT) thay đổi tiêu chí merge: thay vì tìm cặp tần suất cao nhất, nó chọn cặp làm tăng likelihood của training data nhiều nhất. Khác biệt tinh tế nhưng tạo ra vocabulary tối ưu hơn cho masked language modeling.
SentencePiece (dùng trong T5, XLM-R, Llama 3) đi xa hơn: nó xử lý raw text hoàn toàn, kể cả dấu cách. Nó coi dấu cách như một ký tự đặc biệt (thường là "▁"), cho phép tokenize tiếng Trung, Nhật, Thái (không có dấu cách tự nhiên) mà không cần preprocessor ngôn ngữ học phức tạp.
Đây là "aha moment": Tokenization không chỉ là cắt text — nó là cách ta nén tri thức ngôn ngữ vào vocabulary, để model chỉ cần học cách kết hợp ~50k "lego blocks" thay vì học hàng triệu từ cố định.
Tại sao nó hoạt động
BPE hoạt động tốt vì nó khai thác Zipf's law: một số ít pattern (nguyên âm, phụ âm thường, hậu tố phổ biến) chiếm đa số text. Bằng cách merge các pattern này trước, ta tạo ra hệ thống phân cấp:
- Level 0: Ký tự (a, b, c...)
- Level 1: Âm tiết thường (th, ing, un...)
- Level 2: Từ gốc (token, happy...)
- Level 3: Từ hiếm (tokenization = token + ization)
Ví dụ cụ thể với từ "unhappiness":
- Word-level: ["unhappiness"] — từ hiếm, có thể OOV
- Character-level: ["u", "n", "h", "a", "p", "p", "i", "n", "e", "s", "s"] — dài, mất ngữ nghĩa
- BPE subword: ["un", "happiness"] — tái sử dụng prefix "un-" (phủ định) và root "happiness"
Về mặt toán học, BPE tối thiểu hóa sequence length trong khi đảm bảo coverage 100%. Dưới đây là pseudo-code của thuật toán:
# Bắt đầu với corpus và vocab = tất cả ký tự đơn
corpus = {"l o w": 5, "l o w e r": 2, "w i d e s t": 3, ...}
vocab = {"l", "o", "w", "e", "r", "i", "d", "s", "t", ...}
# Merge 10,000 lần hoặc đến khi vocab đủ lớn
while len(vocab) < target_size:
# Tìm cặp liên tiếp phổ biến nhất
pairs = get_stats(corpus)
best_pair = max(pairs, key=pairs.get) # ví dụ: ("e", "r")
# Merge thành token mới
vocab.add("er")
corpus = merge_vocab(best_pair, corpus)Tại sao không dùng từ điển có sẵn? Vì tokenization phải lossless và reversible. Bất kỳ chuỗi byte nào cũng phải chuyển đổi được thành dãy token, và từ dãy token phải reconstruct lại chuỗi byte gốc. BPE đảm bảo điều này bằng cách bắt đầu từ byte gốc và chỉ merge, không loại bỏ.
Ý nghĩa thực tế
Impact thực tế:
- Xử lý ngôn ngữ hiếm: Tiếng Việt với dấu thanh điệu, tiếng Đức với compound words (Donaudampfschifffahrtsgesellschaftskapitänsmütze), tên người Ả Rập — tất cả đều được xử lý bằng cách tách thành subwords đã biết.
- Chống lại typo: "teh" (typo của "the") sẽ thành ["te", "h"] hoặc ["t", "eh"], vẫn gần với embedding của "the" hơn là một OOV hoàn toàn.
- Code và số: GPT-4 tokenize số như "1234" thành ["12", "34"] hoặc ["1", "234"] tùy vào tần suất trong code repository — giúp model nắm pattern số học tốt hơn.
So sánh các phương pháp:
| Algorithm | Dùng trong | Cơ chế merge | Đặc điểm nổi bật | Nhược điểm |
|---|---|---|---|---|
| BPE | GPT-2/3/4, Llama | Frequency-based (cặp phổ biến nhất) | Đơn giản, hiệu quả, dễ implement | Không xử lý đa ngữ tốt (cần pre-tokenizer) |
| WordPiece | BERT, DistilBERT | Likelihood-based (tăng prob data) | Tốt cho Masked LM | Chậm hơn BPE, phụ thuộc vào modeling objective |
| SentencePiece | T5, XLM-R, Llama 3 | Unigram/BPE language-agnostic | Xử lý raw text, không cần pre-tokenizer, tốt cho CJK | Phức tạp hơn, cần tune hyperparameters |
Các giới hạn:
- Language disparity: Tiếng Anh cần ~1.3 tokens/word, tiếng Việt ~2-3 tokens/word, tiếng Trung ~3-4 tokens/ký tự. Điều này làm tăng cost cho ngôn ngữ không phải English khi dùng API tính theo token.
- Ambiguity: Cùng một từ có thể bị tách khác nhau tùy context ("New York" là ["New", "York"] hay single token?), gây khó khăn cho interpretability.
- Attack surface: Adversarial attacks có thể dùng "token smuggling" — tách từ toxic thành subwords vô hại để bypass safety filters.
Đào sâu hơn
Paper gốc:
- Neural Machine Translation of Rare Words with Subword Units — BPE cho NMT (Sennrich et al., 2016)
- Google's Neural Machine Translation System — WordPiece (Schuster & Nakajima, 2012/2016)
- SentencePiece: A simple and language independent subword tokenizer and detokenizer — Kudo & Richardson, 2018
Bài liên quan TroiSinh:
Cùng cụm (sequence-modeling):
- Word2Vec & GloVe — Khi từ ngữ trở thành vector — Sau khi có token ID, làm sao thành vector số?
- Transformer — Bỏ hết recurrence, chỉ giữ Attention — Kiến trúc sử dụng tokenization để xử lý sequence
- Self-Attention — Mỗi token tự hỏi "ai quan trọng với tôi?" — Cách các token tương tác sau khi được tạo ra
- Positional Encoding — Vì sao cần thêm thông tin vị trí sau khi tokenize
Đọc tiếp:
- Flash Attention — Cách tối ưu attention trên các token đã được tạo (Level 1)
- Mamba & SSMs — Kiến trúc mới không dùng attention nhưng vẫn cần tokenization (Level 2)
Mở rộng:
- HuggingFace Tokenizers — Thư viện Rust-based để train tokenizer custom
- Tiktoken — BPE tokenizer của OpenAI, fast and deterministic
Word2Vec & GloVe — Khi từ ngữ trở thành vector
Word embedding biến từ ngữ thành vector số thực, nơi 'king - man + woman ≈ queen'. Hiểu bản chất của Word2Vec và GloVe — nền tảng cho mọi model ngôn ngữ hiện đại.
Transformer — Bỏ hết recurrence, chỉ giữ Attention
Từ RNN tuần tự chậm chạp đến kiến trúc song song nhờ Attention mechanism. Hiểu vì sao GPT, Claude và mọi LLM hiện đại đều dựa trên Transformer.