← 機械学習テキスト 一覧

🎓 レベル:基礎 | 重要度:A(必須)

📎 前提:Transformer自己回帰モデル

要点(BLUF)


1. LLM とは:「次トークン予測」に尽きる

LLM を一言でいうと、巨大な Transformer + 次トークン予測です。難しそうな見た目に反して、やっていることは一つの条件付き分布を出すことだけです。

言語モデル(language model)は、トークン列 x1,x2,x_1, x_2, \dots に対して、次のトークンの確率分布を返す関数として定義されます。

LM:x<t=(x1,,xt1)    p(xtx<t)\text{LM}: \quad x_{<t} = (x_1, \dots, x_{t-1}) \;\longmapsto\; p(x_t \mid x_{<t})

そして文全体の確率は、自己回帰モデルで見た**乗法定理(チェインルール)**でそのまま積に分解されます。

p(x1,,xn)=t=1np(xtx<t)p(x_1, \dots, x_n) = \prod_{t=1}^{n} p(x_t \mid x_{<t})

要するに: 「文を生成する」という大層なタスクは、「前を見て次の1個を当てる」を左から右へひたすら繰り返すことに完全に等しい、というのが出発点です。近似は入っていません。LLM が学習するのは、この各因子 p(xtx<t)p(x_t\mid x_{<t}) を Transformer で表現することだけです。

自己回帰分解そのものの理屈(なぜ厳密尤度が計算できるか、teacher forcing、逐次生成が遅い理由)は 自己回帰モデル に書いたので、ここでは繰り返しません。本ノートは「要素=トークン・本体=Transformer」にしたLLM版の具体に焦点を当てます。


2. トークン化(tokenization):なぜサブワードか

LLM はテキストを直接は扱えません。まずトークンという離散単位の列に区切り、各トークンに整数ID(token ID)を振ります。この区切り方の粒度に、3つの選択肢があります。

粒度語彙サイズ系列長未知語・希少語
文字単位(character)小さい(数百〜数千)非常に長くなる未知語は出ないが、意味の単位が細かすぎる
単語単位(word)巨大(数十万〜)短い未知語(OOV)が必ず出る・活用形が爆発する
サブワード(subword)中庸(数万程度)中庸希少語を部分に分解して表現できる

現代のLLMはほぼ例外なくサブワードを採用します。理由は上の表のトレードオフにあります。

BPE(Byte-Pair Encoding)の考え方

代表的な学習法が BPE(バイト対符号化) です。発想は素朴で、「よく隣り合う組をくっつけて1つの語彙にする」を繰り返すだけです。

  1. 最初は全テキストを最小単位(文字、あるいはバイト)に分解する
  2. コーパス中で最も頻繁に隣接して現れるペアを1つ見つけ、それを新しい1トークンとして語彙に追加(マージ)する
  3. 目標の語彙サイズに達するまで 2 を繰り返す

要するに: 頻出する並びほど早く1トークンにまとまるので、ありふれた語は短く、珍しい語は細かい部品の列になります。語彙サイズという「予算」の中で、頻度の高いものを優先的に1単位へ昇格させる貪欲なアルゴリズムです。

⚠️ 要最新確認:具体的にどのトークナイザ(BPE / WordPiece / Unigram / byte-level BPE など)を使うか、語彙サイズが何万か、特殊トークンの設計などはモデルごとに異なり、世代ごとに変わります。「サブワードで区切る」「頻度ベースでマージする」という原理は安定していますが、個別スペックは採用モデルのドキュメントで確認してください。


3. 埋め込み(embedding):token → ベクトル

トークンID(ただの整数)のままでは計算できないので、各IDを密ベクトルに変換します。これが**埋め込み(embedding)**です。

要するに: トークン化が「言葉を離散IDに落とす」工程、埋め込みが「そのIDを意味を持った連続ベクトルに引き上げる」工程です。ここから先は全部ベクトルの計算になります。


4. 推論の流れ:自己回帰ループ

ここまでの部品を一本につなぐと、LLM の推論(生成)パイプラインができます。入力を1度処理して、あとは1トークンずつ生成して継ぎ足す——これがすべてです。

flowchart LR
    IN["入力テキスト(プロンプト)"] --> TOK["トークン化(サブワードIDの列)"]
    TOK --> EMB["埋め込み(ID→ベクトル + 位置情報)"]
    EMB --> TR["Transformer(マスク付き自己注意の多層)"]
    TR --> DIST["最終位置の次トークン分布 p(xt | x&lt;t)"]
    DIST --> SAMP["サンプリング(次の1トークンを選ぶ)"]
    SAMP -->|"選んだトークンを末尾に追加"| APP["系列を1つ伸ばす"]
    APP -->|"停止条件まで繰り返す(自己回帰)"| EMB
    APP --> OUT["出力テキスト"]

各ステップを言葉にすると:

  1. トークン化:入力テキストをサブワードIDの列にする。
  2. 埋め込み:各IDをベクトルに変換し、位置情報を加える。
  3. Transformer 本体:マスク付き自己注意(Transformer)を多層通す。因果マスクにより「各位置から見えるのは自分以前のトークンだけ」が保証され、未来を盗み見できません。
  4. 次トークンの分布:最後の層が各語彙トークンのロジット zRVz\in\mathbb{R}^{V} を出し、ソフトマックスで確率分布に変換します。
p(xt=vx<t)=exp(zv)vexp(zv)p(x_t = v \mid x_{<t}) = \frac{\exp(z_v)}{\sum_{v'} \exp(z_{v'})}

要するに: Transformer の出力(生のスコア=ロジット)を、足して1になる確率に正規化したものが「次に来るトークンの確率」です。 5. サンプリング:この分布から次の1トークンを選ぶ。常に最大確率を選べば貪欲法(greedy)、確率に従って引けばランダムサンプリング。温度 TT を入れた

pvexp(zv/T)p_v \propto \exp(z_v / T)

揺らぎの大きさを調整できます(T0T\to 0 で貪欲、TT を上げるほど分布が平らになり多様性が増す)。 6. 継ぎ足してループ:選んだトークンを系列の末尾に足し、停止トークンや上限長まで 2〜5 を繰り返す。これが自己回帰生成です。

プレフィルとデコード:並列と逐次

実装上、このループは2つの局面に分かれます。原理を理解するうえで効く区別です。

要するに: 「与えられた文脈を読む」のは並列で速く、「続きを書く」のは1文字ずつしか進めない、という非対称があります。LLM の推論コストやレイテンシの話は、ほぼこの「逐次デコード」が源です(詳細な最適化は要最新確認)。


5. 文脈窓(context window)

LLM が一度の推論で扱えるトークン数の上限を**文脈窓(context window)**と呼びます。

要するに: 文脈窓は「モデルの作業机の広さ」です。机からあふれた古い情報はその推論では考慮されません。

⚠️ 要最新確認:文脈窓が何トークンか(数千〜数百万まで世代差が大きい)、長文脈をどう実現しているかはモデル・バージョンごとに激しく変わります。最新値は採用モデルの公式情報で確認してください。


⚠️ よくある誤解・要最新確認


対応するシミュレーション

simulations/bpe_tokenization.py:LLMの入口で使われるサブワード分割(バイトペア符号化)を小さなコーパスで再現します。最初は文字単位から始め、「最も頻繁に隣り合うペア」を1つの新トークンに統合する、を繰り返すと、esestest_ のように頻出のかたまりが1トークンに育ち、コーパス全体の系列が短くなることを可視化します。未知語も既知の部分文字列に分解でき語彙の外に出ないのが利点です(温度サンプリングは 推論の実務)。

バイトペア符号化の逐次マージ


関連ノート