チャプター 02 · トークン化 · 8 min

テキストからトークンへ

テキストが数値になる仕組み。BPE、サブワード、そしてLLMが文字を数えるのが苦手な理由。

なぜトークンが必要なのか

言語モデルはテキストを直接処理できない。処理するのは数字だ。LLMに話しかけるたびに最初に行われることは、テキストを整数の列——トークンID——に変換することだ。

トークン化とは、この変換を可能にする分割処理のことだ。

なぜ1単語1トークンではないのか

一見すると、1単語=1トークンと考えるかもしれない。シンプルだ。

しかし、それではうまくいかない:

  • 言語には数百万もの可能な単語が含まれる(活用形、新語、固有名詞、タイプミス……)。1単語1トークンでは巨大な語彙が必要になる。
  • モデルは一度も見たことのない単語を処理できない。
  • 中国語や日本語などの言語では、単語間にスペースがない。

ほぼすべての現代LLMが採用した解決策:サブワード

サブワードトークン化

サブワードトークナイザーでは:

  • 頻繁な単語は単一のトークンになる(です
  • 珍しい単語は小さな部品に分割される(トークン化トークン +
  • 未知の文字は常に個別の文字まで分解できる

結果として、合理的なサイズの語彙(典型的には3万から25万トークン超まで。最近のトークナイザーははるかに多くの言語をカバーするため、この幅は世代を追うごとに上がっている)がどんなテキストでも表現できる。

最も広く使われているアルゴリズムは**BPE**(Byte Pair Encoding)と呼ばれる。個別の文字から始め、訓練コーパスで最も頻繁に出現するペアを反復的にマージしていく仕組みだ。

BPEを30秒で理解する

3単語だけの小さなコーパスを想像しよう:lowlowerlowest。まず文字レベルでトークン化する:

l o w
l o w e r
l o w e s t

各反復で、最も頻繁な隣接ペアを探す。ここでは、l oが3回出現する——これをloにマージする:

lo w
lo w e r
lo w e s t

次にlo wが最も頻繁なペアになる。マージする:

low
low e r
low e s t

望む語彙サイズに達するまで続ける。よく現れる断片(low)は単一のトークンになる。珍しいもの(est)は分解されたままになる。これがまさにBPEの動作だ——3単語ではなく数十億の単語に対して、そして現代のモデルでは文字ではなくバイト単位で(バイトレベルBPE)処理することで、どんな入力も「未知」になることがないことを保証している。

知っておくべきいくつかの仲間:WordPiece(BERT)とUnigram LM(T5、mT5)は、BPEと同じく語彙を構築するためのアルゴリズムだ。ここでよくある混同に注意したい。同列に挙げられがちなSentencePieceはアルゴリズムではなくライブラリであり、BPEとUnigramの両方を実装している。T5、mT5、そして初期のLlama(1と2)で使われたのはこれだ。Llama 3(2024年)以降、Metaはtiktokenの流儀に近い12万8000トークンのバイトレベルBPEに切り替えた。いずれも同じアイデア——サブワード語彙——を共有しているが、ヒューリスティックが異なる。

特殊トークン

テキストのサブワード以外に、トークナイザーは自然には現れない特殊トークンをいくつか予約している:

  • <|im_start|><|im_end|>(OpenAI)、[INST]…[/INST](Llama 2とMistral)、<|start_header_id|><|eot_id|>(Llama 3以降)、<|user|> / <|assistant|> ——会話のターンを区切る。モデルのファミリーごとに独自の形式があり、それは世代が変わるたびに変わる。
  • <|endoftext|> ——ドキュメントの終わり。
  • <|fim_prefix|><|fim_middle|> ——コード補完で使われるfill-in-the-middle用。

これらが、*「ユーザーがXと言い、アシスタントがYと答えた」*という対話を、モデルが処理できる線形のトークン列に変える役割を果たす。ChatGPTにメッセージを送ると、これらのマーカーがトークン化の前に自動的に追加されている。

試してみよう

右側にサブワードが表示される:各トークンは再利用可能な断片であり、必ずしも完全な単語ではない。頻繁に使われる語は 1 つのトークンに収まり、まれな語は複数の断片に分解される。

注目すべきいくつかの点:

  • 短くて頻繁な単語はほとんど分割されない。
  • 長い単語や珍しい単語は複数の部品に分割されることが多い。
  • 単語の前のスペースはトークンの一部だ(だから ·hellohello は異なるトークン)。
  • 日本語では、英語よりもトークン/文字の比率が高くなる傾向がある(GPT-3/GPT-4世代のトークナイザーでは特に顕著だった)——モデルは英語のテキストをより多く学習している。語彙がはるかに大きく多言語的になった最近のトークナイザーは、この差をかなり縮めた。ただし消し去ってはいない。日本語は依然として英語より割高だ。

実用的な影響

このトークンという仕組みには、予想外の影響がたくさんある:

  • LLM文字を数えるのが苦手だ。「strawberryにRはいくつある?」は2024年の有名な引っかけ問題になった。多くのモデルが3ではなく2と答えていた。単語がいくつかのトークンとして届き、個別の文字としては届かないからだ。今日では大手のモデルは正解する。だが構造的な原因は一ミリも動いていない。モデルは迂回することを覚えただけだ——数える前に単語を一文字ずつ書き出す。最近のモデルにこの質問をしたら、その推論を見てみるといい。この綴り出しのステップがよく現れる。それこそが、直接数えることは今も機能していないという告白だ。
  • APIの料金はトークン単位で計算され、単語単位ではない。トークン化効率の低い言語は処理コストが少し高くなる。
  • コンテキストウィンドウ128kトークン200kトークン……)もトークンで測られる。10万語の本は約13万トークンになる。

モデルにとって、「トークン化」と「トーク・ン・か」は同じものだ。部品しか見えていない。

次へ

テキストが整数の列になったので、それらの整数がモデルに入力される。モデルの最初のステップでは、これらがベクトル——意味が幾何学的な位置になる数百次元の空間——に変換される。

それが次の章のテーマだ。

更新日