トークン化 | Transformer
1. (BPE:Byte Pair Encoding による)トークン化
基本的な流れ
BPE はテキストを 単語単位ではなく隣接ペアの頻度 でマージします。
初期状態では各文字(バイト)が 1 つのトークンです。
入力: t h i s _ i s _ a _ p e n
1. "is" が2回出現 → 最頻出ペア → ID 256 = "is" にマージ
2. t h [is] _ [is] _ a _ p e n
3. 以降も頻出ペアを繰り返しマージ
ID の割り当て
| 範囲 | 内容 |
|---|---|
| ID 0 〜 255 | 基本バイト(固定) |
| ID 256 〜 N | BPE マージで追加されたトークン |
UTF-8 によるトークン化
UTF-8 は Unicode(コードポイント)を 1 - 4 バイトの可変長で符号化します。
UTF-8 はバイトの先頭ビット役割が重複しない設計になっています。
| バイト種別 | ビットパターン | 範囲 |
|---|---|---|
| ASCII 1バイト文字 | 0xxxxxxx |
0x00〜0x7F |
| 先頭バイト(2バイト文字) | 110xxxxx |
0xC0〜0xDF |
| 先頭バイト(3バイト文字) | 1110xxxx |
0xE0〜0xEF |
| 先頭バイト(4バイト文字) | 11110xxx |
0xF0〜0xF7 |
| 継続バイト | 10xxxxxx |
0x80〜0xBF |
例:cat vs 猫
"cat"
c = 0x63 → 01100011(1バイト文字)
a = 0x61 → 01100001(1バイト文字)
t = 0x74 → 01110100(1バイト文字)
"猫"
0xE7 → 11100111(3バイト文字の先頭)
0xAC → 10101100(継続バイト)
0xAB → 10101011(継続バイト)
※ 0x は 16 進数表記を表します
3 つの範囲が完全に重複しないため、BPE がバイト列を扱っても混同されません。
2. (Embedding レイヤによる)埋め込みベクトル化
入力テキスト
↓
1. トークナイザー( BPE )
テキスト → トークン ID 列
例: "猫は可愛い" → [42567, 11245, 98, 334]
↓
2. Embedding レイヤ
トークン ID → 埋め込みベクトル
例: 42567 → [0.23, -0.41, 0.87, ...] (768次元など)
↓
3. Transformer ブロック
Embedding レイヤ
語彙数 × 埋め込み次元数 の参照テーブル(重み行列)です。 トークン ID は単なる 行番号(インデックス) として使われます。
役割の分離
| 役割 | 内容 |
|---|---|
| BPE | 単語に ID を割り振る(学習前に決定) |
| Embedding レイヤ | 単語 ID から埋め込みベクトルを出力(重み行列は学習で最適化) |
3. 語彙数
$語彙数 = 256 + マージ回数$ です。
マージ回数は事前に決めるハイパーパラメータです。
| モデル | 語彙数 |
|---|---|
| GPT-2 | 50,257 |
| LLaMA 3 | 128,256 |
| cl100k(GPT-4) | 100,277 |
トレードオフ
| 語彙数 | メリット | デメリット |
|---|---|---|
| 大きい | 1 トークンで長い単語を表現できる | Embedding レイヤの重み行列が大きくなりメモリ増加 |
| 小さい | メモリ節約 | 1 つの単語が多くのトークンに分割される |
4. 未知の単語
学習時に存在しなかった語彙が推論時に入力された場合の優先順位:
入力文字列
↓
1. BPE の既知トークンに一致するか? → 一致すればその ID
↓ 一致しない
2. より短い BPE トークンに分解できるか? → 分解して ID 列にする
↓ それも無理
3. 1 バイトずつ分解 → ID 0〜255 の基本バイト
BPE はどのような入力も必ず 0〜255 のバイトに分解できるため未知の単語が原理的に発生しませんが、学習時に十分出現していた語彙ほど良い Embedding を持ちます。
| 状況 | 品質 |
|---|---|
| 既知トークン “東京” | 学習で意味を獲得済みなので良い |
| バイト分解 [0xE7, 0xB4, …] | 文脈から推測するしかないので悪い️ |
補足
word2vec と BPE トークン化の関係
word2vec は BPE を使いません。
word2vec は、単語単位(word-level)のトークン化を採用しています。
"I love cats" → ["I", "love", "cats"]
- 空白(スペース)で単語を区切る
- 必要に応じて簡単な前処理(小文字化、句読点除去など)を行う
word2vec の課題:未知語問題
単語単位のトークン化には大きな課題があります。
- 学習時の語彙(vocabulary)に含まれない単語は扱えない(OOV: Out-of-Vocabulary 問題)
- 語形変化(例:「play」「playing」「played」)がそれぞれ独立したベクトルとして扱われ、関連性が活かせない