一文まとめ: コンピュータはテキストを直接処理できません。トークナイゼーションはテキストをトークン ID に変換し、その ID がベクトルへとマッピングされます。
4.1 なぜトークナイゼーションが必要なのか
前章では、Transformer のパイプラインの最初のステップを次のように示しました。
text -> token IDs
本章ではこのステップを説明します。
4.1.1 コンピュータには数字が必要
コンピュータは私たちと同じようには文を見ていません。たとえば次の文を見ても、
The agent opened a pull request.
それが意味を持つ単語の連なりであることはわかりません。コンピュータには数値の単位が必要なのです。
トークナイゼーションとは、テキストを数値の列に変換するプロセスです。各数値単位を トークン ID(テキストを表す番号)と呼びます。そして、トークン ID に対応するテキストの断片そのものを トークン(モデルが扱うテキスト片)と呼び、トークナイゼーションを実行する仕組みを トークナイザ と呼びます。
4.1.2 アーキテクチャ上の位置づけ
トークナイゼーションは入り口に位置します。
raw text -> token IDs -> embeddings -> position -> Transformer blocks
トークナイゼーションがなければ、モデルの残りの部分は処理する材料を持てません。
4.2 トークナイズの2つの方法
最も単純な発想は、すべての文字に番号を割り当てることです。しかし、実際の LLM はもう少し賢いやり方を採用しています。
4.2.1 方法その1: 文字単位の ID
英語の文に対して、素朴な文字単位のトークナイザは次のように番号を割り振るかもしれません。
T -> 1
h -> 2
e -> 3
space -> 4
a -> 5
g -> 6
n -> 7
t -> 8
...
仕組みは理解しやすく、すべての文字が数字になります。
しかし、いくつか問題があります。
- トークン数が多すぎる: 1単語が複数の文字に分解されてしまいます。
- 意味の単位が弱い:
pull requestは意味のある一つの語句なのに、文字に分解されてしまいます。 - コンテキストの使い方が非効率: 長いテキストはコンテキスト長をすぐに使い切ってしまいます。
文字単位のトークナイゼーションが間違いというわけではありませんが、現代の LLM にとって最良の選択肢になることはほとんどありません。
4.2.2 方法その2: BPE とサブワード
GPT 系のトークナイザの多くは、BPE(Byte Pair Encoding)のようなサブワード戦略を採用しています。
考え方は次の通りです。
- 頻出するまとまりは1つのトークンになる
- 珍しい単語はより小さい トークン片(サブワード単位の小片)に分割できる
- 語彙のサイズは有限のまま保てる
- 未知のテキストにも対応できる
OpenAI の cl100k_base トークナイザを使うと、次のテキストは、
The agent opened a pull request.
このようにエンコードされます。
[791, 8479, 9107, 264, 6958, 1715, 13]
各トークン片の対応は以下の通りです。
791 -> "The"
8479 -> " agent"
9107 -> " opened"
264 -> " a"
6958 -> " pull"
1715 -> " request"
13 -> "."
スペースがトークンの一部に含まれていることに気付くでしょう。これは正常な挙動です。
4.2.3 コンテキスト長
コンテキスト長とは、モデルが一度に処理できるトークン数のことです。
128,000 トークンに対応するモデルは、英単語 128,000 個を処理できるという意味ではありません。あくまでトークナイザの単位で 128,000 個という意味です。
世代を追うごとにコンテキスト長は大きく伸びてきました。
| モデル | コンテキスト長 |
|---|---|
| GPT-3 | 4,096 トークン |
| GPT-4 (オリジナル) | 8,192 トークン |
| GPT-4 Turbo / 32k 系 | 32,768 〜 128,000 トークン |
| GPT-5 | 400,000+ トークン |
| Claude (Sonnet 4.5) | 200,000 トークン |
| Gemini 2.5 Pro | 1,000,000+ トークン |
言語や文字体系によってトークンの効率は異なります。英単語は馴染みのあるまとまりにトークナイズされやすい一方、中国語のテキストは効率が大きく落ちます。cl100k_base トークナイザでは中国語の漢字1文字あたり 2〜3 トークンを必要とすることが多く、同じ内容を読むのに英語の2〜3倍のトークンを消費する場合があります。
LLM の API が単語ではなくトークン単位で課金するのは、こうした事情があるからです。
4.3 トークンから埋め込みへ
トークン ID だけではまだ不十分です。モデルは各 ID をベクトルに変換しなければなりません。
これを 埋め込み(Embedding) と呼びます。
4.3.1 埋め込みのルックアップテーブル
モデルの内部には大きな表があります。
[vocab_size, d_model]
ここで、
- vocab_size はトークナイザが知っているトークン ID の総数(語彙のサイズ)です。
- d_model はモデルが扱うベクトルの幅です。
たとえば、
vocab_size = 100256
d_model = 64
であれば、埋め込みテーブルが含む数の個数は次のようになります。
100256 x 64 = 6,416,384 個
これらの数値はすべて学習可能なパラメータです。
4.3.2 ルックアップの流れ
例として次の文を考えます。
The agent opened a pull request.
トークナイゼーションすると、
[791, 8479, 9107, 264, 6958, 1715, 13]
そしてモデルはテーブル参照を行います。
token 791 -> row 791 -> vector
token 8479 -> row 8479 -> vector
token 9107 -> row 9107 -> vector
...
結果として得られるのは行列です。
[context_length, d_model]
文が 7 個のトークンを持ち、d_model = 64 であれば、行列の形状は次のようになります。
[7, 64]
この行列が、Transformer ブロックに送られる数値表現です。
4.3.3 なぜベクトルを使うのか
トークン ID をそのまま使えばよいのでは、と思うかもしれません。
しかし、ID には幾何構造がありません。トークン ID 791 がトークン ID 792 に意味的に「近い」とは言えないのです。
ベクトルはこの問題を解決し、関係性を表現できます。
agent、tool、workflowは近い領域に位置できるpull requestとcode reviewは関連付けられるpull requestとpull tabは文脈に応じて分離できる
埋め込みベクトルは、トークン ID 自体に意味があるかのように扱うことなく、言語を行列演算の世界に持ち込む手段なのです。
4.4 tiktoken で試してみる
OpenAI のトークナイザライブラリを使えば、トークナイゼーションの様子を実際に観察できます。
import tiktoken
enc = tiktoken.get_encoding("cl100k_base")
text = "The agent opened a pull request."
tokens = enc.encode(text)
print(f"Token IDs: {tokens}")
print(f"Token count: {len(tokens)}")
print(f"Decoded: {enc.decode(tokens)}")
for token_id in tokens:
print(f"{token_id} -> {enc.decode([token_id])!r}")
実行結果のイメージは次のようになります。
Token IDs: [791, 8479, 9107, 264, 6958, 1715, 13]
Token count: 7
Decoded: The agent opened a pull request.
791 -> 'The'
8479 -> ' agent'
...
この小さな実験はぜひやってみてください。tokenizer.encode() と tokenizer.decode() の動きを目で見ると、トークナイゼーションが一気に具体的なものに感じられます。
4.5 埋め込み層のパラメータ数
埋め込み層は無視できない数のパラメータを保持します。
4.5.1 計算式
embedding parameters = vocab_size x d_model
4.5.2 例
| モデル | 語彙 | 幅 | パラメータ数 |
|---|---|---|---|
| GPT-2 Small | 50,257 | 768 | 約 38.6M |
| GPT-2 Large | 50,257 | 1,280 | 約 64.3M |
| GPT-3 | 50,257 | 12,288 | 約 618M |
| LLaMA-2-7B | 32,000 | 4,096 | 約 131M |
埋め込みは小さな前処理の細部ではありません。学習されたパラメータテーブルそのものであり、無視できない存在です。
4.6 章のまとめ
4.6.1 重要な概念
| 概念 | 意味 |
|---|---|
| トークナイゼーション | テキストをトークナイザの単位に変換する |
| トークン | モデルが読める形のテキスト片 |
| トークン ID | トークンに対応する数値 ID |
| ボキャブラリサイズ | 既知のトークン ID の数 |
| 埋め込み | トークン ID をベクトルに対応付ける |
| d_model | モデル内部のベクトルの幅 |
| コンテキスト長 | 一度に処理できる最大トークン数 |
4.6.2 流れ
"The agent opened a pull request."
|
| Tokenization
v
[791, 8479, 9107, 264, ...]
|
| Embedding lookup
v
[context_length, d_model] matrix
4.6.3 核心のメッセージ
トークナイゼーションと埋め込みは、テキストを Transformer に入力する仕組みそのものです。トークナイゼーションがテキストをモデルに読める単位に切り分け、埋め込みがその単位を行列演算に参加できるベクトルへと変換します。
チャプターチェックリスト
本章を読み終えたあと、次のことができるようになっているはずです。
- なぜトークナイゼーションが必要なのかを説明できる
- 文字単位のトークナイゼーションと BPE 系のトークナイゼーションの違いを述べられる
-
vocab_size、d_model、コンテキスト長の意味を説明できる - トークン ID をベクトルに変換する理由を説明できる
- 埋め込みテーブルのパラメータ数を計算できる
次章に向けて
ここまでがトークナイゼーションの全体像です。次に API がトークン単位で課金してきたら、それが何を数えているのかを正確に理解できているはずです。
これでテキストはベクトルになりました。しかし、まだ大事なものが一つ欠けています。それが 位置(position) です。
たとえば次の二つの文を見てください。
The agent tagged the reviewer.
The reviewer tagged the agent.
ほぼ同じ単語が並んでいるのに、意味は異なります。第5章では、モデルがそれぞれのトークンが系列のどこにあるかをどう知るのかを説明します。
ここまでお付き合いいただきありがとうございました。次の章でまたお会いしましょう。