LLMトークナイゼーションパイプライン(エルエルエムトークナイゼーションパイプライン)
BPE・SentencePiece・WordPieceなどのサブワードトークナイザを学習データに適用し、テキストをトークンID列に変換する処理系。トークナイザの学習・適用・語彙管理を含む。
LLMトークナイゼーションパイプラインとは
LLMトークナイゼーションパイプラインは、前処理・品質フィルタリング済みのテキストデータをトークンID列に変換し、言語モデルが直接学習できる形式にする処理系である。トークナイザの学習(語彙構築)とトークン化の適用(テキスト→ID変換)の2つのフェーズから構成され、語彙サイズ・サブワード分割戦略がモデルの言語理解能力に直接影響する。
トークナイゼーションアルゴリズム
主要アルゴリズムの比較
| アルゴリズム | 代表的モデル | 語彙構築法 | 特徴 | 採用例 |
|---|---|---|---|---|
| BPE(Byte Pair Encoding) | GPT-4, Claude, Llama 3 | 頻度ベースのマージ | 最も広く使用、バイトレベルBPEが主流 | OpenAI tiktoken |
| Unigram | T5, mBART | 尤度ベースの刈り込み | 確率的な分割が可能 | SentencePiece |
| WordPiece | BERT, DistilBERT | 尤度ベースのマージ | BERTファミリーで標準 | HuggingFace tokenizers |
| Byte-level BPE | GPT-2以降 | バイト単位のBPE | 未知語なし、多言語対応 | tiktoken, tokenizers |
2026年現在、Byte-level BPE が LLM のデファクトスタンダードとなっている。GPT-4 は cl100k_base(100,256語彙)、Llama 3 は 128,256語彙のBPEトークナイザを使用している。
トークナイザの学習プロセス
BPE の学習手順
- 初期語彙の構築: 全バイト値(256個)を初期語彙とする(Byte-level BPE の場合)
- 頻度計算: 学習コーパス中の隣接トークンペアの出現頻度を計算
- マージルール生成: 最も高頻度のペアを1つのトークンとしてマージ
- 繰り返し: 目標語彙サイズに達するまでステップ2-3を繰り返す
- 特殊トークン追加:
<|endoftext|>,<|im_start|>などの制御トークンを追加
語彙サイズの選択
| モデル | 語彙サイズ | トークナイザ | 備考 |
|---|---|---|---|
| GPT-2 | 50,257 | BPE | 英語中心 |
| GPT-4 | 100,256 | Byte-level BPE (cl100k) | 多言語対応強化 |
| Llama 3 | 128,256 | Byte-level BPE | 多言語・コード対応 |
| Claude 3 | 非公開 | BPE系 | 高効率な多言語分割 |
| Gemini | 256,000 | SentencePiece | 最大級の語彙 |
| Qwen 2.5 | 151,643 | Byte-level BPE | CJK最適化 |
語彙サイズが大きいほど1トークンあたりの情報量が増え、同じテキストをより少ないトークン数で表現できる。ただし、語彙サイズの増大は埋め込み層のパラメータ数増加につながる。
多言語トークナイゼーションの課題
言語間の効率格差
同一のトークナイザで異なる言語を処理する場合、言語によってトークン効率が大きく異なる。
| 言語 | 英語基準のトークン数比 | 原因 |
|---|---|---|
| 英語 | 1.0x(基準) | BPE学習データの大部分が英語 |
| フランス語 | 1.3〜1.5x | ラテン文字だがアクセント記号で分割増 |
| 日本語 | 1.5〜3.0x | 漢字・ひらがな・カタカナの混在 |
| 中国語 | 1.5〜2.5x | 漢字がバイト分割される |
| アラビア語 | 2.0〜3.0x | 右から左の文字体系 |
| タイ語 | 3.0〜5.0x | 分かち書きなし、固有文字 |
Llama 3 や Qwen 2.5 は多言語データの比率を増やしてトークナイザを学習することで、この格差を縮小している。
日本語の最適化戦略
- 事前分割: MeCab/Sudachi で形態素解析後にBPEを適用(日本語特化モデル向け)
- バイトフォールバック: 未知文字をバイト列として処理(Byte-level BPE の標準動作)
- CJK専用マージルール: 漢字の部首・偏旁レベルのサブワード分割を学習
- 語彙割当ての増加: 全語彙の 20〜30% を CJK 系言語に割り当て
パイプライン実装
大規模トークン化の処理フロー
-
トークナイザ学習(1回のみ)
- 学習コーパスのサブセット(10〜100GB)から語彙を構築
- SentencePiece または HuggingFace tokenizers で学習
- 学習時間: 数時間〜数日
-
並列トークン化(データ全体)
- テキストファイルをチャンク分割し、マルチプロセスで並列処理
- 各チャンクをトークンID列に変換し、バイナリ形式(numpy mmap)で保存
- 処理速度: 1コアあたり約 50〜100MB/秒
-
シャッフルと保存
- トークン列を固定長シーケンス(2048〜8192トークン)に分割
- ランダムシャッフルして学習時のデータ偏りを防止
- Arrow/Parquet 形式で保存(HuggingFace Datasets との互換性)
処理速度ベンチマーク
| ツール | 言語 | 速度(MB/秒/コア) | 備考 |
|---|---|---|---|
| tiktoken | Rust/Python | 約 150 | OpenAI公式、最速 |
| HuggingFace tokenizers | Rust/Python | 約 120 | 多機能、カスタマイズ性高 |
| SentencePiece | C++/Python | 約 80 | Unigram サポート |
| custom BPE (Python) | Python | 約 5 | 学習用、本番非推奨 |
tiktoken と HuggingFace tokenizers は Rust で実装されたコアエンジンを Python バインディングで利用する設計で、純粋な Python 実装と比較して 20〜30倍の速度差がある。
トークナイザの評価指標
| 指標 | 定義 | 望ましい値 |
|---|---|---|
| 圧縮率 | 元テキストのバイト数 / トークン数 | 高いほど良い(英語で3.5〜4.5) |
| 語彙カバレッジ | 未知トークン(UNK)の発生率 | 0%(Byte-level BPE では原理的に0) |
| 多言語公平性 | 言語間のトークン数比の分散 | 低いほど良い |
| 正規化安定性 | 同一意味テキストの分割一貫性 | 高いほど良い |
| 可逆性 | トークン→テキストの復元精度 | 100%(ロスレス) |
よくある質問(FAQ)
Q1: トークナイザは事前学習後に変更できるか? A: 原則として変更できない。トークナイザの語彙はモデルの埋め込み層と密結合しており、語彙を変更するとモデル全体の再学習が必要になる。ただし、特殊トークンの追加(ファインチューニング用)やアダプタ手法による部分的な語彙拡張は可能。
Q2: 語彙サイズは大きいほど良いのか? A: 一概には言えない。語彙サイズを増やすとトークン効率は向上するが、埋め込み層のパラメータ数が増加し、低頻度トークンの学習が不十分になるリスクがある。Llama 3 の 128K語彙は、多言語対応と効率のバランスとして2026年時点で最適に近い選択とされている。
Q3: SentencePiece と HuggingFace tokenizers の違いは? A: SentencePiece はテキストを直接サブワードに分割する「前処理不要」設計で、Unigram モデルをサポートする。HuggingFace tokenizers は BPE/WordPiece を高速に実行する Rust 実装で、カスタムの前処理・後処理パイプラインを柔軟に構成できる。新規プロジェクトでは HuggingFace tokenizers が推奨される。
まとめ
- Byte-level BPE が 2026年現在のLLMトークナイザの標準
- 語彙サイズは 100K〜150K がバランスの良い範囲
- 多言語対応では言語間のトークン効率格差が重要な課題
- tiktoken/HuggingFace tokenizers の Rust 実装が本番環境の標準
- トークナイザの選択はモデル設計の初期段階で決定すべき不可逆な判断