一文要約: Transformer の順伝播はパイプラインです — テキスト → トークン → Embedding + 位置 → N 個のブロック (Attention + FFN) → 語彙への線形射影 → Softmax 確率 → 予測される次トークン。このパイプラインを理解すれば、GPT がどのように「考える」かを理解できます。
15.1 全体像: Decoder-Only アーキテクチャ
15.1.1 GPT、LLaMA、Claude はすべて Decoder-Only
現代の言語モデル — GPT、LLaMA、Claude — はすべて Decoder-Only アーキテクチャを採用しています。元の Transformer の Encoder-Decoder 設計とは異なり、Decoder-Only はデコーダースタックのみを残し、自己回帰的な生成に特化しています。
15.1.2 GPT-2 と GPT-1 のアーキテクチャ比較
これら2つのモデルは Decoder-Only という骨格を共有しています。主な違いは LayerNorm の配置です。
| GPT-1 (Post-Norm) | GPT-2 (Pre-Norm) | |
|---|---|---|
| LayerNorm の位置 | Attention/FFN の後 | Attention/FFN の前 |
| 学習の安定性 | やや不安定 | より安定 |
| 現代のモデル | — | LLaMA、GPT-3、それ以降のほぼすべて |
Pre-Norm は今や標準です。本章では GPT-2 を参照モデルとして使い、データの流れを下から上へ追跡していきます。
15.1.3 完全なパイプライン全体像
入力テキスト: "The agent opened a pull request for"
|
Step 1: トークン化
|
Step 2: Word Embedding
|
Step 3: 位置エンコーディング
|
Steps 4-6: N × Transformer Block (GPT-2 Pre-Norm スタイル)
(LayerNorm → Attention → 残差 → LayerNorm → FFN → 残差)
|
Step 7: 最終 Layer Norm
|
Step 8: Linear → Softmax → 出力確率
|
予測された次トークン: "review" (最高確率)
15.2 Step 1-3: 入力処理
15.2.1 Step 1: トークン化
テキストが数値になります。tiktoken の cl100k_base を使うと、
入力: "The agent opened a pull request for"
トークン ID: [791, 8479, 9107, 264, 6958, 1715, 369]
長さ: 7 トークン
各単語またはサブワードは固有の整数 ID にマップされます。トークナイザは文字を見ているのではなく、学習済みの語彙エントリを見ているのです。
15.2.2 Step 2: Word Embedding
トークン ID は ルックアップテーブルを介してモデルに入力されます。
トークン ID [7]
| Embedding ルックアップ (vocab_size × d_model 行列)
トークン Embedding [7, 512]
各トークンは、そのトークンに関する意味情報を担う 512 次元ベクトルになります。意味が幾何として存在する最初の場所です。
15.2.3 Step 3: 位置エンコーディング
Attention には順序の感覚が組み込まれていません。位置情報がなければ、モデルは「the agent tagged the reviewer」と「the reviewer tagged the agent」を区別できません。位置エンコーディングはこれを解決します。
トークン Embedding [7, 512]
| + 位置エンコーディング [7, 512]
入力ベクトル [7, 512]
主な戦略は2つあります。
- 元の Transformer: 固定の正弦波関数 (学習不要)
- GPT 系: 学習される位置 Embedding (エンドツーエンドで学習)
いずれの場合でも、すべての位置に固有のエンコーディングが与えられ、近い位置同士は似たエンコーディングを持ちます。
出力: 各トークンは、それが何であるかとどこに位置するかを同時にエンコードした 512 次元ベクトルになります。
15.3 Step 4: Transformer Block の内部
15.3.1 ブロックの構造
各 Transformer Block は2つのサブレイヤーを持ちます。
入力 X [7, 512]
|
+-------------------------------+
| LayerNorm |
| | |
| Multi-Head Attention | <- トークン間の関係を理解
| | |
| Dropout -> + X (残差) |
+-------------------------------+
|
+-------------------------------+
| LayerNorm |
| | |
| Feed Forward Network | <- 特徴変換
| | |
| Dropout -> + X (残差) |
+-------------------------------+
|
出力 [7, 512]
決定的な性質は、入力が [7, 512] で、出力もやはり [7, 512] であることです。次元はどのブロックを通っても変わりません。最終射影だけがこの不変量を破ります。
15.3.2 Multi-Head Attention の詳細
Attention は Transformer の核です。ステップごとに分解していきましょう。
Step 4.1: Q、K、V の生成
入力 X [7, 512]
| × Wq, Wk, Wv (3つの重み行列)
Q, K, V それぞれ [7, 512]
| ヘッドに分割
各ヘッド: Q, K, V それぞれ [7, 64] (8 ヘッドの場合)
Step 4.2: Attention スコアの計算
Q と K の内積は類似度を測ります — トークン i がトークン j にどれだけ注目すべきかを示します。
Step 4.3: Attention 行列の可視化
Q × K^T の生の結果は 7×7 の行列です。各セルは1組のトークン位置間の類似度スコアです。色が濃いほど類似度が高いことを意味します。
Step 4.4: 因果マスクの適用
下三角マスクは上三角を -inf に設定します。Softmax の後、-inf は 0 になります。これが因果マスク (Causal Mask) です — 各位置は自分より前 (または自身) のトークンしか見ることができません。これにより、teacher forcing を使った学習が安全になり、推論時に正直なふるまいが保証されます。
Step 4.5: Softmax と重み付き和
Attention 重み = Softmax(マスク済みスコア)
出力 = Attention 重み × V
各位置の出力は、すべての V ベクトルの重み付き平均で、重みが Attention スコアです。モデルは学習中に何に注目すべきかを学習しました。
15.3.3 Feed Forward Network
FFN は各トークン位置に独立に作用するシンプルな2層ネットワークです。
入力 [7, 512]
| Linear: 512 → 2048 (4 倍に拡張)
| ReLU 活性化
| Linear: 2048 → 512 (モデル幅に戻す)
出力 [7, 512]
FFN はモデルの「事実知識」の大部分を蓄えています。すべてのパラメータの半分近くを占めます — これについては、後のパラメータ数のセクションで詳しく見ていきます。
15.4 Step 5-6: 残差接続と LayerNorm
15.4.1 なぜ残差接続なのか?
すべてのサブレイヤーは、計算を残差接続でラップします。
output = x + sublayer(x) # 違う: output = sublayer(x)
利点は次の通りです。
- 勾配は恒等経路を通って直接逆方向へ流れることができ、消失を回避できる
- ネットワークは学習の不安定性なしに多くの層を積み重ねることができる
- サブレイヤーが何も有用なものを学ばなくても、元の信号はそのまま通過する
これは第13章で出てきたバイパスレーンです。これがなければ、48 層の GPT-2 は収束しないでしょう。
15.4.2 LayerNorm の配置
GPT-2 は Pre-Norm を採用しています。
# Pre-Norm (GPT-2、LLaMA、ほとんどの現代モデル)
output = x + attention(layernorm(x))
# Post-Norm (元の Transformer、2017)
output = layernorm(x + attention(x))
Pre-Norm はサブレイヤーの前で入力を正規化し、結合された出力を正規化しません。これにより、特にパラメータのスケールが予測不可能な学習初期において、学習が安定化します。
15.5 Step 7: 複数ブロックのスタック
15.5.1 N 回の繰り返し
GPT-2 はモデルサイズに応じて 12 から 48 のブロックを積み重ねます。
Block 1 [7, 512] → Block 2 [7, 512] → ... → Block 12 [7, 512]
各ブロックは、
- 形状
[seq, d_model]を保持する - もう一度の Attention + FFN で表現を洗練する
- 深さが増すにつれて、ますます抽象的な特徴を構築する
初期のブロックは構文や局所的なパターンを処理する傾向があります。後段のブロックはより長距離の依存関係や抽象的な意味を扱います。これは設計上の決定ではなく、学習から創発したものです。
15.5.2 すべてのパラメータがどこにあるか
| コンポーネント | パラメータ式 | 例 (d_model=512、vocab=100,256) |
|---|---|---|
| Word Embedding | vocab × d_model | ~51M |
| Attention (×12) | 4 × d_model² × 12 | ~12.6M |
| FFN (×12) | 8 × d_model² × 12 | ~25.2M |
| 出力 Linear | d_model × vocab | ~51M |
15.6 Step 8: 出力マッピング
15.6.1 最終 LayerNorm
すべてのブロックの後、射影の前にもう一度 LayerNorm を適用します。
Block 12 出力 [7, 512]
| LayerNorm
正規化済み出力 [7, 512]
15.6.2 Linear レイヤー: 語彙への射影
肝となるステップ: 512 次元の隠れベクトルを 100,256 次元のロジットベクトルにマップします。
入力 [batch, seq, d_model] = [4, 7, 512]
| @ Wp [d_model, vocab_size]
出力 [batch, seq, vocab_size] = [4, 7, 100256]
15.6.3 Wp 行列の意味
Wp は次のように考えてください。語彙のすべてのトークンが、d_model 次元の特徴ベクトル (signature) を持っている。 トークン i の出力ロジットは、現在の隠れ状態とトークン i の特徴ベクトルの内積 — すなわち類似度スコアです。
内積が高い → ロジットが高い → モデルはこのトークンが次トークンとして可能性が高いと判断する。
15.6.4 Softmax で確率へ
ロジット [7, 100256]
| Softmax (最後の次元について)
確率 [7, 100256]
これで各位置に語彙上の確率分布ができました。
- すべての確率は合計して 1 になる
- 最高確率のトークンがモデルの予測
- 完全な分布はサンプリング戦略が利用するもの
15.7 完全な形状追跡
15.7.1 入力から出力まで
token_ids: [batch=4, seq=7]
Steps 1-2: Embedding: [4, 7, 512]
Step 3: + 位置: [4, 7, 512]
Steps 4-6: Blocks 1-12: [4, 7, 512] <- 形状は変わらない!
Step 7: 最終 LayerNorm: [4, 7, 512]
Step 8: Linear: [4, 7, 100256]
Softmax: [4, 7, 100256] <- ここで確率に
最後の位置を取る: [4, 100256]
argmax: [4] <- シーケンスごとの予測トークン ID
次元はすべてのブロックを通して d_model で安定しています。最後にだけ vocab_size へと跳ね上がります。
15.7.2 主要な次元パラメータ
| パラメータ | 意味 | GPT-2 Small | GPT-2 Large |
|---|---|---|---|
d_model | モデル幅 | 768 | 1280 |
n_layers | ブロック数 | 12 | 36 |
n_heads | Attention ヘッド数 | 12 | 20 |
d_ff | FFN 隠れ次元 | 3072 | 5120 |
vocab_size | 語彙サイズ | 50,257 | 50,257 |
15.8 パラメータ数
15.8.1 コンポーネント別内訳
GPT-2 Small を例に取ります (d_model=768、n_layers=12、vocab_size=50,257)。
| コンポーネント | 式 | パラメータ数 |
|---|---|---|
| Token Embedding | vocab × d_model | ~38.6M |
| Position Embedding | max_len × d_model | ~0.8M |
| Attention (×12) | 4 × d_model² × 12 | ~28.3M |
| FFN (×12) | 2 × d_model × d_ff × 12 | ~56.6M |
| LayerNorm (×25) | 2 × d_model × 25 | ~0.04M |
| 出力射影 | Token Embedding と共有 | 0* |
*出力射影は通常、Token Embedding テーブルと重みを共有します (weight tying)。これは最適化ではなく、「トークンの意味をエンコードする幾何と、トークンの尤度をスコア付けする幾何は同じであるべきだ」というモデリング上の選択です。
合計: 約 1 億 2400 万パラメータ。
15.8.2 パラメータの分布
Embedding: ~31% ||||||||
Attention: ~23% ||||||
FFN: ~46% ||||||||||||
LayerNorm: <1%
FFN がパラメータの半分近くを占めています。FFN 層がモデルの知識を蓄えていると言われるのはこのためです — 単純にそこに置き場所が多くあるからです。
15.9 学習中の誤差逆伝播
15.9.1 損失関数
学習中はターゲット (実際の次トークン) がわかっているので、交差エントロピー損失を計算できます。
Loss = CrossEntropy(predicted_probs, target_token)
15.9.2 勾配の流れ
損失はすべてのコンポーネントを通って後方へ伝播します。
Loss
|
出力射影 (Wp) <- 更新
|
LayerNorm <- 更新
|
Block 12 (Attention、FFN) <- 更新
|
...
|
Block 1 <- 更新
|
Embedding <- 更新
ここでは残差接続が決定的に重要です。各サブレイヤーをバイパスする勾配のハイウェイを提供し、深さによって学習が止まってしまうような勾配消失を防ぎます。
15.10 章のまとめ
15.10.1 8 ステップの順伝播
| ステップ | 操作 | 形状の遷移 |
|---|---|---|
| 1 | トークン化 | テキスト → トークン ID |
| 2 | Embedding | ID → ベクトル [seq, d_model] |
| 3 | + 位置 | 位置情報を加算 |
| 4 | Attention | トークン間の関係を捉える |
| 5 | 残差 + Norm | 学習を安定化 |
| 6 | FFN | 特徴変換 |
| 7 | × N ブロック | ステップ 4-6 を繰り返す |
| 8 | Linear + Softmax | 出力確率分布 |
15.10.2 パラメータの分布
| コンポーネント | パラメータの割合 | 役割 |
|---|---|---|
| Embedding | ~30% | トークンの意味表現 |
| Attention | ~25% | トークン間の関係を捉える |
| FFN | ~45% | 知識の蓄積、特徴変換 |
15.10.3 核心の洞察
Transformer の順伝播は優美なパイプラインです。トークンはベクトルになり、N 層の Attention (文脈理解) と FFN (特徴抽出) を通り抜け、語彙サイズの確率分布へと射影されます。形状はすべてのブロックを通して
d_modelに固定されます — 最終射影だけがその不変量を破ります。
章のチェックリスト
この章の後、以下ができるようになっているはずです。
- Transformer の順伝播の 8 ステップすべてを説明できる。
- トークン ID からロジットまでテンソル形状を追跡できる。
- 因果マスクが何をし、なぜ必要なのかを説明できる。
- FFN がパラメータの半分近くを占める理由を説明できる。
-
d_model、n_layers、vocab_sizeから各コンポーネントのパラメータ数を見積もれる。
コード実装
ここで述べた完全な順伝播は、第 5 部 (第 18 章〜第 20 章) で段階的に実装されます。
- 第 18 章:
model.py— モデル定義 - 第 19 章:
train.py— 学習ループ - 第 20 章:
inference.py— 推論ロジック
次章へ
これが完全な順伝播です。図を見ずに、入力テキストから出力確率までテンソルを追跡できるようになっていれば、第 16 章へ進む準備は万全です。
第 16 章では、学習と推論を比較します — 同じ順伝播ですが、まったく異なる2つのモードで動作します。この区別を理解することは、本番環境で多くの混乱が宿る場所でもあります。それでは、また次章でお会いしましょう。