トークナイゼーションとは?AIがテキストを処理する最初のステップ

what-is-tokenization Uncategorized

ChatGPTに質問すると、AIはまず「トークナイゼーション(Tokenization)」という処理を実行します。これは、テキストを「トークン」と呼ばれる小さな単位に分割する作業で、LLM(大規模言語モデル)がテキストを理解する最初のステップです。

トークナイゼーションの仕組みを理解すると、なぜAPIの料金がトークン数で決まるのか、なぜ日本語が英語より高コストなのか、コンテキストウィンドウをどう節約できるかが見えてきます。本記事では、その技術的背景を平易に解説します。

トークナイゼーションとは何か?

トークナイゼーションは、テキストを機械学習モデルが処理できる単位に分割する技術です。例えば、以下のように変換されます。

入力: "人工知能は面白い"

トークン分割(GPT-4の場合):
["人工", "知", "能", "は", "面白", "い"]

トークンID(数値化):
[12345, 67890, 11234, 56789, 99876, 54321]

この数値IDが、ニューラルネットワークに入力されます。なぜ単語そのままではなく、トークンに分割するのでしょうか?

トークナイゼーションの目的

  1. 語彙サイズの制限: 世界のすべての単語を覚えるのは不可能なので、頻出する「部分文字列」のリストを作る
  2. 未知語への対応: 新しい単語も、既存トークンの組み合わせで表現できる
  3. 多言語対応: 異なる言語を同じトークン体系で扱える

トークナイゼーションの歴史

単語分割(Word-level Tokenization)

初期の自然言語処理では、空白やカンマで単語を分割していました。

"I love AI" → ["I", "love", "AI"]

問題点:
– 語彙が膨大(英語だけで数十万語)
– 「run」「running」「runs」を別の単語として扱う
– 未知語(typoや新語)を処理できない

文字分割(Character-level Tokenization)

文字1つ1つをトークンとする方法です。

"AI" → ["A", "I"]

問題点:
– 文字の並びから意味を学習するのが困難
– 長い文章で処理が非効率

サブワード分割(Subword Tokenization)

現代のLLMは、単語と文字の中間的な「部分文字列」をトークンとします。これがBPEやSentencePieceです。

"running" → ["run", "ning"]
"AI技術" → ["AI", "技", "術"]

頻出する部分は1トークン、まれな部分は複数トークンに分割されます。

BPE(Byte Pair Encoding):GPTの標準手法

GPTシリーズは、BPE(バイトペアエンコーディング)というアルゴリズムを採用しています。

BPEの仕組み

  1. 初期化: すべての文字を個別のトークンとする
  2. 頻出ペアの統合: 最も頻繁に隣接する文字ペアを1つのトークンに統合
  3. 繰り返し: 目標の語彙サイズ(例:50,000トークン)に達するまで繰り返す

:

初期: ["l", "o", "w", "e", "s", "t"]
"e", "s"が頻出 → ["l", "o", "w", "es", "t"]
"es", "t"が頻出 → ["l", "o", "w", "est"]
"l", "o"が頻出 → ["lo", "w", "est"]

この学習済みトークンリストを使って、新しいテキストを分割します。

GPT-4のトークナイゼーション例

OpenAIのTokenizer Toolで実際に試してみましょう。

入力: "ChatGPTは便利です"

トークン分割:
["Chat", "G", "PT", "は", "便利", "です"]
→ 6トークン

英語版:

入力: "ChatGPT is useful"

トークン分割:
["Chat", "GPT", " is", " useful"]
→ 4トークン

日本語が6トークン、英語が4トークンで、日本語の方がトークン数が多いことがわかります。これが料金に影響します。

SentencePiece:言語非依存のトークナイゼーション

Googleが開発したSentencePieceは、空白に依存しない多言語対応のトークナイザーです。LLaMA、PaLM、Claude、Geminiなどで採用されています。

BPEとの違い

  • 言語非依存: 日本語・中国語など空白がない言語も統一的に処理
  • 生テキスト学習: 前処理なしで学習し、トークン境界を自動決定
  • バイトフォールバック: 未知文字をバイト列として扱える

Unigram Language Model

SentencePieceは、BPEだけでなく「Unigram LM」というアルゴリズムも選択できます。これは、確率的に最適な分割を計算する手法です。

"人工知能" → 以下の候補から最尤を選択
- ["人工", "知能"] (確率: 0.6)
- ["人", "工", "知", "能"] (確率: 0.3)
- ["人工知能"] (確率: 0.1)

日本語トークナイゼーションの特殊性

日本語は英語と異なり、以下の特徴があります。

空白がない

英語は空白で単語が分かれますが、日本語は「私は人工知能を学んでいます」のように連続しています。そのため、トークナイザーは文字の連なりからトークン境界を推定する必要があります。

文字種の混在

ひらがな、カタカナ、漢字、アルファベット、数字が混在し、エンコーディングが複雑です。

トークン効率の低さ

GPT-4の場合、日本語は英語の約1.5〜2倍のトークン数になります。

英語: "Artificial Intelligence" → 2トークン
日本語: "人工知能" → 3トークン

これが、日本語でのAPI利用コストが高くなる理由です。

日本語特化トークナイザー

rinna、CyberAgentなどの日本企業が開発する日本語LLMは、日本語に最適化したトークナイザーを使用し、トークン効率を改善しています。

トークン数と料金の関係

OpenAI APIの料金は、トークン数に基づいて課金されます(2026年3月時点)。

GPT-4 Turboの料金例

  • 入力: $0.01 / 1,000トークン
  • 出力: $0.03 / 1,000トークン

料金計算例

ユーザー: "東京の観光名所を5つ教えてください"(8トークン)
GPT-4: "東京の主要観光名所は以下の通りです...(200トークン)"

入力コスト: 8 × $0.01 / 1,000 = $0.00008
出力コスト: 200 × $0.03 / 1,000 = $0.006
合計: $0.00608 ≈ 0.6円

大量の文書をプロンプトに含めるRAGシステムでは、入力トークン数が数千〜数万に達するため、コスト管理が重要です。

トークン数を減らす実践テクニック

1. 簡潔なプロンプト

不要な丁寧語や冗長な表現を削ります。

悪い例:

お忙しいところ恐縮ですが、もしよろしければ、
以下の文章を要約していただけますでしょうか。

→ 20トークン

良い例:

以下を要約してください。

→ 5トークン

2. チャンク分割

長文を小さな塊に分割し、必要な部分だけをLLMに送ります。

# 10,000トークンの文書を500トークンずつに分割
chunks = split_into_chunks(document, chunk_size=500)
# 関連するチャンクのみを検索で抽出
relevant_chunks = search(query, chunks, top_k=3)
# 1,500トークン程度に圧縮

3. 要約の活用

長い会話履歴を要約し、トークンを節約します。

過去100ターンの会話(10,000トークン)
 ↓ 要約
要約版(500トークン)→ プロンプトに追加

4. トークン効率の良いモデル選択

Claude 3は、日本語のトークン効率がGPT-4より優れている場合があります。用途に応じて使い分けます。

トークナイゼーションとエンベディング

トークナイゼーションは、エンベディングの前処理として機能します。

  1. トークナイゼーション: テキスト → トークンID列
  2. エンベディング: トークンID → 数値ベクトル
  3. Transformer処理: ベクトル列を処理

例えば「猫」というトークンは、常に同じID(例:12345)に変換され、同じエンベディングベクトルが割り当てられます。このエンベディングが、TransformerのAttention機構で文脈を考慮しながら更新されます。

トークナイゼーションの実装例

OpenAI APIでトークン数を取得

import tiktoken

# GPT-4のトークナイザーを読み込み
encoding = tiktoken.encoding_for_model("gpt-4")

text = "人工知能は未来を変える"
tokens = encoding.encode(text)

print(f"トークン数: {len(tokens)}")  # 出力: 7
print(f"トークンID: {tokens}")        # [12345, 67890, ...]
print(f"デコード: {encoding.decode(tokens)}")  # 元のテキスト

HuggingFaceのトークナイザー

from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("gpt2")
text = "Artificial Intelligence"

tokens = tokenizer.tokenize(text)
print(tokens)  # ['Art', 'ificial', ' Intelligence']

token_ids = tokenizer.encode(text)
print(token_ids)  # [3163, 9542, 9345]

トークナイゼーションの未来

動的トークナイゼーション

文脈に応じてトークン境界を動的に調整する研究が進んでいます。例えば「AI」は1トークンだが、「AI技術」では「AI」「技術」と分割する、といった適応的な処理です。

バイトレベルモデル

トークナイゼーションを完全に廃止し、バイト(8ビット)単位で直接処理するモデルも登場しています。これにより、未知語や多言語の問題が根本的に解決される可能性があります。

マルチモーダルトークン

テキスト・画像・音声を統一的なトークン体系で扱う研究が進んでいます。GPT-4Vは、画像を仮想的な「画像トークン」として扱い、テキストと同時に処理します。

FAQ

Q1. トークンと単語の違いは何ですか?

トークンは、モデルが処理する最小単位で、単語より小さい場合があります。「running」は1単語ですが、トークナイゼーションでは「run」「ning」の2トークンになることがあります。日本語では、1文字が1トークンになることも多いです。

Q2. トークン数の上限はどう決まっていますか?

モデルごとにコンテキストウィンドウ(一度に処理できるトークン数)が決まっています。GPT-4 Turboは128,000トークン、Claude 3 Opusは200,000トークンです。この上限を超えると、古い部分が切り捨てられます。

Q3. トークン数を事前に確認する方法はありますか?

OpenAIのTokenizer Toolや、tiktokenライブラリで確認できます。API呼び出し前に確認し、コストを見積もることが推奨されます。

Q4. 同じテキストでもモデルによってトークン数が変わりますか?

はい。GPT-4、Claude、LLaMAなど、モデルごとに異なるトークナイザーを使用しているため、同じテキストでもトークン数が異なります。料金やコンテキスト制限を比較する際は、各モデルのトークナイザーで確認が必要です。

関連記事

出典

  1. Sennrich, R., et al. (2016). “Neural Machine Translation of Rare Words with Subword Units”. ACL.
  2. Kudo, T., & Richardson, J. (2018). “SentencePiece: A simple and language independent approach to subword tokenization”. EMNLP.
  3. OpenAI (2023). “Tokenizer”. https://platform.openai.com/tokenizer
  4. Radford, A., et al. (2019). “Language Models are Unsupervised Multitask Learners”. OpenAI Blog.

コメント