Tokenization
Tokenization は、生 text を LLM の入力単位 (token) に変換する処理です。語彙設計は、モデルの効率、多言語性能、コード理解、推論精度すべてに影響します。
なぜ単語単位ではないのか
単語単位の tokenizer には、
- 語彙が爆発する (固有名詞、活用、新語)
- OOV (out-of-vocabulary) が出る
- 言語ごとに大きく違う
という問題があります。一方、文字単位は語彙は小さいですが、sequence が長くなりすぎます。
実用上は、subword tokenization (単語と文字の中間) が標準です。
BPE (Byte-Pair Encoding)
BPE は、文字 pair の中で頻出するものを順次 merge して、語彙を構築する手法です。
例:
"low" -> l o w
"lower" -> l o w e r
"newest"-> n e w e s t
"widest"-> w i d e s t
merges: (e,s) -> es, (es,t) -> est, ...
GPT-2、GPT-3、GPT-4、Llama などは BPE 系を使います。
Byte-Level BPE
GPT-2 以降は byte-level BPE が主流です。任意の Unicode を扱えるため、
- 多言語
- 絵文字、記号
- バイナリに近い data
も losslessly に token 化できます。
SentencePiece
SentencePiece は、空白を陽に扱わず、生 text を直接 unigram LM や BPE で tokenize するライブラリです。日本語のように空白で区切らない言語にも自然に適用できます。Llama、T5、PaLM などで採用されています。
何が問題になるか
| 問題 | 例 |
|---|---|
| 多言語の効率差 | 英語は 1 token / 単語、日本語や中国語は文字単位になりやすい |
| 数値演算 | 数字の分割の仕方で計算精度が変わる |
| コード | インデント、空白の扱いが重要 |
| 長い識別子 | 不自然な split が CoT を壊す |
| Prompt injection | 特殊 token の悪用 |
近年の Llama 3 / GPT-4o などは、語彙を大幅に拡張して多言語・コード効率を改善しています。
数式で見る BPE の merge
BPE は、corpus 内で最も頻繁に隣接して現れる token pair を順番に merge して語彙を作ります。現在の token sequence 集合を とすると、次に merge する pair は次のように選べます。
選ばれた pair は新しい token に置き換えられます。
この式の気持ちは、「よく一緒に出る文字列を一つの単位にまとめることで、語彙数と sequence length の妥協点を作る」というものです。頻出語や頻出 subword は短い token 列になり、珍しい語は細かい token に分かれます。
Tokenization は、LLM の計算量にも直接影響します。文字列 の token 数を とすると、self-attention の計算量は概念的に次の量に比例します。
ここで、 は hidden dimension です。同じ文章でも tokenizer によって が変わるため、多言語や code では tokenizer の効率が context length と推論コストに大きく効きます。
関連ページ
主なソース
- BPE for NMT (Sennrich): https://arxiv.org/abs/1508.07909
- SentencePiece: https://arxiv.org/abs/1808.06226
- tiktoken: https://github.com/openai/tiktoken