Mục lục
- Mục tiêu bài học
- Vocabulary là gì — tập token cố định
- Mapping bi-directional: vocab và inv_vocab
- Vocab size phổ biến 2024-2026
- Trade-off vocab lớn vs nhỏ
- Embedding table — chiếm phần lớn param của smaller model
- Output head (LM head) và tied weight
- Code Python — inspect vocab GPT-2
- encode và decode
- Special token và add token tùy chỉnh
- Padding, truncation và attention_mask
- Batch encoding — trả về tensor PyTorch
- Inspect raw vocab file của tokenizer
- OOV (Out-of-Vocabulary)
- Token frequency và anomalous token
- Vocab pruning và domain-specific tokenizer
- Multilingual vocab và tokenizer cho code
- Bài tập
- Tóm tắt
Mục tiêu bài học
Sau bài này, bạn cần trả lời được:
- Vocabulary của một tokenizer chứa gì, mapping với token ID ra sao.
- Vocab size của các model phổ biến (GPT-2, GPT-4, Llama 3, Gemma…) khác nhau bao nhiêu và vì sao.
- Embedding table chiếm bao nhiêu tham số trong model 7-8B, vì sao "tied weight".
- Khi nào cần thêm token mới và phải làm gì với embedding table.
- Padding, truncation, attention_mask hoạt động thế nào khi batch encode.
Bài 4 (SentencePiece / WordPiece) đã giải thích cách tokenizer được train; bài này tập trung vào sản phẩm của quá trình train — bảng vocabulary và cách dùng nó trong code.
Vocabulary là gì — tập token cố định
Vocabulary (vocab) của một tokenizer là tập tất cả token mà tokenizer biết. Tập này cố định sau khi train xong tokenizer — model chỉ có thể "đọc" và "sinh" những token nằm trong vocab.
Mỗi token trong vocab có một token ID là một số nguyên không âm duy nhất. ID là chỉ số (index) của token trong vocab. Khi nói "vocab size = 50.257" tức là tokenizer đó có 50.257 token, ID đánh từ \( 0 \) tới \( 50{,}256 \).
Phía model, mọi tính toán đều làm trên token ID (số nguyên), không phải trên chuỗi ký tự. String chỉ tồn tại ở hai biên: input của encode và output của decode.
"Hello" ──encode──▶ [15496] ──model──▶ [15496, 11, 995] ──decode──▶ "Hello, world"
Vocab không phải là một danh sách "từ" theo nghĩa ngôn ngữ học. Một token có thể là một từ đầy đủ (" the"), một subword ("##ing"), một byte ("<0x41>"), một dấu câu (",") hoặc một special token (<|endoftext|>).
Mapping bi-directional: vocab và inv_vocab
Vocab thường được lưu dưới hai dictionary nghịch đảo:
vocab[token_string] = id— dùng khi encode, tra ID từ token string.inv_vocab[id] = token_string— dùng khi decode, tra string từ ID.
Hai quá trình tương ứng:
- Encode:
text → [id_1, id_2, ..., id_n]. Tokenizer chạy thuật toán phân đoạn (BPE / WordPiece / SentencePiece) trên text rồi travocabtừng token. - Decode:
[id_1, ..., id_n] → text. Trainv_vocabtừng ID rồi nối các token string lại, áp dụng quy tắc khử prefix (ví dụ##của WordPiece,▁của SentencePiece, byte unicode của BPE).
Round-trip decode(encode(text)) phải bằng text ban đầu với các tokenizer hiện đại (byte-level BPE, SentencePiece). Với tokenizer cũ hơn (BERT WordPiece) có thể mất whitespace hoặc dấu trọng âm — gọi là lossy.
Vocab size phổ biến 2024-2026
Vocab size là siêu tham số quan trọng được chọn trước khi train model. Một số model tham chiếu:
Model Vocab size Tokenizer
─────────────────────────────────────────────────────
GPT-2 50,257 byte-level BPE
GPT-3 50,257 byte-level BPE (giữ nguyên GPT-2)
GPT-3.5 / GPT-4 100,256 cl100k_base (tiktoken)
GPT-4o 200,019 o200k_base (tiktoken)
BERT base 30,522 WordPiece
RoBERTa 50,265 byte-level BPE
Llama 2 32,000 SentencePiece BPE
Llama 3 / 3.1 128,256 tiktoken-style BPE
Gemma / Gemma 2 256,000 SentencePiece
Mistral 7B 32,000 SentencePiece BPE
Qwen2 151,936 tiktoken-style BPE
Quy luật quan sát được:
- Model thế hệ sau xu hướng tăng vocab size (Llama 2 → Llama 3 tăng 4×).
- Model multilingual / cover nhiều script (Gemma 256k, Qwen 152k) có vocab lớn hơn model English-centric (Llama 2 32k).
- Vocab size không phải số tròn đẹp (50.257, 100.256, 128.256) vì gồm token "normal" cộng với một nhúm special token được pad cho căn chỉnh kích thước embedding table với block size phần cứng.
Trade-off vocab lớn vs nhỏ
Vocab lớn (128k - 256k):
- Mỗi token "đóng gói" nhiều ký tự hơn → cùng đoạn text cần ít token hơn → context window dùng hiệu quả, inference rẻ hơn theo số token.
- Embedding table to: \( V \times d \) tăng theo \( V \).
- Output head (LM head) FC weight \( d \times V \) tương tự.
- Phù hợp multilingual: có chỗ cho token của nhiều script (Cyrillic, CJK, Arabic…).
Vocab nhỏ (30k - 50k):
- Sequence dài hơn — cùng văn bản tốn nhiều token hơn.
- Embedding compact, ít tham số "lãng phí" cho token hiếm gặp.
- Phù hợp single-language hoặc khi tổng tham số bị giới hạn (model nhỏ, model edge).
Việc chọn vocab size phải cân nhắc cùng kích thước model (hidden size \( d \)) và corpus train. Một heuristic không chính thức: với model dense, embedding + LM head nên chiếm khoảng 10-20% tổng tham số.
Embedding table — chiếm phần lớn param của smaller model
Embedding table biến token ID thành vector. Shape:
\[ E \in \mathbb{R}^{V \times d} \]
Trong đó \( V \) là vocab size, \( d \) là hidden dimension. Với token ID \( i \), embedding là hàng thứ \( i \) của \( E \).
Ví dụ Llama 3 8B: \( V = 128{,}256 \), \( d = 4096 \). Số tham số của embedding table:
\[ 128{,}256 \times 4096 = 525{,}336{,}576 \approx 525\text{M} \]
Tổng tham số Llama 3 8B là khoảng 8 tỷ → embedding chiếm xấp xỉ 6,6%. Với model nhỏ hơn (Llama 3 1B / 3B, Gemma 2B với vocab 256k) tỷ lệ này có thể lên 25-40% — embedding trở thành thành phần tốn tham số lớn nhất.
Một số biến thể giảm chi phí embedding:
- Factorized embedding (ALBERT): chia \( E \) thành \( V \times e \) và \( e \times d \) với \( e \ll d \).
- Adaptive embedding: cho token tần suất cao dùng \( d \) đầy đủ, token hiếm dùng kích thước nhỏ hơn.
Bài 6 (Text Embedding) sẽ đi sâu hơn về ý nghĩa hình học của các vector này.
Output head (LM head) và tied weight
LM head (Language Modeling head) project hidden state cuối cùng \( h \in \mathbb{R}^d \) trở lại không gian vocab để tính logit cho từng token:
\[ \text{logits} = h W_{\text{LM}}^\top \in \mathbb{R}^{V}, \qquad W_{\text{LM}} \in \mathbb{R}^{V \times d} \]
Sau softmax, logits trở thành phân phối xác suất trên \( V \) token để chọn token tiếp theo (xem bài 30 — Sampling).
Tied weight (weight tying, Press & Wolf 2017): dùng chung ma trận tham số cho cả embedding và LM head:
\[ W_{\text{LM}} = E \]
Tiết kiệm xấp xỉ \( V \cdot d \) tham số — gần như cắt một nửa "phần vocab" của model. Với Llama 3 8B con số này là 525M tham số, không nhỏ.
Lựa chọn của model phổ biến:
- GPT-2, BERT, RoBERTa, T5: tied.
- Llama 1 / 2 / 3: untied — embedding và LM head là hai ma trận riêng (model lớn nên chi phí thêm vài trăm M tham số chấp nhận được, đổi lại tự do biểu diễn).
- Gemma: tied (vocab 256k → tied tiết kiệm rất nhiều).
Kiểm tra một model có tied weight hay không trong Hugging Face Transformers:
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained("gpt2")
print(model.config.tie_word_embeddings) # True với GPT-2
print(model.get_input_embeddings().weight.data_ptr()
== model.get_output_embeddings().weight.data_ptr()) # True nếu tied
Code Python — inspect vocab GPT-2
Cài transformers (v4.x trở lên):
pip install transformers
Code inspect:
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("gpt2")
print(tokenizer.vocab_size) # 50257
print(len(tokenizer)) # 50257 (gồm cả special token đã add)
# Tra ID của một token
vocab = tokenizer.get_vocab()
print(vocab["hello"]) # 31373
print(vocab["Ġhello"]) # 23748 — token " hello" (Ġ = space đầu)
# Tra token từ ID
print(tokenizer.convert_ids_to_tokens(15496)) # 'Hello'
print(tokenizer.decode([15496])) # 'Hello'
# 20 token đầu vocab
for i in range(20):
print(i, repr(tokenizer.convert_ids_to_tokens(i)))
Lưu ý ký tự Ġ trong vocab GPT-2: đây là cách byte-level BPE biểu diễn ký tự space (byte 0x20 được map sang Ġ để in được, xem bài 3 — BPE).
encode và decode
Phương thức chính:
from transformers import AutoTokenizer
tok = AutoTokenizer.from_pretrained("gpt2")
ids = tok.encode("Hello, AI!")
print(ids) # [15496, 11, 9552, 0]
print(tok.decode(ids)) # "Hello, AI!"
# Encode trả về str token thay vì ID
print(tok.tokenize("Hello, AI!")) # ['Hello', ',', 'ĠAI', '!']
# So sánh số token với cl100k (GPT-4) — cần thư viện tiktoken
import tiktoken
enc = tiktoken.get_encoding("cl100k_base")
print(len(enc.encode("Hello, AI!"))) # 4 — giống GPT-2 ở câu ngắn này
# Câu dài: chênh lệch rõ
text = "The quick brown fox jumps over the lazy dog."
print(len(tok.encode(text)), len(enc.encode(text))) # 11 vs 10 (ví dụ)
Với cùng một đoạn text, hai tokenizer khác nhau cho ra số token khác nhau — đây là lý do cùng một prompt nhưng chi phí gọi GPT-4 vs Llama 3 không tỷ lệ thuận theo độ dài ký tự (xem bài 34 — Chi phí token).
Special token và add token tùy chỉnh
Mỗi tokenizer kèm một tập special token mặc định, không phát sinh từ văn bản thường:
print(tok.all_special_tokens)
# GPT-2: ['<|endoftext|>']
# BERT: ['[UNK]', '[SEP]', '[PAD]', '[CLS]', '[MASK]']
# Llama 3: ['<|begin_of_text|>', '<|end_of_text|>', '<|start_header_id|>',
# '<|end_header_id|>', '<|eot_id|>', ...]
Các special token đảm nhiệm vai trò control (đánh dấu đầu chuỗi, kết chuỗi, padding, role trong chat template…) và phải được giữ nguyên dạng qua encode / decode — chúng không bao giờ bị tokenizer chẻ nhỏ.
Thêm token mới (ví dụ token cho domain riêng):
from transformers import AutoTokenizer, AutoModelForCausalLM
tok = AutoTokenizer.from_pretrained("gpt2")
model = AutoModelForCausalLM.from_pretrained("gpt2")
old_size = len(tok)
n_added = tok.add_tokens(["", ""])
print(n_added, "token thêm")
print(len(tok)) # old_size + 2
# QUAN TRỌNG: resize embedding để model có hàng cho ID mới
model.resize_token_embeddings(len(tok))
ids = tok.encode("Bệnh nhân uống liều .")
print(ids)
Nếu quên gọi resize_token_embeddings, model sẽ raise lỗi index-out-of-range ngay forward pass đầu tiên dùng ID mới. Token mới có embedding khởi tạo ngẫu nhiên (Llama / GPT-2) hoặc trung bình của embedding cũ — bắt buộc phải fine-tune trước khi dùng thật.
Padding, truncation và attention_mask
Model dùng GPU/TPU yêu cầu mỗi batch là tensor cùng shape. Hai chuỗi text độ dài khác nhau cần được "ép" về cùng độ dài:
- Padding: thêm token
<pad>vào chuỗi ngắn cho tới khi đạt độ dài chung. Padding bên phải là mặc định, có model dùng padding trái (Llama causal generation). - Truncation: cắt phần dư khi chuỗi vượt
max_length.
attention_mask đi kèm input_ids để chỉ cho model biết vị trí nào là token thật, vị trí nào là padding:
input_ids = [ 15496, 11, 9552, 0, 50256, 50256, 50256 ]
attention_mask = [ 1, 1, 1, 1, 0, 0, 0 ]
←──── token thật ────→ ←──── pad ────→
Trong attention layer, vị trí có mask = 0 bị thay logit thành \( -\infty \) trước softmax → xác suất attend = 0. Padding không ảnh hưởng kết quả model. Nếu bỏ qua attention_mask, model sẽ "nhìn thấy" token pad và output sai — đây là bug rất phổ biến.
Một số tokenizer (GPT-2 mặc định) không có pad_token — cần gán thủ công:
tok.pad_token = tok.eos_token # GPT-2: dùng <|endoftext|> làm pad
Batch encoding — trả về tensor PyTorch
Cách "đúng" để encode nhiều câu cùng lúc là gọi trực tiếp tokenizer(...), không phải vòng lặp encode:
from transformers import AutoTokenizer
tok = AutoTokenizer.from_pretrained("bert-base-uncased")
batch = tok(
["Hello", "AI Engineer", "Anthropic Claude is helpful"],
padding=True, # pad tới chuỗi dài nhất trong batch
truncation=True,
max_length=16,
return_tensors="pt", # trả về torch.Tensor
)
print(batch["input_ids"].shape) # torch.Size([3, max_len_trong_batch])
print(batch["attention_mask"].shape) # cùng shape
print(batch["input_ids"])
print(batch["attention_mask"])
Các option padding hay dùng:
Truehoặc"longest"— pad tới chuỗi dài nhất trong batch (tiết kiệm bộ nhớ)."max_length"— luôn pad tớimax_length(cần thiết khi compile mode dùng shape cố định).False— không pad (chỉ dùng khi batch size 1).
Với tokenizer "fast" (tokenizers của Hugging Face, viết Rust), batch encode chạy đa luồng — nhanh hơn version "slow" Python cỡ 10-100×. Mặc định AutoTokenizer.from_pretrained tải bản fast nếu có.
Inspect raw vocab file của tokenizer
Trên đĩa, vocab được lưu khác nhau tùy loại tokenizer:
- WordPiece (BERT):
vocab.txtdạng plain text, mỗi dòng một token, ID = số thứ tự dòng (0-indexed). - BPE (GPT-2): hai file —
vocab.json(dict token → id) vàmerges.txt(danh sách cặp merge theo thứ tự ưu tiên). - SentencePiece: file binary
.modelchứa cả vocab và quy tắc merge. Đọc bằngsentencepiecehoặc protobuf. - tiktoken (OpenAI): file
.tiktokendạng base64 + rank, đọc bằng thư việntiktoken. - tokenizers (Hugging Face fast):
tokenizer.json— JSON gộp tất cả thông tin (model, normalizer, pre-tokenizer, post-processor, decoder, vocab) thành một file duy nhất.
Vị trí file sau khi tải:
tok = AutoTokenizer.from_pretrained("gpt2")
print(tok.vocab_files_names)
# {'vocab_file': 'vocab.json', 'merges_file': 'merges.txt', ...}
# Lưu thư mục
tok.save_pretrained("./my-tokenizer")
# my-tokenizer/
# ├── tokenizer.json
# ├── tokenizer_config.json
# ├── vocab.json
# └── merges.txt
OOV (Out-of-Vocabulary)
OOV xảy ra khi gặp text mà tokenizer không có token tương ứng. Cách xử lý phụ thuộc loại tokenizer:
- Byte-level BPE (GPT-2, RoBERTa, Llama 3): không có OOV. Tokenizer luôn có thể "rút" về 256 byte cơ bản, mọi chuỗi Unicode đều encode được — kể cả emoji, ký tự hiếm.
- SentencePiece BPE / unigram: tương tự, có byte fallback (
<0x41>= byte 'A') nên cũng không OOV nếu bậtbyte_fallback=True. - WordPiece (BERT): chẻ tới subword nhỏ nhất, nếu vẫn không có thì fallback
[UNK](ID 100 với BERT base uncased). Mọi[UNK]chia sẻ chung một embedding — model không phân biệt được giữa hai từ OOV khác nhau.
"Không có OOV" không có nghĩa là "tokenizer hiệu quả với mọi text". Một ký tự CJK hiếm hoặc emoji có thể bị tokenizer GPT-2 chẻ thành 4-6 byte token, tiêu tốn context và giảm hiệu năng. Tokenizer được thiết kế tốt cho corpus train (phần lớn là tiếng Anh, code, web).
tok = AutoTokenizer.from_pretrained("gpt2")
print(tok.tokenize("emoji: 🚀"))
# ['em', 'oji', ':', 'Ġ', 'ðŁ', 'ļ', 'Ģ'] — 4 byte cho emoji
print(tok.tokenize("emoji: 🚀", add_special_tokens=False))
Token frequency và anomalous token
Token trong vocab không có "trọng số" như nhau. Tần suất xuất hiện trong corpus train rất lệch:
- Token cực phổ biến:
" the",",","."," a"," of","\n". Embedding của các token này được cập nhật hàng tỷ lần qua training. - Token hiếm: tên riêng lạ, technical term, fragment ký tự còn sót từ giai đoạn train tokenizer. Embedding rất ít được cập nhật → biểu diễn yếu, nhiễu.
Anomalous tokens (Rumbelow & Watkins 2023, "SolidGoldMagikarp"): các token thực ra không bao giờ xuất hiện trong text huấn luyện model dù vẫn nằm trong vocab. Nguyên nhân: tokenizer được train trên dataset rộng hơn dataset của model (ví dụ chứa username Reddit, log Twitch). Khi model gặp các token này, behavior trở nên kỳ lạ — bịa từ, lặp ký tự, đôi khi bypass guardrail. Một số ví dụ:
- GPT-2 / GPT-3:
" SolidGoldMagikarp"," petertodd"," davidjl"(đều là username Reddit). - GPT-3.5 / 4 (cl100k):
" ForCanBeConverted"," ForCanBeConvertedToF"— sót từ data scrape code C#.
Hệ quả thực tế: khi build prompt cho model, tránh dán string lạ không kiểm soát; khi fine-tune, cân nhắc lọc bỏ token tần suất quá thấp.
Vocab pruning và domain-specific tokenizer
Hai hướng tinh chỉnh vocab cho use case riêng:
1. Train tokenizer mới trên corpus domain-specific.
- Y tế: nhiều thuật ngữ Latin (
cardiomyopathy,angioplasty) bị tokenizer general chẻ thành 3-5 subword. Train BPE riêng trên PubMed sẽ gộp các thuật ngữ này thành 1 token. - Luật pháp / hợp đồng: cụm từ cố định lặp nhiều (
"hereinafter referred to as") có lợi khi gộp. - Code: ngôn ngữ lập trình có cú pháp đặc thù — indent, keyword, operator. StarCoder, CodeLlama train tokenizer trên The Stack thay vì web crawl.
2. Vocab pruning — bỏ token không cần.
- Lấy tokenizer multilingual, giữ lại chỉ token dùng cho ngôn ngữ đích, xóa phần còn lại khỏi embedding table và LM head.
- Giảm tham số model nhanh chóng cho deployment edge.
- Cần fine-tune ngắn sau khi prune để model "ổn định" lại.
Hugging Face tokenizers hỗ trợ train tokenizer mới với vài chục dòng code (xem bài 16 — Transformers library):
from tokenizers import Tokenizer
from tokenizers.models import BPE
from tokenizers.trainers import BpeTrainer
from tokenizers.pre_tokenizers import ByteLevel
tok = Tokenizer(BPE(unk_token="[UNK]"))
tok.pre_tokenizer = ByteLevel()
trainer = BpeTrainer(vocab_size=8000, special_tokens=["[PAD]", "[UNK]", "[EOS]"])
tok.train(files=["corpus.txt"], trainer=trainer)
tok.save("custom-tokenizer.json")
Multilingual vocab và tokenizer cho code
Multilingual model phải chia ngân sách vocab cho nhiều ngôn ngữ. Ví dụ:
- mBERT (2018): 110 ngôn ngữ, 119k token. Mỗi ngôn ngữ chiếm ~1k token — tiếng Việt bị tokenize rất "vụn".
- XLM-R (2019): 100 ngôn ngữ, 250k token. Hiệu năng cao hơn mBERT nhờ ngân sách rộng và corpus CommonCrawl đa dạng.
- Llama 3 (2024): 128k token, optimize cho English nhưng cải thiện đáng kể tiếng Trung, Đức, Pháp so với Llama 2 32k.
- Gemma 2 (2024): 256k token — multilingual mạnh, kể cả các script ít resource.
Đo độ "rộng rãi" của tokenizer cho một ngôn ngữ: tính số token trung bình trên mỗi từ tiếng Việt. Ví dụ:
text = "Học máy là một nhánh của trí tuệ nhân tạo."
# So sánh số token (số có thể thay đổi nhỏ giữa các phiên bản)
print(len(AutoTokenizer.from_pretrained("gpt2").encode(text)))
# ~ 26 token (byte-level cho ký tự dấu tiếng Việt)
print(len(AutoTokenizer.from_pretrained("vinai/phobert-base").encode(text)))
# ~ 12 token (PhoBERT train trên corpus tiếng Việt)
Tokenizer cho code: StarCoder dùng vocab 49k trên The Stack (358 ngôn ngữ lập trình); CodeLlama dùng vocab 32k của Llama 2 cộng thêm token <FILL_ME> cho fill-in-the-middle. Tokenizer code tối ưu cho indent, dấu ngoặc, keyword phổ biến (def, return, function) — gộp thành 1 token thay vì nhiều subword.
Bài tập
- Load tokenizer Llama 3 (
meta-llama/Meta-Llama-3-8BhoặcNousResearch/Meta-Llama-3-8Bnếu không có access gate). In vocab size và 20 token đầu. So sánh với GPT-2. - Encode chuỗi
"Anthropic"bằng tokenizer GPT-2, GPT-4 (cl100k quatiktoken), Llama 3. Ghi lại số token và list ID. Vì sao kết quả khác nhau? - Batch encode 3 câu khác độ dài (1, 5, 12 từ) với
padding=True, return_tensors="pt". Ininput_idsvàattention_mask. Kiểm tra vị trí 0 trong mask có đúng là padding không. - Tính embedding table size cho cấu hình hypothetical
V = 128{,}256, \( d = 4096 \). Sau đó tính tổng tham số nếu untied (cộng thêm LM head) và nếu tied. Quy đổi sang MB ở float16 (mỗi tham số 2 byte). - (Tùy chọn) Thêm 2 token mới
<PATIENT>,<DIAGNOSIS>vào tokenizer GPT-2. Resize embedding. Encode chuỗi chứa hai token mới, verify chúng được giữ nguyên 1 token (không bị chẻ).
Tóm tắt
- Vocabulary là tập token cố định, mỗi token có 1 ID nguyên duy nhất. Mapping bi-directional qua
vocab/inv_vocab. - Vocab size 2024-2026: GPT-2 50k, GPT-4 cl100k 100k, GPT-4o o200k 200k, Llama 3 128k, Gemma 256k. Model multilingual có vocab lớn hơn.
- Embedding table \( V \times d \) và LM head \( d \times V \) chiếm phần đáng kể tham số, đặc biệt ở model nhỏ. Tied weight giảm chi phí xấp xỉ một nửa.
- Thêm token mới phải đi kèm
model.resize_token_embeddings(len(tokenizer))và fine-tune. - Batch encode cần
padding,truncation,attention_mask. Quên mask → model "thấy" padding → kết quả sai. - Tokenizer hiện đại (byte-level BPE, SentencePiece) gần như không OOV. Tuy nhiên token hiếm / anomalous vẫn có thể gây behavior bất thường.
Bài 6 (Text Embedding) sẽ làm rõ ý nghĩa hình học của vector \( E[i] \) — vì sao vector của "king" trừ "man" cộng "woman" xấp xỉ "queen", và tại sao tính chất này quan trọng cho mọi tầng tính toán phía sau của LLM.
- Hugging Face Transformers — Tokenizer documentation
- Hugging Face tokenizers library
- OpenAI tiktoken — Fast BPE tokenizer cho GPT-3.5 / 4 / 4o
- Google SentencePiece
- Press & Wolf 2017 — Using the Output Embedding to Improve Language Models (arXiv:1608.05859)
- Lan et al. 2019 — ALBERT: factorized embedding (arXiv:1909.11942)
- Llama 3 Technical Report (arXiv:2407.21783)
- Gemma 2 Technical Report (arXiv:2408.00118)
- Rumbelow & Watkins 2023 — SolidGoldMagikarp (anomalous tokens)
- tiktoken — encoding registry và vocab size từng model OpenAI
- Hugging Face — Padding and truncation
- PreTrainedModel.resize_token_embeddings
