GPTの動作原理 — 自己回帰モデル

ChatGPTに「今日の天気は」と入力すると、次のように単語を1つずつ生成します。

入力: "今日の天気は"

予測: "晴れ"  ← 1単語生成

入力に追加: "今日の天気は晴れ"

予測: "で"

入力に追加: "今日の天気は晴れで"

予測: "す"

... 終端トークンが出るまで繰り返す

このように 前のトークンから次のトークンを予測することを繰り返す モデルを 自己回帰モデル(Autoregressive Model) と呼びます。GPT、Claude、Gemini、Llama……現代のチャット系LLMはすべて自己回帰モデルです。

graph LR
  A[今日の天気は] --> M1[Model]
  M1 --> B[晴れ]
  B --> A2[今日の天気は晴れ]
  A2 --> M2[Model]
  M2 --> C[で]
  C --> A3[今日の天気は晴れで]
  A3 --> M3[Model]
  M3 --> D[す]

  style A fill:#3b82f6,stroke:#1d4ed8,color:#fff
  style A2 fill:#3b82f6,stroke:#1d4ed8,color:#fff
  style A3 fill:#3b82f6,stroke:#1d4ed8,color:#fff
  style B fill:#14b8a6,stroke:#0d9488,color:#fff
  style C fill:#14b8a6,stroke:#0d9488,color:#fff
  style D fill:#14b8a6,stroke:#0d9488,color:#fff
自己回帰モデルは1トークンずつ予測し、出力を入力に追加して次を予測する

問題:訓練中に「未来をカンニング」してはダメ

自己回帰モデルを訓練するとき、「次の単語を当てる」という問題を出して正解を教えます。たとえば「今日の天気は晴れです」という訓練データなら、こんな問題を作ります。

# 訓練データ: "今日の天気は晴れです"

# 問題群:
位置1の「今日」: 入力「<開始>」→ 正解「今日」
位置2の「の」:   入力「今日」→ 正解「の」
位置3の「天気」: 入力「今日 の」→ 正解「天気」
位置4の「は」:   入力「今日 の 天気」→ 正解「は」
位置5の「晴れ」: 入力「今日 の 天気 は」→ 正解「晴れ」
位置6の「です」: 入力「今日 の 天気 は 晴れ」→ 正解「です」

ここで重要な制約があります。位置5の「晴れ」を予測するとき、未来の位置6「です」を見てはいけない。当然ですよね、推論時はまだ「です」を生成していないのですから。

ところが、Self-Attentionは すべてのトークン間で内積を計算してしまう 仕組みです。何の工夫もしないと、位置5は位置6を見てカンニングできてしまいます。

解決策:Causal Mask(因果マスク)

そこで登場するのが Causal Mask(因果マスク) です。「因果」とは「原因 → 結果」、つまり「過去 → 未来」の方向のみを許可する、という意味です。

仕組みは驚くほどシンプル。Attentionスコアの行列のうち、上三角部分(=未来側)に -∞ を入れる だけです。

# QK^T の行列(5×5、5単語の文)
# 行 = クエリ位置、列 = キー位置

         今日   の   天気   は   晴れ
今日   [ 0.5  -∞   -∞    -∞   -∞  ]
の     [ 0.3  0.8  -∞    -∞   -∞  ]
天気   [ 0.4  0.6  0.7    -∞   -∞  ]
は     [ 0.2  0.5  0.9   0.4   -∞  ]
晴れ   [ 0.1  0.3  0.8   1.2  0.6  ]
       ↑      上三角を -∞ で埋めた

なぜ -∞ なのか? ここで第5章のsoftmaxの式を思い出してください。

softmax(xᵢ) = e^xᵢ / Σⱼ e^xⱼ

x = -∞ なら、e^(-∞) = 0

つまり -∞ を入れると、softmax後にその位置の重みが 完全に0 になります。未来の情報がまったく混ざらない、というわけです。

graph LR
  A[QK^T 行列\n上三角に -∞] --> B[softmax 適用]
  B --> C[未来側は重み0\n過去だけ参照]
  C --> D[× V で加重平均]
  D --> E[各位置は\n自分以前の情報だけ\n取り込んだベクトル]

  style A fill:#3b82f6,stroke:#1d4ed8,color:#fff
  style C fill:#f97316,stroke:#ea580c,color:#fff
  style E fill:#14b8a6,stroke:#0d9488,color:#fff
-∞ → softmax → 0 のメカニズム。未来情報を完全に遮断する

並列訓練の魔法

Causal Maskには素晴らしい副産物があります。「次の単語を予測する」という6つの問題を、1回のAttentionで同時に解ける のです。

RNNだったら「位置1を計算→位置2を計算→…→位置6を計算」と6回逐次的に処理する必要がありました。Transformerは、Causal Mask付きAttentionを1回計算するだけで、6つの位置すべての出力(=次トークン予測)が並列に得られます。

RNN/LSTM(訓練時) Transformer(訓練時)
処理方式 時刻 t は t-1 を待つ(逐次) 全位置を1回で並列処理
n=1000のとき 1000回のステップが必要 1回のAttentionで全位置
GPU効率 低い 極めて高い
訓練速度 遅い 速い(Transformerの強みの1つ)

KVキャッシュ — 推論を高速化する仕組み

推論時に1トークンずつ生成するとき、毎回ゼロから全体を計算するのは大変な無駄です。「今日の天気は晴れ」→「で」を予測するとき、「今日」「の」「天気」「は」「晴れ」のKeyとValueは 前ステップで計算済み のはず。

そこで、計算したK・Vを保存して再利用する仕組みが KVキャッシュ(KV Cache) です。

graph TD
  S1[ステップ1\n今日 → の] --> CACHE1["K, V を保存\n[今日のK, 今日のV]"]
  CACHE1 --> S2[ステップ2\n今日 の → 天気]
  S2 --> CACHE2["追加保存\n[今日, の]のK,V"]
  CACHE2 --> S3[ステップ3\n今日 の 天気 → は]
  S3 --> CACHE3["追加保存\n[今日, の, 天気]のK,V"]
  CACHE3 --> S4[新しいトークンのQだけ\n計算して既存K,Vと内積]

  style CACHE1 fill:#f97316,stroke:#ea580c,color:#fff
  style CACHE2 fill:#f97316,stroke:#ea580c,color:#fff
  style CACHE3 fill:#f97316,stroke:#ea580c,color:#fff
  style S4 fill:#14b8a6,stroke:#0d9488,color:#fff
KVキャッシュ:過去のK, Vを保存し、新しいトークンのQだけ計算する

補足:BERTは因果マスクを使わない

ここまでGPT系(Decoder-only)の話をしましたが、BERT系(Encoder-only)モデルは 因果マスクを使いません

GPT系(Decoder-only) BERT系(Encoder-only)
Attention Causal Mask あり マスクなし(双方向)
用途 文章生成 文章理解・分類
訓練タスク 次トークン予測 Masked Language Modeling(穴埋め)
代表モデル GPT-4, Claude, Llama BERT, RoBERTa

BERTは「文章の穴埋め問題」を解くため、前後両方の文脈を見られた方が有利です。一方GPTは「次の単語を予測する」ため、未来を見てはいけません。同じTransformerでも、マスクの設計がモデルの目的を決める のです。

この章のまとめ

GPT系の自己回帰モデルは Causal Mask(上三角を-∞で埋める)により、訓練中の「未来カンニング」を防いでいます。-∞ → softmax → 0 のメカニズムで未来情報を完全に遮断し、しかも全位置を1回で並列に訓練できる優れた設計です。

推論時は逐次生成になりますが、KVキャッシュ で過去のK・Vを再利用し、高速化を図ります。

次の第9章では、Attentionの「隠れた弱点」を補う仕組み——Positional Encoding(位置エンコーディング)——を扱います。Attentionは順序を見ないので、位置情報を別途注入する必要があるのです。

理解度チェック

問題 0 / 50%
Q1

GPT系のような自己回帰モデルで「因果マスク」が必要な理由は何ですか?

キーボード: 1〜4 で選択、Enter で回答