BPEトークナイザー(ビーピーイートークナイザー)
Byte Pair Encoding(BPE)に基づくサブワード分割アルゴリズム。テキストを統計的に最適なサブワード単位に分割し、LLMが処理可能なトークン列に変換する。GPT系のtiktoken、LLaMA系のSentencePieceが代表的な実装である。
BPEトークナイザーとは、Byte Pair Encoding(バイトペアエンコーディング)アルゴリズムを用いてテキストをサブワード単位に分割する自然言語処理の基盤技術である。GPT-4o・Claude 4・Gemini 2.0など2026年の主要LLMはすべてBPE派生のトークナイザーを採用している。
概要
BPEは1994年にPhilip Gageがデータ圧縮アルゴリズムとして発表し、2016年にSennrichらが機械翻訳のサブワード分割に応用した。従来の単語単位分割では語彙外(OOV)問題が発生し、文字単位分割では系列長が爆発する。BPEはこの中間解として、頻出するバイト列(文字ペア)を繰り返し結合して最適な語彙を構築する。
学習手順は単純である。初期語彙をUTF-8バイト(256種)に設定し、コーパス中で最頻出のバイトペアを結合して新トークンを追加する操作を、目標語彙サイズに達するまで繰り返す。GPT-4oのtiktoken(cl100k_base)は約100,256トークンの語彙を持つ。
主要トークナイザー実装の比較
| トークナイザー | 開発元 | 語彙サイズ | 採用モデル | 特徴 |
|---|---|---|---|---|
| tiktoken (cl100k_base) | OpenAI | 100,256 | GPT-4o, GPT-4o mini | Rust実装で高速、日本語対応改善 |
| tiktoken (o200k_base) | OpenAI | 200,000 | o1, o3, GPT-4.1 | 多言語効率向上、日本語トークン数30%削減 |
| SentencePiece (BPE) | 32,000〜256,000 | LLaMA 3, Gemma 2 | 言語非依存、Unigram方式も選択可 | |
| HuggingFace Tokenizers | HuggingFace | 可変 | 各種OSSモデル | Rust実装、WordPiece/Unigramも対応 |
| Claude Tokenizer | Anthropic | 非公開 | Claude 4 Opus/Sonnet/Haiku | 日本語効率が高い独自BPE |
BPEの学習アルゴリズム
- 初期化: テキストをUTF-8バイト列に変換。初期語彙 = 256バイト値
- ペア頻度計算: コーパス全体で隣接バイトペアの出現頻度を集計
- 最頻ペア結合: 最も頻出するペアを新トークンとして語彙に追加
- 反復: 目標語彙サイズ(32K〜200K)に達するまでステップ2-3を繰り返す
- 特殊トークン追加:
<|endoftext|>,<|im_start|>等の制御トークンを語彙末尾に追加
語彙サイズのトレードオフ:
- 小語彙(32K): メモリ効率が良いが日本語・中国語の分割が細かくなり系列長が増大
- 中語彙(100K): GPT-4oの標準。英語・日本語・コードのバランスが取れる
- 大語彙(200K): o200k_baseで採用。多言語効率は最高だがembedding層のパラメータ数が増加
日本語トークン化の課題と対策
日本語はスペース区切りがないため、BPEの分割品質が学習コーパスの日本語比率に強く依存する。
- tiktoken cl100k_base: 「人工知能」→「人工」「知」「能」(3トークン)
- tiktoken o200k_base: 「人工知能」→「人工知能」(1トークン)、日本語効率30%改善
- SentencePiece: 事前の形態素解析なしでバイト列から直接学習。日本語コーパス比率で品質が決まる
- Claude Tokenizer: 日本語の1トークンあたり約2文字で、tiktokenの約1.5文字より効率的
実装とパフォーマンス
# tiktoken の使用例(Python)
import tiktoken
enc = tiktoken.encoding_for_model('gpt-4o')
tokens = enc.encode('自作PCのメモリ選び') # → [... 5トークン程度]
print(f'トークン数: {len(tokens)}')
print(f'デコード: {enc.decode(tokens)}')
処理速度の実測値(Apple M3 Pro、1MBテキスト):
- tiktoken (Rust): 約12ms
- SentencePiece (C++): 約18ms
- HuggingFace Tokenizers (Rust): 約15ms
- Python純粋実装: 約850ms(70倍遅い)
よくある質問(FAQ)
Q1: BPEとWordPieceの違いは何か? A: BPEは頻出バイトペアを結合する方式、WordPieceは結合による言語モデル尤度の改善量で選択する方式。BERTがWordPiece、GPT系がBPEを採用。実用上の差は小さいが、BPEの方が実装が単純で高速。
Q2: トークナイザーの選択がLLMのコストにどう影響するか? A: 語彙サイズが大きいほど同じテキストを少ないトークンで表現でき、API課金が削減される。o200k_baseはcl100k_baseより日本語テキストのトークン数を約30%削減し、同じ処理でコストが3割安くなる。
Q3: カスタムトークナイザーを学習する意味はあるか? A: 特定ドメイン(医療・法律・プログラミング言語)に特化したモデルでは、ドメイン語彙をトークナイザーに含めることでトークン効率が10〜20%改善する。ただし既存モデルのファインチューニングではトークナイザー変更は非推奨。
まとめ
- BPEは頻出バイトペアの反復結合でサブワード語彙を構築するアルゴリズム
- GPT系のtiktoken、LLaMA系のSentencePiece、HuggingFace Tokenizersが3大実装
- 語彙サイズ32K〜200Kのトレードオフ: メモリ効率 vs 多言語トークン効率
- 日本語は英語の1.5〜2倍のトークン数を消費し、o200k_baseで30%改善
- Rust/C++実装は純Python比で70倍高速、本番環境ではネイティブ実装が必須