トークナイゼーション
テキストをトークン (単語やサブワードなどの処理単位) に分割する処理。
トークナイゼーション (tokenization) は、テキストを処理の基本単位であるトークンに分割する処理です。自然言語処理 (NLP) や大規模言語モデル (LLM) の入力前処理として不可欠な工程であり、分割の粒度や方式によって後続の処理精度が大きく左右されます。トークンの単位は単語、サブワード、文字、バイトなど目的に応じて選択され、同じテキストでもトークナイザの種類によって分割結果が異なります。
トークナイゼーションの代表的な手法には、単語単位の分割、サブワード分割、文字単位の分割があります。単語単位の分割は英語のようにスペースで区切られる言語では直感的ですが、未知語 (語彙に含まれない単語) を扱えない問題があります。この課題を解決するのがサブワード分割で、アルゴリズムとしては BPE (Byte Pair Encoding)、WordPiece、Unigram 言語モデルの系統が広く使われています。BPE は頻出する文字列のペアを繰り返し結合して語彙を構築する手法で、GPT シリーズのトークナイザ (tiktoken) に採用されています。WordPiece は BERT 系のモデルで使われてきた手法です。ここで混同しやすいのが SentencePiece で、これはアルゴリズムの名前ではなく BPE と Unigram 言語モデルの両方を実装したライブラリです。生の文をそのまま学習でき、事前の単語分割を必要としない点が特徴なので、「SentencePiece を使っている」という情報だけでは分割方式は決まりません。
日本語のトークナイゼーションは英語と比べて格段に複雑です。日本語にはスペースによる単語区切りがないため、形態素解析器 (MeCab、Sudachi、Janome など) を用いて単語境界を推定する必要があります。さらに、LLM 向けには SentencePiece のような言語非依存のサブワードトークナイザが使われることが多く、日本語の漢字やひらがなが細かいサブワードに分割されます。たとえば「東京都」は「東京」「都」や「東」「京」「都」のように分割される場合があり、トークナイザの語彙サイズによって結果が変わります。
実務でトークナイゼーションが特に重要になるのは、LLM の利用コスト管理です。ChatGPT や Claude などの API は入出力のトークン数に基づいて課金されるため、同じ内容でもトークン数が少ないプロンプトのほうがコストを抑えられます。日本語は英語に比べてトークン効率が悪い (同じ意味の文章でもトークン数が多くなる) 傾向があり、日本語 1 文字が 1〜3 トークンに分割されることも珍しくありません。このため、日本語でのプロンプト設計ではトークン数を意識した文章の簡潔化が重要です。
よくある誤解として、「文字数 = トークン数」と考えてしまうケースがあります。実際には英語では 1 単語が 1〜2 トークン程度ですが、日本語では 1 文字が複数トークンになることがあり、文字数とトークン数は一致しません。また、トークナイザはモデルごとに異なるため、GPT-4 と Claude では同じテキストでもトークン数が異なります。トークン数を正確に把握するには、各モデル専用のトークナイザを使って事前に計算する必要があります。
目的による使い分けも押さえておきたいところです。検索インデックスの作成やキーワードの集計のように「人が意味を取れる単位」が欲しい場面では形態素解析が向き、モデルへ入力を渡す場面ではそのモデル専用のサブワード分割を使うしかありません。前者の結果を後者の代わりに使うと、トークン数の見積もりが実際の課金と合わなくなります。さらに分割結果は分割器そのものより「辞書や語彙の版」に左右されます。同じ MeCab でも辞書を IPAdic から UniDic に替えれば単語の切れ目や品詞が変わり、集計結果がずれます。LLM 側もモデルを乗り換えたり新しい世代へ上げたりすると語彙が入れ替わるため、以前に測った見積もりはそのまま使えません。トークン数を根拠に上限や料金を設計するときは、使った分割器とその版を記録しておくと、後から差分の原因を追えます。
文字数カウントとの関連では、テキストの「長さ」を測る尺度として文字数、バイト数、トークン数の 3 つが実務で使い分けられています。SNS の投稿制限は文字数、LLM の入出力制限はトークン数で管理され、データベースのカラム上限は製品や型の指定方法によって文字数とバイト数のどちらで数えるかが変わります。3 つの尺度は互いに換算できないため、どの制限に引っかかっているのかを先に切り分けることが、切り詰めや分割の設計を誤らない前提になります。