テキストのトークナイゼーションは、人間の言語をAIが理解できる数値データに変換する重要なステップです。本記事では、その仕組みやBPEなどのアルゴリズム、トークナイザーの役割、言語ごとの違いまで詳しく解説します。言語モデルがどのようにテキストを処理し、トークンを通じて意味解析を行うのかを理解できます。
テキストのトークナイゼーションは、人間の言語をニューラルネットワークが理解できる数値データへと変換する最初のステップです。ニューラルネットワークは、人間のように文章全体を一度に読むわけではありません。モデルは、単語やスペース、句読点などからなるテキストを、まず数学的な計算に適した形へと変換する必要があります。この役割を果たすのがトークナイゼーションであり、言語モデルによるあらゆるリクエスト処理の初期段階となっています。
トークナイゼーションとは、元の文章をモデルが処理できる個々の要素に分割するプロセスです。これらの要素は、単語、単語の一部、記号、数字、句読点など様々です。
例えば、人間は「トークナイゼーション」という言葉を一つのまとまりとして捉えます。しかし、特定のモデルのトークナイザーはこれを一つのトークンとして扱う場合もあれば、複数の断片に分割する場合もあります。同様のことが、名前や専門用語、珍しい単語、異なる言語でも発生します。
その理由は簡単です。ニューラルネットワークは、直接文字や単語に対して数学的な操作を行うことができません。プロセッサが扱えるのは数値のみなので、テキストはまず数値の形に変換される必要があります。トークナイゼーションは、人間の言語と数学的モデルの間に位置する中間レイヤーとなるのです。
なお、トークナイゼーションは単なるスペースでの分割ではありません。たとえば、「ニューラルネットワークはテキストを理解する」というフレーズの場合、単純にスペースで区切ると3つの単語になりますが、実際のトークナイザーは、長い単語の一部や句読点、あるいは単語の複数の断片を抽出することがあります。結果は、使用するアルゴリズムや辞書によって異なります。
また、トークンは必ずしも単語の同義語ではありません。短い一般的な単語は1トークンになることもありますが、長い単語や珍しい単語は2つ、3つ、あるいはそれ以上のトークンに分割されます。逆に、一つのトークンが句読点や数字列、単語の一部になることもあります。
そのため、同じ単語数の2つの文章でも、トークン数が大きく異なる場合があります。また、同じ意味のテキストでも、日本語と英語では必要なトークン数が必ずしも一致しません。
トークナイザーは、入力された文章を自らの辞書の要素に基づき分割します。このとき、トークンの境界が単語の境界と一致するとは限りません。ある場合は単語全体がトークンとなり、別の場合は単語の一部や記号がトークンとなります。
例えば、「ニューラルネットワークはテキストを分析する」という文を考えましょう。人間なら3つの単語と1つの句読点を意識しますが、トークナイザーは次のように分割するかもしれません:
これはあくまで例であり、実際の分割はトークナイザーによって異なります。また、スペースもトークンに含まれる場合があり、同じ文字列でも文頭と文中で異なるトークンになることもあります。
このように辞書にすべての語形を保存する必要がなくなり、モデルは珍しい単語や複雑な語も、より基本的な断片から組み立てられるのです。
特定の文字列がトークナイザー作成時のデータで頻繁に出現していれば、独立したトークンとして登録されやすくなります。一般的な単語や語尾、記号の組み合わせは、より短いトークンで表現される傾向があります。
一方、珍しい専門用語、名前、長い複合語などは、辞書にそのまま存在しない場合が多く、トークナイザーによって既知の部分に分割されます。
例えば、「マイクロアーキテクチャ」は次のように分割される場合があります:
さらに大きな断片が辞書にない場合、さらに細かく分割されます。
特に言語によってこの違いは顕著です。英語に最適化された辞書では、英語のテキストは日本語やロシア語に比べてコンパクトにコーディングされるため、同じ意味のフレーズでも言語によってトークン数が異なる場合があります。
また、珍しい記号や絵文字、数字列、プログラムコードなども、人間にとっては短いものが、意外と多くのトークンに分割されることがあります。
トークナイザーとは、テキストをどのようにトークンへ分割・変換するかを定めるアルゴリズムおよびデータセットです。重要な要素として、各トークンに固有の数値IDを割り当てる辞書があります。
例えば、辞書の一部は次のようになることがあります:
数値はあくまで例であり、モデルごとに辞書やIDは異なります。ユーザーがリクエストを送信すると、トークナイザーは適切な要素を辞書から探し、シーケンスを作成します。単語が辞書になければ、より小さな要素で分割します。こうして、どんなテキストも既知のトークンの組み合わせとして表現できます。
辞書のサイズや構成方法によって、テキストの圧縮率や多言語対応、珍しい単語への対応が変わってきます。トークナイゼーションは単なる技術的な手続きではなく、言語モデルのアーキテクチャの重要な一部なのです。
トークナイゼーションで広く使われている手法の一つが、BPE(バイトペアエンコーディング)です。元々はデータ圧縮手法として考案されましたが、現在は言語モデルの辞書構築にも活用されています。
BPEの主な発想は、頻繁に出現する文字列をより大きな単位として統合することです。これにより、よく使われる単語やその一部を辞書にまとめて保存でき、珍しい語は短いトークンの組み合わせで表現できます。
例えば、辞書に単語単位だけを登録すると膨大なサイズになります。日本語やロシア語などの屈折語では、語形変化ごとにすべて登録するのは非効率的です。BPEなら、新しい名前や専門用語、商品名など、過去に存在しなかったものにも柔軟に対応できます。
逆に、すべてのテキストを1文字ずつ分割するだけでは、トークン列が長くなりすぎます。BPEはこの両極端の間の妥協点を見つける仕組みです。
たとえば、学習データに次の単語がよく出現したとします:
最初は1文字ずつ分割しますが、「ニ」+「ュ」や「ュ」+「ー」など、隣り合う文字の組み合わせの出現頻度をカウントし、最も多い組み合わせを新しい要素として統合していきます。「ニュー」や「ニューラル」などが独立したトークンになるイメージです。
このようにして、頻繁に使われるパターンを辞書にまとめておき、珍しい単語は既知の小さな断片で表現できるため、モデルは柔軟かつ効率的に膨大な語彙に対応できるのです。
BPE自体にも様々なバリエーションがあり、各モデルでトークン化ルールや辞書の大きさ、スペースや特殊文字の扱いが異なります。そのため、同じフレーズでもモデルごとに異なる数のトークンになることがあります。
しかし、目的は共通です。つまり、ほぼ無限に多様な人間のテキストを、有限個のトークンで表現できるようにすることです。トークナイザーがトークンを決めた後、それぞれに数値を割り当ててニューラルネットワークに渡します。
トークナイゼーション後、モデルが扱うのは単語ではなく、トークンのシーケンスです。しかし、トークン自体もそのままではネットワークに直接入力できません。次のステップは、各トークンに数値IDを割り当てることです。
トークナイザーの辞書では、すべてのトークンに固有の整数IDが対応付けられています。たとえば、「ニューラルネットワークはテキストを理解する」というフレーズは、まず次のように分割され、
さらに、次のようなIDのシーケンスに変換されます:
これらの数値もあくまで例です。実際の値はモデルごとに異なります。
このIDは、巨大なテーブルの中の行番号のようなものです。しかし、この番号だけではトークンの意味そのものは分かりません。
数値IDは、単にトークンの識別のためだけに使われます。例えば、「猫」が500、「犬」が9000というIDでも、「犬」が「猫」より18倍重要という意味にはなりません。IDはデータベースの行番号のようなものであり、それ自体は意味を持ちません。
そのため、各IDからベクトル(埋め込み)と呼ばれる多次元の数値セットが生成されて、モデルに渡されます。
各トークンについて、モデルは数百から数千の要素を持つ数値ベクトルを保存しています。ID「3817」なら、それに対応するベクトル例は:
このようなベクトルは、語同士の関係性や文脈の類似性を反映するように学習されます。ただし、ベクトルの各座標が「動物」や「感情」など特定の意味を持つわけではありません。意味は多数のパラメータに分散して表現され、モデル全体の文脈で機能します。
さらに、語順情報なども加味され、たとえば同じ単語でも順序が異なると意味が変わることが考慮されます。
フロー全体は次のようにまとめられます:
ユーザーが普通の文章を入力すると、トークナイザーが複数のトークンに分割し、それぞれが数値に置き換えられ、対応するベクトルがモデルに渡されて、トークン間の関係や文脈が解析されます。この段階で人間の言葉が数学的データに変換され、ニューラルネットワークによる計算が可能になるのです。
トークナイゼーション自体がテキストの意味を決定するわけではありませんが、テキストがどのような形でモデルに渡されるかを直接左右します。フレーズがよく知られたトークンに分割されるほど、モデル内部でコンパクトに表現され、シーケンスとして処理しやすくなります。
例えば、「猫」「子猫」「ネコちゃん」といった単語は、モデルによって異なるトークンの分割となる場合があります。ある単語は1トークン、別の単語は2つまたはそれ以上のトークンに分かれることもあります。この後、ニューラルネットワークは文脈を考慮して、これらの要素間の関係性を学習します。
珍しい用語ではトークナイゼーションの効果が顕著です。頻繁に出現する単語は大きめのトークンで表現されますが、まれな専門用語や新語、化学式などは多くの断片に分かれることもあります。
例えば、
これでも、モデルはトークンのシーケンスとして文脈を理解し、意味解析が可能です。ただし、こうした珍しい単語はより多くのトークンを消費します。
ユーザー名、URL、シリアルナンバー、ランダムな記号列やコードなども同様で、人間には短い文字列が、トークン数としては意外と長くなる場合もあります。
また、トークナイザーの辞書は特定のデータセットに基づいて作られるため、言語ごとにトークン化の効率が異なります。英語のフラグメントが大きなトークンとしてまとめられていれば、同じ情報量でも日本語やロシア語ではより多くのトークンが必要になるケースもあります。
特に長文を扱う際は、モデルの「コンテキストウィンドウ」はトークン数で制限されているため、見た目のテキスト量が同じでも、言語や語彙によって利用できる文脈量が変わることがあります。
ただし、トークナイゼーションによって「理解」が発生するわけではありません。モデルは、単語を複数のトークンに分割した後、全体のシーケンスとその関係性をベクトル空間で解析します。
たとえば、「キー」という単語は、道具、水源、暗号化の鍵、システムのアクセスキーなど複数の意味を持ちますが、トークナイザーは単にトークンに分割するだけで、その意味を選びません。本当の意味づけは、モデルが文脈全体を解析する後続プロセスで行われます。
したがって、「ニューラルネットワークがテキストをどのように理解するか」という問いへの答えは、トークナイゼーションから始まり、それだけでは終わらないのです。トークナイザーが人間の言語を計算しやすい形に変換し、その後のコンテキスト処理や関係性の解析は、言語モデル内部で実行されます。
テキストのトークナイゼーションは、通常の人間の言葉をニューラルネットワークで処理可能なデータへと変換する最初のステップです。テキストはトークンに分割され、各トークンに数値IDが割り当てられ、その後、モデルはベクトル表現を用いて計算を行います。
トークンは必ずしも単語と一致するわけではなく、単語全体のこともあれば、部分、記号、句読点の場合もあります。そのため、トークン数はテキストの長さだけでなく、言語、語彙、トークナイザーの仕様によっても左右されます。
Byte Pair Encodingのようなアルゴリズムは、全単語を辞書に登録する非効率さと、1文字ずつ分割する煩雑さの中間を実現します。頻繁に使われるパターンは大きなトークンとして、珍しい単語は小さな断片の組み合わせで表現されます。
このように、テキストが言語モデル内でたどる流れは次のようにまとめられます:
人間のテキスト → トークナイザー → トークン → 数値ID → ベクトル → ニューラルネットワーク
このプロセスを理解することで、なぜChatGPTなどの言語モデルがコンテキスト量をトークン数で管理するのか、なぜ同じ長さのテキストでもコンテキスト消費量が異なるのか、普通の文章がどのように計算可能な数値データへと変換されるのかを深く知ることができます。
さらに詳しい解説は、「AIとトークン:ChatGPTはなぜ単語ではなくトークンを数えるのか」をご覧ください。