Transformer の計算グラフによる構造解説

🧑 User

2026-06-09T15:07:35.983313Z

Transformer の構造と動作を計算グラフで説明してください。


🤖 Claude

2026-06-09T15:09:22.567886Z

Transformerは、エンコーダ・デコーダ構造とSelf-Attentionという2つの核心アイデアから成っています。全体の計算グラフを順番に見ていきましょう。

🖼️ Diagram: transformer_architecture_overview

Transformer アーキテクチャ全体図 入力埋め込みからエンコーダ・デコーダを経て出力確率分布までの計算グラフ Encoder Input Embedding トークン → d_model次元ベクトル Positional Encoding sin/cos で位置情報を加算 × N layers Multi-Head Self-Attention Q, K, V → Scaled Dot-Product Add & Norm Feed Forward Network Linear → ReLU → Linear Add & Norm Encoder Output (K, V) K, V Decoder Output Embedding 生成済みトークンの埋め込み Positional Encoding sin/cos で位置情報を加算 × N layers Masked Self-Attention 未来トークンをマスク Add & Norm Cross-Attention Q←Decoder, K/V←Encoder Add & Norm Linear + Softmax d_model → vocab_size → 確率分布 Output Probabilities 次トークンの確率分布 Attention FFN Add & Norm Embedding Masked Attn Output層

全体像を把握したところで、Transformerの中核である Scaled Dot-Product Attention の計算グラフを見てみましょう。


🖼️ Diagram: scaled_dot_product_attention

Scaled Dot-Product Attention の計算グラフ Q, K, V から Attention出力までの行列演算フロー 入力 X W_Q W_K W_V Q (query) K (key) V (value) MatMul(Q, Kᵀ) 類似度スコア行列 Scale ÷ √d_k 勾配消失を防ぐ正規化 Mask(Decoder のみ) -∞ で未来をマスク Softmax → Attention weights MatMul(weights, V) = Attention Output Attention(Q,K,V) = softmax(QKᵀ/√d_k)V

最後に、Residual Connection(残差接続)と Layer Normalization の詳細です。これはEncoder/Decoder両方の各サブ層に挟まれる重要な構造です。


🖼️ Diagram: residual_connection_layer_norm

Residual Connection と Layer Normalization Add and Norm の計算グラフ。入力がサブ層をバイパスして加算される 入力 x skip (x そのまま) Sublayer(x) Multi-Head Attention or FFN Add:x + Sublayer(x) LayerNorm(x + Sublayer(x)) なぜ残差接続? 勾配消失を防ぎ 深い層の学習を安定化 LayerNorm は 平均0・分散1に正規化

まとめ:計算グラフの全体的な流れ

Encoder側(理解)

Decoder側(生成)

Attention計算(核心式)

Attention(Q, K, V) = softmax(QKᵀ / √d_k) · V

各ブロックをクリックすると、詳細を聞けます。 特に深掘りしたいブロック(Multi-Head Attention、Positional Encoding、Cross-Attentionなど)があれば教えてください。


🧑 User

2026-06-09T16:37:37.450190Z

K, V と書いてある破線の矢印はどこからどこに何を入出力することを示していますか?


🤖 Claude

2026-06-09T16:37:48.428953Z

図の中の破線矢印(紫色、"K, V" ラベル付き)についてです。

出発点:Encoder側の Encoder Output (K, V) というテキストラベルのある箇所(左カラム下部、Add & Norm の下)

終着点:Decoder側の Cross-Attention ブロック(右カラム中段)

何を渡しているか:

EncoderがN層の処理を経て出力したコンテキスト表現ベクトル群を、Key (K) と Value (V) の行列として Decoder の Cross-Attention に渡しています。

Cross-Attention の中では、役割が3者に分かれます。

つまり、DecoderがQ("今何を生成すべきか")でEncoderの全出力をK/Vとして検索し、関連する文脈情報を引き出す、エンコーダ→デコーダの情報ブリッジがこの破線矢印です。機械翻訳で言えば「翻訳先の次トークンを生成するために、翻訳元文全体を参照する」経路がまさにここに当たります。


🧑 User

2026-06-09T16:58:09.703545Z

元の Attention の計算グラフと、Scaled Dot-Product Attention の計算グラフの構造の関係を説明してください。


🤖 Claude

2026-06-09T16:58:26.213581Z

良い質問です。2つの図は同じ計算を異なる抽象レベルで描いたものです。


全体構造図(1枚目)での Attention の位置

1枚目では、EncoderとDecoderの中に Multi-Head Self-Attention や Cross-Attention というブロックが1つの箱として描かれています。中身は完全に隠蔽されており、「何かAttentionの計算をする箱」としてのみ扱われています。


2枚目はその箱の「中身」を展開したもの

2枚目の Scaled Dot-Product Attention の図は、1枚目の紫の Attention ブロック1つを分解したものです。対応関係は次の通りです。

入力の対応

1枚目(箱の外から見た入力) 2枚目(箱の中の処理)
前段の出力ベクトル X 入力 X → W_Q, W_K, W_V で線形変換
(Self-Attention の場合)X が Q/K/V 全てに 同じ X から Q, K, V を3方向に射影
(Cross-Attention の場合)K/V は Encoder から K, V だけ Encoder 出力から射影、Q は Decoder から

計算ステップの対応

1枚目で Multi-Head Self-Attention と書かれた箱の中で起きていることが、2枚目の MatMul(Q, Kᵀ) → Scale ÷√d_k → Mask → Softmax → MatMul(weights, V) という一連のフローです。

出力の対応

2枚目の Attention Output が、1枚目で Attention ブロックから出て Add & Norm に流れ込む矢印の中身です。


"Multi-Head" との関係(2枚目では省略されている部分)

2枚目はさらに Scaled Dot-Product 1つ分しか描いていません。実際の Multi-Head Attention では、2枚目の計算全体を h個並列に走らせ、それぞれ異なる W_Q, W_K, W_V を使い、最後に全ヘッドの出力を concat して線形変換します。つまり、

1枚目の紫箱1個 = 2枚目の計算グラフ × h個 + Concat + Linear

という入れ子構造になっています。


🧑 User

2026-06-09T17:06:57.311938Z

Scaled Dot-Prduct Attention の入力 X から Q, K, V を生成する計算の詳細を説明してください。


🤖 Claude

2026-06-09T17:07:49.624746Z

Q, K, V の生成は線形変換(全結合層)を3つ並列に適用するだけです。


数式

Q = X · W_Q    (shape: [seq_len, d_k])
K = X · W_K    (shape: [seq_len, d_k])
V = X · W_V    (shape: [seq_len, d_v])

W_Q, W_K, W_V はそれぞれ独立した学習パラメータの行列で、shape は [d_model, d_k] です。バイアス項を加える実装もありますが、本質的には行列積だけです。


計算グラフで展開すると

🖼️ Diagram: qkv_projection_detail

Q, K, V 射影の計算グラフ詳細 入力行列 X に3種類の重み行列 W_Q, W_K, W_V を掛けて Q, K, V を生成する行列演算フロー。各行が1トークンに対応。 X [seq_len × d_model] 各行 = 1トークンの埋め込み W_Q [d_model × d_k] 学習パラメータ W_K [d_model × d_k] 学習パラメータ W_V [d_model × d_v] 学習パラメータ × × Q = X · W_Q [seq_len × d_k] 「何を探しているか」 K = X · W_K [seq_len × d_k] 「索引」 W_V [d_model × d_v] 学習パラメータ × V = X · W_V 「取り出す中身」 典型的な寸法(base) d_model = 512 d_k = d_v = 64 h(heads) = 8 h × d_k = d_model W_Q, W_K, W_V は head ごとに独立 (Multi-Head の場合) Self vs Cross Attention Self-Attention: Q, K, V 全て同じ X から Cross-Attention: Q はDecoder X、 K, V はEncoder 出力から

ポイントのまとめ

3つの射影は構造的に同じ演算で、違いは重み行列だけです。

Q = X · W_Q    # 「今何を探しているか」を表す空間へ投影
K = X · W_K    # 「ここに何があるか」を表す空間へ投影
V = X · W_V    # 「実際に取り出す情報」を表す空間へ投影

d_k と d_model が分離している理由は、Multi-Head Attention で h 個のヘッドに分割するためです。h × d_k = d_model という関係が成り立ちます(base Transformer では 8 × 64 = 512)。各ヘッドは独自の W_Q, W_K, W_V を持ち、異なる種類の依存関係(構文・意味・位置など)をそれぞれ独立して学習します。

Self-Attention と Cross-Attention の違いは、X の出所だけです。Self-Attention では同じ X を3方向に射影しますが、Cross-Attention では Q だけ Decoder の X から、K と V は Encoder 出力から射影します。これが先ほどの破線矢印(K, V)の正体です。


🧑 User

2026-06-09T17:17:28.281472Z

同じ行列積(次元ごとの内積)の計算の重み係数が、Q=何を探しているか、K=索引、V=取り出す中身 を得る値を学習できると考えているのはなぜですか?また、K=索引とは、系列上の位置のことであっていますか?


🤖 Claude

2026-06-09T17:17:49.988226Z

良い疑問です。2つ、分けて答えます。


1. なぜ同じ行列積で異なる役割を学習できるか

「同じ演算なのに役割が違う」という違和感は正しい直感です。答えは役割の違いは演算の種類ではなく、損失関数からの勾配によって重み行列が異なる方向に押し出された結果という点にあります。

学習の流れを追うと:

  1. W_Q, W_K, W_V はすべてランダムな初期値からスタートする
  2. softmax(QKᵀ/√d_k)V という計算全体を経て、最終的な予測損失が計算される
  3. 誤差逆伝播で各行列に勾配が流れる
  4. W_Q への勾配は「このクエリベクトルが正しいキーに高スコアを出せるか」という方向に、W_K への勾配は「このキーベクトルが正しいクエリに応答できるか」という方向に、W_V への勾配は「アテンションで選ばれたとき、有用な情報を出力できるか」という方向にそれぞれ独立して流れる

つまり、3つの行列は同じ演算構造を持ちながら、損失から受け取る勾配の意味が構造的に異なるため、異なる役割に収束するのです。事前に「これはクエリ用」と設計されているわけではなく、訓練によってそのように分業が生まれます。

なお「Q/K/V」という名前はデータベースの比喩として後付けで付けられたもので、設計の意図を説明するラベルであり、学習メカニズムの説明ではありません。


2. K = 索引とは位置のことか?

いいえ、位置ではありません。 これは重要な誤解で、整理する価値があります。

K(Key)が表すのはそのトークンが持つ内容的な特徴です。「自分はどんな情報を持っているか」を表すベクトルであり、系列上の何番目にいるかという位置情報ではありません。

位置情報は別経路で入ります。Positional Encoding が X に加算された時点で、すでに各トークンのベクトルに位置が織り込まれています。その後 W_K を掛けるので、K には位置情報も含まれてはいますが、それは K の主な役割ではなく、あくまで X が運んでいた情報の一部が引き継がれているだけです。

「索引」という比喩をデータベースで考えると:

データベース Attention
クエリ文字列 Q:「動詞を探している」
インデックスキー K:「私は動詞である」「私は名詞である」など内容ベースの特徴
レコードの値 V:実際に取り出したい意味情報

検索キーは行番号(位置)ではなく、内容に基づいた特徴量です。たとえば「the cat sat on the mat」で "sat" がクエリを投げるとき、"cat" の K が高スコアを得るのは "cat" が2番目にあるからではなく、「主語である」「動作の主体になり得る名詞だ」という内容的特徴がマッチするからです。


🧑 User

2026-06-09T17:26:40.064332Z

「the cat sat on the mat で sat がクエリを投げると cat が高スコアを得る」とは、sat に続く系列値の予測計算においては、 sat まで続いた系列上の値の中では cat がもつ情報を強く重み付けすると精度が上がると判断している、という意味であっていますか?


🤖 Claude

2026-06-09T17:26:53.675936Z

はい、ほぼ正確です。少しだけ精度を上げると:


「高スコアを得る」の意味

softmax(QKᵀ/√d_k) の出力は、V の各行を加重平均するときの重みです。

つまり「cat の K が高スコアを得る」とは:

sat の Q ベクトルと cat の K ベクトルの内積が大きい
→ softmax 後の重みで cat の V が大きく選ばれる
→ sat の Attention 出力は「cat の V を強く含んだ加重平均」になる

これが「cat の情報を強く重み付けする」の正体です。


「予測計算において」の部分について

ここだけ補足が必要です。Encoder の Self-Attention と Decoder の Masked Self-Attention で意味が少し異なります。

Encoder の場合("the cat sat on the mat" を丸ごと処理)

マスクがないので、sat は未来のトークン(on, the, mat)も参照できます。「次を予測する」ためではなく、sat という単語の意味をシーケンス全体の文脈で豊かに表現し直すための計算です。出力は「この文脈における sat の意味ベクトル」になります。

Decoder の Masked Self-Attention の場合

マスクがあるので、sat は自分より前のトークン(the, cat)しか参照できません。この場合はおっしゃる通り、sat までの系列を見て次のトークンを予測するための文脈表現を作る計算です。


整理すると

おっしゃった解釈はDecoder の Masked Self-Attention に対しては完全に正しいです。Encoder の Self-Attention については「次を予測する」ではなく「文脈を取り込んで表現を更新する」と読み替えると正確になります。どちらの場合も「cat の V を強く重み付けすると最終的な損失が下がる」という訓練シグナルによって、そのアテンションパターンが学習されるという仕組みは同じです。


🧑 User

2026-06-09T19:23:49.929456Z

具体的には、 Residual Connection(残差接続)と Layer Normalization は最初の図の何処にどのように入っていますか?


🤖 Claude

2026-06-09T19:24:38.692114Z

最初の全体図の Add & Norm ブロックがまさにそれです。図では1つの箱に圧縮されていましたが、内部構造を対応付けると以下のようになります。

🖼️ Diagram: add_norm_in_context

Add & Norm の全体図内での位置と内部構造 Encoderの1層分を取り出し、Add&Normブロックの内部(Residual ConnectionとLayer Norm)を展開して示した図 全体図(Encoder 1層分) 入力 x(前層の出力) Multi-Head Self-Attention Sublayer₁(x) Add & Norm = LayerNorm(x + Sublayer₁(x)) Feed Forward Network Sublayer₂(x') Add & Norm = LayerNorm(x' + Sublayer₂(x')) 出力(次層へ) ← Add & Norm の箱 Add & Norm の内部(展開図) 入力 x skip Sublayer(x) Attention or FFN Add:x + Sublayer(x) Layer Normalization 平均0・分散1 に正規化 出力 展開 Encoder 1層の式 x' = LayerNorm(x + Attention(x)) out = LayerNorm(x' + FFN(x')) Add & Norm は2回登場する 全体図での出現箇所 Encoder:各層に2回 Decoder:各層に3回 Decoder:各層に3回 (Masked Attn・Cross Attn・FFN の後)

対応関係のまとめ

最初の全体図で Add & Norm と書かれた灰色の箱は、展開すると右カラムの3ステップです。

Encoder 1層に Add & Norm は2回入ります。

Decoder 1層には3回入ります。Masked Self-Attention・Cross-Attention・FFN それぞれの直後です。

skip(残差)接続の起点はサブ層への入力 xで、サブ層をバイパスして Add のもう一方の入力に直接つながります。全体図では箱と箱の間の縦線しか描かれていませんでしたが、実際にはその縦線と並行してバイパス経路が存在しています。


🧑 User

2026-06-09T19:27:24.829104Z

TransformerのCross-Attentionを詳しく説明してください


🤖 Claude

2026-06-09T19:28:15.411124Z

Cross-Attention は「Decoder が何を生成すべきか迷ったとき、Encoder の記憶を参照する」仕組みです。構造は Self-Attention と同じ Scaled Dot-Product ですが、Q の出所だけが異なります。

🖼️ Diagram: cross_attention_detail

Cross-Attention の詳細計算グラフ EncoderのK,VとDecoderのQがCross-Attentionで結合される計算フロー Encoder 側 Encoder 最終出力 C [src_len × d_model] W_K 学習パラメータ W_V 学習パラメータ K = C·W_K src_len × d_k V = C·W_V src_len × d_v Decoder 側 Masked Self-Attn 出力 D [tgt_len × d_model] W_Q 学習パラメータ Q = D·W_Q tgt_len × d_k MatMul(Q, Kᵀ) tgt_len × src_len Scale ÷√d_k → Softmax Attention Output tgt_len × d_v 行列サイズの意味 src_len:入力文の長さ tgt_len:生成済み長さ スコア行列は非正方形 マスクについて Cross-Attention に 未来マスクは不要 Encoder 出力は全公開

Self-Attention との構造的な違い

Self-Attention Cross-Attention
Q の出所 同じ層の入力 X Decoder(Masked Self-Attn の出力)
K, V の出所 同じ層の入力 X Encoder 最終出力 C
スコア行列の形 seq_len × seq_len(正方形) tgt_len × src_len(非正方形)
マスク Decoder では未来をマスク 不要(Encoder 出力は全公開)

スコア行列 [tgt_len × src_len] の読み方

スコア行列の各行は「Decoder の1トークンが、Encoder の全トークンにどれだけ注目するか」を表します。

機械翻訳の例で言うと:

          The    cat    sat    on    the    mat
  猫は    0.02   0.91   0.04   0.01  0.01   0.01   ← 「猫は」を生成するとき
  座った  0.01   0.08   0.88   0.02  0.00   0.01   ← 「座った」を生成するとき
  マットに 0.01  0.01   0.02   0.10  0.05   0.81   ← 「マットに」を生成するとき

各行の softmax 重みで V(Encoder の内容ベクトル群)を加重平均することで、「今生成しようとしているトークンに関連する入力側の情報」 を引き出します。


Cross-Attention がない場合に何が起きるか

Decoder の Masked Self-Attention だけでは、生成済みトークン(自分より前の出力)しか参照できません。Cross-Attention があることで初めて 入力文全体を何度でも自由に参照できるようになります。これが Encoder-Decoder 構造の核心です。

GPT 系のモデル(Decoder only)は Cross-Attention を持たず、プロンプトを入力トークンとして系列に直接埋め込むことで同様の効果を得ています。


🧑 User

2026-06-09T19:37:12.510440Z

EncoderとDecoder にはそれぞれ、どのような形で系列データを入力しますか?具体例を含めて説明してください。


🤖 Claude

2026-06-09T19:38:05.904706Z

機械翻訳「The cat sat → 猫は座った」を例に、入力の形を順番に説明します。


Encoder への入力

入力文を一度に全トークンまとめて渡します。

ステップ1:トークン化
"The cat sat" → ["The", "cat", "sat"]

ステップ2:トークンIDに変換
["The", "cat", "sat"] → [464, 3797, 3332]

ステップ3:Embedding → shape [3, 512]
行0: [0.12, -0.34, 0.87, ...]  ← "The" の埋め込みベクトル
行1: [0.55,  0.21, -0.63, ...]  ← "cat"
行2: [-0.09, 0.78, 0.44, ...]  ← "sat"

ステップ4:Positional Encoding を加算 → shape [3, 512]
(位置0, 1, 2 のsin/cosベクトルをそれぞれ加算)

Encoder はこの [3, 512] 行列を受け取り、N層の処理を経て同じ shape [3, 512] のコンテキスト行列 C を出力します。これが Cross-Attention に渡る K, V の元になります。


Decoder への入力

Decoder はトークンを1つずつ逐次生成します。各ステップで「生成済みトークン列」を入力として受け取ります。

🖼️ Diagram: decoder_autoregressive_input

Decoder の自己回帰的入力:各ステップで生成済みトークンを入力に追加していく様子 ステップ1から4まで、Decoderへの入力系列が1トークンずつ増えていく図 ステップ Decoder への入力系列 出力(予測) Step 1 <BOS> [1, 512] Decoder + softmax 猫は ← 生成 Step 2 <BOS> 猫は [2, 512] 座った ← 生成 Step 3 <BOS> 猫は 座った [3, 512] <EOS> ← 生成終了 各ステップでの Masked Self-Attention の参照範囲 Step 2 の入力 [<BOS>, 猫は] に対するマスク: <BOS> 猫は <BOS> ○ 参照可 ✕ マスク 猫は ○ 参照可 ○ 参照可 行 = クエリ(今見ているトークン) 列 = キー(参照先のトークン) ✕ の箇所は -∞ を加算して softmax 後に 0 になる

訓練時と推論時の違い

ここは重要なポイントです。

推論時は図の通り、1トークン生成するたびに Decoder を回し直します(自己回帰)。

訓練時は効率化のため、全ステップを1回のフォワードパスで並列処理します。

訓練時の Decoder 入力(1回のフォワードパスで全部渡す):
[<BOS>, 猫は, 座った]   → shape [3, 512]

教師ラベル(1つずれた正解系列):
[猫は, 座った, <EOS>]

位置0の出力 → 「猫は」を予測
位置1の出力 → 「座った」を予測
位置2の出力 → 「<EOS>」を予測

Masked Self-Attention のマスクが訓練時に本質的な役割を果たすのはここです。全トークンを一度に入力していても、マスクによって「位置iの予測には位置i未満しか参照できない」という制約を強制することで、推論時と同じ条件を再現しています。マスクがなければ「答えを見ながら答えを予測する」状態になってしまいます。


Encoder との決定的な違い

Encoder Decoder
入力タイミング 全トークンを一度に 推論時は1トークンずつ逐次
参照範囲 全トークン双方向 自分より前のトークンのみ
処理の目的 入力文の意味表現を構築 次トークンを逐次予測
先頭トークン 実際の入力トークン <BOS>(生成開始記号)

Encoder は「入力文を丸ごと読んで理解する」、Decoder は「1単語ずつ書き出す」という非対称な役割分担が、入力形式の違いにそのまま現れています。


🧑 User

2026-06-09T21:16:49.944269Z

つまり、推論時の forward 計算は、Encoder には毎回系列全体、Decoder には各回系列中の1トークンのみ の入力で計算する手続きを系列に沿って全トークン繰り返し処理し、訓練時のforward計算は、Encoder、Decoderともに系列全体を1サンプルにつき1回入力して計算する、ということですか?


🤖 Claude

2026-06-09T21:17:04.606900Z

ほぼ正確です。1点だけ補足します。


Encoder については完全に正しい

Encoder への入力
推論時 入力系列全体を1回
訓練時 入力系列全体を1回

Encoder は推論・訓練ともに変わりません。また推論時も Encoder は生成ループの外で1回だけ実行し、出力 C をキャッシュして全ステップで使い回します。


Decoder の補足

「各回1トークンのみ」という部分が、厳密には**「累積した生成済み系列全体」**です。

Step 1 入力:[<BOS>]              → shape [1, 512]
Step 2 入力:[<BOS>, 猫は]        → shape [2, 512]
Step 3 入力:[<BOS>, 猫は, 座った] → shape [3, 512]

各ステップで入力長が1ずつ伸びていきます。「新たに追加されるのは1トークン」ですが、入力として渡す系列は毎回先頭から全部です。

ただし実装上はKV キャッシュという最適化が一般的で、前ステップで計算済みの K, V を再利用することで、実質的に新しい1トークン分の計算だけで済むようにします。なのでおっしゃった「1トークンのみ入力」はキャッシュあり実装の説明として正しいです。


整理すると

Encoder Decoder
推論時 系列全体を1回(ループ外) 系列が1トークンずつ伸びる入力をT回繰り返す(Tは生成長)
訓練時 系列全体を1回 正解系列全体を1回(マスクで並列化)

訓練時の Decoder が「1回で済む」のは、Masked Self-Attention のマスクが「推論時に1トークンずつ増やす処理」を行列演算として一括エミュレートしているからです。この並列化こそが RNN に対する Transformer の訓練速度上の最大の優位点です。


🧑 User

2026-06-09T21:36:47.599385Z

Encoder, Decoder ともに、Embeddingと Positional Encodingの結合に続くAttentionをMulti-Headにしているのは、パラメータ数を増やして保持情報表現力を大きくするためですか?


🤖 Claude

2026-06-09T21:37:05.749599Z

半分正しく、半分は別の理由です。分けて整理します。


「パラメータ数を増やすため」ではない

パラメータ数だけが目的なら、d_model を大きくすれば済みます。わざわざ分割する必要はありません。

実際、1ヘッドで d_k = 512 の Single-Head Attention と、8ヘッドで d_k = 64 の Multi-Head Attention は総パラメータ数がほぼ同じです。

Single-Head:W_Q [512×512] + W_K [512×512] + W_V [512×512]
Multi-Head :W_Q [512×64] × 8 + W_K [512×64] × 8 + W_V [512×64] × 8
             → 合計サイズは同じ

本質的な理由:異なる「注目パターン」を並列に学習できる

1つのヘッドは1種類の注目パターンしか表現できません。Multi-Head にすることで、同じ系列に対して複数の異なる視点から同時に注目できます。

機械翻訳の例で言うと:

"The animal didn't cross the street because it was too tired"

ヘッド1(構文的依存): it → animal  (代名詞の参照先)
ヘッド2(動詞との関係): cross → animal, street  (動詞の主語・目的語)
ヘッド3(局所的文脈): tired → too  (直近の修飾関係)
ヘッド4(位置的近接): 直近トークン同士の関係

これらを1つのヘッドで同時に表現しようとすると、softmax が1つの確率分布しか出力できない制約上、どれか1つの関係に集中するしかありません。


「表現力」の意味が違う

おっしゃった「保持情報の表現力」は正しい方向ですが、それはパラメータ量による表現力ではなく、注目パターンの多様性による表現力です。

観点 Single-Head Multi-Head
パラメータ数 ほぼ同じ ほぼ同じ
注目できる関係の種類 1種類 h種類を並列
各ヘッドの次元 d_k = d_model d_k = d_model / h(小さい)
表現の豊かさ 1つの部分空間 h個の異なる部分空間

各ヘッドは d_model を h 等分したより小さな部分空間に射影してから Attention を計算します。この「次元を絞った部分空間への射影」が、ヘッドごとに異なる種類の関係に特化させる仕組みの核心です。全ヘッドの出力を最後に concat して W_O で線形変換することで、h種類の注目結果を統合した最終表現を得ます。


🧑 User

2026-06-09T21:51:19.786376Z

Encoderで元の入力系列におけるQに対するKとVの重みを含んだ情報を、KとVだけに重みとして情報集約しなおしたものに対して、同様にしてDecoderではQとVだけに重みとして情報集約しなおしたものと合わせて、再度Attentionの構造でQに対するKとVの重みを計算することで、「言語翻訳」という系列間対応情報を表現することができる、というのは、学習と推論による実験結果としてそうなったということ以外に、定性的なメカニズムの仮説やデータ調査による検証といった研究結果の情報はありますか?


🤖 Claude

2026-06-09T21:51:52.362106Z

非常に鋭い問いです。「なぜこの構造が翻訳に効くのか」については、実験結果の積み上げに加えて、複数の定性的仮説と解釈研究が存在します。


1. Attention の可視化研究(Bahdanau 以来の系譜)

最も初期の証拠はAttention 重みの可視化です。

Bahdanau et al. (2015) の原著論文で、フランス語→英語翻訳において Attention 行列を可視化したところ、対応する単語間でスコアが高くなるほぼ対角的なパターンが現れました。これは「モデルが翻訳時に入力側の対応語を実際に参照している」という定性的証拠として広く引用されています。

Transformer の論文(Vaswani et al. 2017)でも同様の可視化が示されており、Cross-Attention の各ヘッドが異なる言語間対応パターンを捉えていることが報告されています。


2. Encoder の K/V が「何を圧縮しているか」の解釈仮説

ご指摘の「KとVへの情報集約」については、情報のボトルネック的圧縮という仮説があります。

Encoder の Self-Attention を経た K, V は、各トークンの局所的な表現ではなく文脈全体を加味した表現になっています。これを「文脈化された記憶」として Cross-Attention に渡すことで、Decoder は個々のトークンの表面的特徴ではなく、文脈依存的な意味にアクセスできる、という解釈です。

ただしこれは仮説の域を出ておらず、実際に K と V が何を分担しているかは次の研究群で掘り下げられています。


3. K と V の役割分担についての解釈研究

Geva et al. (2021) "Transformer Feed-Forward Layers Are Key-Value Memories" は FFN 層について同様の問いを立て、FFN の重み行列が事実的知識を Key-Value 的に格納していることをデータ調査で示しました。Attention の K/V に直接対応する研究ではありませんが、「なぜ K と V を分離するか」という問いへの間接的な回答として参照されています。

Attention の K/V に絞った研究としては、V が意味内容を、K が検索条件を担うという分業が、プロービング(中間表現への線形分類器の適用)実験でそれぞれ独立して確認されています。


4. Cross-Attention が言語間対応を学習するメカニズムの仮説

「なぜ Cross-Attention が翻訳対応を表現できるか」については、複数の仮説が競合しています。

仮説A:分散表現の幾何学的整合性

事前学習済みの多言語モデルの研究(Pires et al. 2019 など)から、異なる言語の対応概念が埋め込み空間で近傍に配置されることが示されています。Encoder と Decoder の埋め込み空間が共有または整合的に学習されるなら、Cross-Attention の内積が言語をまたいで意味的類似度を計測できる、という説明です。

仮説B:損失関数による暗黙的な整合化

Cross-Attention の Q(Decoder)と K(Encoder)の内積が高くなるよう W_Q, W_K が学習されるとき、翻訳ペアとして正解なトークン対の内積が高くなる方向に勾配が流れます。これが結果として「翻訳対応の検索構造」を自然に誘導する、という説明です。これは実験的検証というより構造的な必然性に近い議論です。

仮説C:Encoder が言語中立的な表現を作る

多言語 Transformer の研究(mBERT, mT5 など)で、Encoder の上位層が言語に依存しない意味表現に収束することが示されています。この「言語中立空間」を経由することで、Cross-Attention が言語をまたいだ対応を計算しやすくなる、という解釈です。


5. 限界と未解決部分

正直なところ、「なぜこの特定の構造(Q/K/V の3分割と Encoder-Decoder の組み合わせ)が最良か」という理論的な証明は存在しません。

現状の研究コンセンサスは:

つまりご質問の前提通り、実験結果として有効性が確認された構造に対して、事後的に複数の解釈仮説が提案されているという状態です。理論先行ではなく実験先行で発展してきた分野の典型的な姿と言えます。


🧑 User

2026-06-10T17:14:43.523807Z

Feed Forward Networkを説明してください


🤖 Claude

2026-06-10T17:15:35.175935Z

Feed Forward Network(FFN)は Transformer の中で唯一、トークン間の相互作用を持たない層です。Attention が「どのトークンを参照するか」を決める層だとすると、FFN は「参照結果をどう変換するか」を担います。


計算の構造

🖼️ Diagram: ffn_computation_graph

Feed Forward Network の計算グラフ FFN の計算グラフ(1トークン分) 入力 x d_model 次元(例:512) Linear₁:x · W₁ + b₁ W₁ [d_model × d_ff] 次元を拡大 ReLU:max(0, x) 非線形変換 負を0にクリップ Linear₂:x · W₂ + b₂ W₂ [d_ff × d_model] 次元を戻す 出力 d_model 次元(入力と同じ) FFN(x) = max(0, x·W₁+b₁)·W₂+b₂ 各トークンに独立・同一の変換を適用 次元の変化(base Transformer) d_model = 512 × 4 d_ff = 2048 ReLU d_ff = 2048(約半分が0) ÷ 4 d_model = 512(復元) パラメータ数 W₁:512 × 2048 = 1,048,576 W₂:2048 × 512 = 1,048,576 合計 ≈ 2M / 層 トークン間の独立性 全トークンに同じ W₁, W₂ を 適用(位置ごとに共有)

Attention との役割分担

Attention と FFN はセットで1つの処理単位を構成しており、担う計算の種類が異なります。

Attention FFN
計算の種類 トークン間の関係(横方向) 各トークン内の変換(縦方向)
入力依存性 系列全体を参照 自トークンのみ
役割の仮説 文脈の収集 収集した文脈の非線形変換

Attention が「どのトークンの情報をどれだけ混ぜるか」を決め、FFN が「混ぜた結果をどう変換するか」を担う、という分業です。


次元を拡大してから戻す理由

d_model → d_ff → d_model(512→2048→512)という形が意味を持つのは、ReLU による非線形性は高次元空間で豊かに作用するからです。

低次元のまま非線形変換を適用しても、表現できる関数の複雑さが限られます。一度高次元に射影してから ReLU で「どの方向を活性化するか」を選択し、元の次元に圧縮して戻すことで、線形変換だけでは表現できない複雑な特徴変換を実現します。


「記憶」としての解釈

先ほど言及した Geva et al. (2021) の観点では、FFN の W₁ の各行が「パターン検出器」、W₂ の各列が「出力する知識」に対応するという解釈があります。

W₁ の行 i が "パリ" "フランス" のような文脈にマッチすると
ReLU で活性化され
W₂ の列 i が「首都」「ヨーロッパ」といった意味を出力に加算する

この視点では FFN は Attention が収集した文脈に対して、学習済み知識を引き出す連想記憶として機能しています。Attention が「文脈から何を参照するか」を決め、FFN が「その文脈に対応する知識を想起する」という解釈です。


🧑 User

2026-06-10T17:30:57.826532Z

FFNの活性化関数をReLUではなくGELUにすると、どのような効果が期待されますか?


🤖 Claude

2026-06-10T17:31:48.171277Z

GELUへの変更は現代のTransformer実装(BERT、GPT-2以降)でほぼ標準となっており、ReLUに対して複数の点で異なる振る舞いをします。


ReLUとGELUの関数形の違い

🖼️ Diagram: relu_vs_gelu

ReLU と GELU の比較グラフ x y 0 1 2 -1 -2 1 ReLU GELU 負の値が微小に通過 ReLU: x<0 で 勾配=0(dead neuron) x < 0 の領域での振る舞いが最大の違い 数式と性質 ReLU f(x) = max(0, x) x < 0:出力=0、勾配=0 x ≥ 0:出力=x、勾配=1 不連続な勾配(x=0で折れ) GELU f(x) = x · Φ(x) Φ(x):標準正規分布のCDF x < 0:小さな負の値が通過 x ≥ 0:ほぼ x に近い出力 全域で滑らかな勾配 確率的ゲーティングの解釈あり

期待される効果

1. Dead Neuron 問題の緩和

ReLU は x < 0 で出力も勾配も完全にゼロになります。一度ゼロになったニューロンは以後どんな入力が来ても活性化せず、重みが更新されなくなります(Dead Neuron)。GELUは負の領域でも微小な値を通過させるため、勾配が完全には消えません。

2. 勾配の滑らかさ

ReLU は x = 0 で勾配が不連続に折れます。GELUは全域で滑らかな勾配を持つため、最適化の軌跡が安定します。特に深いネットワークで層をまたいで勾配を逆伝播するとき、この滑らかさが効いてきます。

3. 確率的ゲーティングの解釈

GELUは x · Φ(x) という形を持ちます。Φ(x) は標準正規分布の累積分布関数(CDF)なので、「入力 x が標準正規分布から来た値より大きい確率」を重みとして x をスケールする操作と解釈できます。これは入力の大きさに応じてどれだけ情報を通すかを確率的に決めるという直感に対応しており、ReLUの「0か1か」よりも柔軟なゲーティングです。


実際の性能への影響

モデル 活性化関数
元の Transformer (2017) ReLU
BERT (2018) GELU
GPT-2以降 GELU
PaLM, LLaMA 等 SwiGLU(GELUの派生)

実験的には特に深いモデル・大規模モデルで GELUが ReLUを上回ることが報告されています。ただし浅いモデルや小規模タスクでは差が小さく、計算コストも GELU の方がわずかに高いため、常に GELU が優るとは言えません。

GELUのさらなる派生として、Noam Shazeer (2020) が提案した SwiGLU は x · σ(βx) にゲート機構を組み合わせたもので、現在の大規模モデルではこちらが主流になっています。


🧑 User

2026-06-10T17:39:01.207643Z

SwiGLUは具体的にどのような実装で、計算コストと効果がどのように変わりますか?


🤖 Claude

2026-06-10T17:39:55.689663Z

SwiGLUの核心は「2つの線形変換の出力をゲートとして掛け合わせる」という構造です。


通常のFFNとSwiGLUの実装比較

import torch
import torch.nn as nn
import torch.nn.functional as F

# ===== 通常の FFN (ReLU / GELU) =====
class FFN(nn.Module):
    def __init__(self, d_model, d_ff):
        super().__init__()
        self.W1 = nn.Linear(d_model, d_ff)
        self.W2 = nn.Linear(d_ff, d_model)

    def forward(self, x):
        return self.W2(F.gelu(self.W1(x)))
        # shape: [batch, seq_len, d_model]


# ===== SwiGLU =====
class SwiGLU(nn.Module):
    def __init__(self, d_model, d_ff):
        super().__init__()
        self.W1 = nn.Linear(d_model, d_ff)   # ゲート用
        self.W2 = nn.Linear(d_model, d_ff)   # 値用
        self.W3 = nn.Linear(d_ff, d_model)   # 出力射影

    def forward(self, x):
        gate = F.silu(self.W1(x))   # Swish: x * sigmoid(x)
        value = self.W2(x)          # ゲートされる値
        return self.W3(gate * value) # 要素積でゲーティング

構造の違いは1点だけです。通常のFFNが Linear → 活性化 → Linear の直列構造なのに対して、SwiGLUは2つの Linear を並列に走らせ、要素積で掛け合わせてから出力射影するという構造です。


計算グラフ

🖼️ Diagram: swiglu_vs_ffn_graph

通常のFFNとSwiGLUの計算グラフ比較 通常の FFN(GELU) 入力 x [d_model] W₁ [d_model → d_ff] 線形変換 GELU(·) W₂ [d_ff → d_model] 線形変換 出力 [d_model] パラメータ W₁ + W₂ = 2 × d_model × d_ff SwiGLU 入力 x [d_model] W₁ gate W₂ value Swish(·) ⊙(要素積) W₃ [d_ff → d_model] 出力射影 出力 [d_model] W₁ + W₂ + W₃ = 3 × d_model × d_ff vs

計算コストの変化

線形変換が2つから3つに増えるためパラメータ数が1.5倍になりますが、実装では d_ff を調整してパラメータ数を揃えます。

通常のFFN:d_ff = 4 × d_model = 2048
SwiGLU   :d_ff = (4/3) × 2 × d_model ≈ 1365 ← 2/3に縮小

結果として総パラメータ数はほぼ同じ

Shazeer (2020) の論文でこの調整が提案されており、LLaMAなどの実装でも採用されています。計算量(FLOPs)は調整後でほぼ同等ですが、線形変換が3回に増えるためカーネル起動のオーバーヘッドはわずかに増えます。


GELUに対してSwiGLUが異なる点

ゲーティングの構造的な違いが本質です。

GELUは x · Φ(x) で、同じ x を使って自己ゲーティングします。入力の大きさに応じて自分自身をスケールするだけです。

SwiGLUは Swish(W₁x) · W₂x で、独立した2つの線形変換の出力が互いにゲーティングします。W₁が「何を通すか」を決め、W₂が「通す内容」を決めるという分業が生まれます。これはLSTMのゲート機構に近い構造的な発想です。

Swish(SiLU)自体の性質としては、GELUとほぼ同形ですが x · σ(x) という形でσがシグモイド関数であり、計算が若干シンプルです。

GELU:  x · Φ(x)        Φ は正規分布CDF(計算コスト高め)
Swish: x · sigmoid(x)  シグモイドで代替(計算コスト低め)

実験的な効果

Shazeer (2020) の報告では、同パラメータ数・同FLOPsの条件でGELU-FFNと比較したとき、翻訳・言語モデリングのperplexityが一貫して改善しています。なぜ改善するかの理論的な説明は現時点では「ゲーティングによる表現力の向上」という経験則にとどまっており、前回お話したFFNの解釈研究と同様に実験先行の状況です。

LLaMA、Mistral、Gemmaなど現在の主要なオープンモデルがほぼ全てSwiGLUを採用していることが、実用上の有効性の最も強い証拠と言えます。


🧑 User

2026-06-10T18:08:59.489058Z

各Attentionで、Layer Normalization を先に入れるか後に入れるかではどのような効果の違いがありますか?


🤖 Claude

2026-06-10T18:09:46.873828Z

これは「Pre-LN vs Post-LN」として知られており、訓練安定性に大きく影響する設計選択です。


構造の違い

🖼️ Diagram: pre_ln_vs_post_ln

Pre-LN と Post-LN の計算グラフ比較 Post-LN(元論文 Vaswani 2017) 入力 x skip Sublayer(x) Attention or FFN Add:x + Sublayer(x) LayerNorm(後) 出力 課題 ・深い層で勾配が不安定 ・warmup 必須 ・学習率に敏感 ・収束後の性能は高い Pre-LN(GPT-2 以降の主流) 入力 x skip LayerNorm(先) Sublayer(LN(x)) Attention or FFN Add:x + Sublayer(LN(x)) 出力 利点 ・勾配が安定して流れる ・warmup なしでも学習可 ・深いモデルに向く ・最終層に別途LN推奨

勾配の流れ方の違いが本質

Post-LN では、skip 接続を経た Add の出力に対して LayerNorm がかかります。逆伝播時、勾配は Sublayer を通る経路と skip 経路の両方から流れてきた後で LayerNorm を通ります。LayerNorm は正規化によってスケールを揃えますが、深い層では各層の Sublayer 出力が加算され続けるため、勾配のスケールが層ごとに大きく変動します。これが訓練初期の不安定さの原因です。

Pre-LN では、skip 経路は LayerNorm を通らず x をそのまま通過します。逆伝播時に skip 経路から来る勾配は LayerNorm に触れないため、入力から出力まで正規化されない勾配の高速道路が確保されます。これが深い層でも勾配が安定して流れる理由です。

Post-LN の逆伝播:
∂L/∂x = ∂L/∂LN(x+sub) · ∂LN/∂(x+sub) · (1 + ∂sub/∂x)
          ↑ ここで全ての勾配がLNを通る

Pre-LN の逆伝播:
∂L/∂x = ∂L/∂(x+sub(LN(x))) · (1 + ∂sub(LN(x))/∂x)
          ↑ skip の 1 が常に素通りで残る

skip 経路の 1 が全層を通じて勾配に加算され続けることで、ResNet と同じ理由で深い層への勾配消失が防がれます。


Pre-LN の唯一の注意点

Pre-LN では最終層の出力が正規化されないまま Linear + Softmax に渡ります。そのため最終層の後に別途 LayerNorm を1つ追加するのが標準的な実装です。GPT-2 の実装でもこの構造が採用されています。

# Pre-LN Transformer の最終出力
x = transformer_layers(x)   # 各層内部で Pre-LN
x = final_layer_norm(x)     # ← 最後に1回だけ追加
logits = lm_head(x)

モデル別の採用状況

モデル LN の位置
Transformer (2017) Post-LN
BERT Post-LN
GPT-2 Pre-LN
GPT-3, LLaMA, Mistral Pre-LN
PaLM Pre-LN

元論文が Post-LN だったにもかかわらず GPT-2 以降で Pre-LN が主流になった背景には、モデルを深くスケールするときに Post-LN では warmup の調整が難しく訓練が発散しやすいという実験的知見の蓄積があります。ただし Xiong et al. (2020) の理論的分析によって Pre-LN の勾配安定性が定量的に示されるまでは、この選択の理由は主に経験則でした。


🧑 User

2026-06-10T18:42:03.736241Z

Pre-LN vs Post-LN の比較は、Vision Transformer では異なる点がありますか?


🤖 Claude

2026-06-10T18:43:01.362172Z

基本的な構造上の議論はTransformerと同じですが、ViT固有の事情がいくつかあります。順番に整理します。


ViT固有の文脈

ViTはTransformerのEncoder構造をそのまま画像に適用したモデルです。入力がトークン列ではなくパッチ列になりますが、Self-AttentionとFFNの構造は同じであるため、Pre-LN/Post-LNの議論の骨格は共通です。

ただし以下の点でViT固有の事情があります。


1. ViTの原論文からすでにPre-LNを採用

Dosovitskiy et al. (2020) のViT原論文は、NLPのTransformer原論文(Post-LN)とは異なり、最初からPre-LNを採用しています。

NLP Transformer (2017):Post-LN → 後にPre-LNへ移行
ViT (2020)             :最初からPre-LN

これはGPT-2以降のPre-LN移行がすでに知られていた時期に設計されたためです。ViTの文脈でPost-LNとPre-LNを比較した研究(Touvron et al. DeiT等)でも、Pre-LNの訓練安定性上の優位が確認されています。


2. CLSトークンとの相互作用

ViTはシーケンスの先頭にCLSトークンを付加し、そのトークンの最終出力を分類に使います。

🖼️ Diagram: vit_cls_token_ln

ViTのCLSトークンとLayerNormの関係 ViT の入力構造 [CLS] 位置 0 patch₁ 位置 1 patch₂ 位置 2 ... patch_N 位置 N Transformer Encoder × L layers(Pre-LN) 全トークンが Self-Attention で相互参照 [CLS] 出力 patch₁ (不使用) ... patch_N (不使用) Final LayerNorm CLSトークンに適用 MLP Head 分類ラベルへ Post-LN との違い Post-LN:各層の Add の後にLN  → CLSが層ごとに正規化される Pre-LN:各層の入力にLN、最後に1回  → CLSの勾配経路がskipで保護

CLSトークンはランダム初期化されたパラメータで、全パッチトークンとのAttentionを通じて情報を集約します。Post-LNでは各層のAddの後にLNがかかるため、CLSトークンの表現が層をまたぐたびに正規化されます。Pre-LNではskip経路がLNを通らないため、CLSトークンの情報が層をまたいで素通りしやすく、深いモデルでの勾配安定性が高まります。


3. ViT固有の追加的な事情

パッチ数とシーケンス長

ViTのシーケンス長はパッチ数に依存します。224×224画像をパッチサイズ16×16で分割すると196トークンになります。これはNLPの典型的な系列長と同程度ですが、高解像度画像では数千トークンになることがあり、そのスケールではPre-LNの安定性がより重要になります。

学習データ量とウォームアップの関係

NLPと比較してViTは大規模データ(JFT-300M等)で訓練することが多く、長い訓練スケジュールでPost-LNの不安定さが顕在化しやすい傾向があります。DeiTのような比較的小規模データでの訓練でも、Pre-LNの方が強いデータ拡張との組み合わせで安定することが報告されています。


4. 近年の変種:LayerScale

ViT固有の発展として、Touvron et al. (2021) のLayerScaleがあります。これはPre-LN/Post-LNとは別軸の工夫で、Residual接続に学習可能なスカラーを掛けることで深いViTの訓練を安定させます。

# LayerScale の実装
class LayerScale(nn.Module):
    def __init__(self, d_model, init_value=1e-4):
        super().__init__()
        self.gamma = nn.Parameter(
            torch.ones(d_model) * init_value
        )

    def forward(self, x, sublayer_out):
        # skip + スケールされたsublayer出力
        return x + self.gamma * sublayer_out

初期値を非常に小さく設定することで、訓練初期はほぼ恒等写像として振る舞い、学習が進むにつれて徐々に各層の寄与を増やします。Pre-LNと組み合わせることでViT-深層モデル(ViT-H等)での訓練が安定することが示されており、DeiT-IIIやOpenCLIPなどで採用されています。


まとめ

観点 NLP Transformer ViT
原論文のLN位置 Post-LN Pre-LN
現在の主流 Pre-LN Pre-LN
固有の追加工夫 なし LayerScale
CLS固有の問題 該当なし skip経路の保護が重要

基本的な議論はNLPと共通ですが、ViTは原論文の時点ですでにPre-LNを採用しており、LayerScaleという独自の安定化手法が発展したという点がViT固有の事情です。