Self-Attention の計算:QKV とスケーリングの導出
アテンションの中身を式で開封。QKVの内積がなぜ類似度になり、なぜ√d_kで割るのかまで、手を動かして腑に落とせます。
- 1.各トークンを Query・Key・Value の3つのベクトルに線形変換し、QとKの内積で「どのトークンをどれだけ見るか」の類似度スコアを作る。
- 2.スコアを √d_k で割って softmax にかけ、合計1の重みに正規化。これを Value の重み付き和にしたものが出力。式は Attention(Q,K,V)=softmax(QKᵀ/√d_k)·V。
- 3.√d_k で割るのは、次元 d_k が大きいほど内積の分散が d_k に比例して膨らみ、softmax が飽和して勾配が消えるのを防ぐため。
アテンションを「式」で開ける
LLM と Transformer では、アテンションを「いまの単語を解釈するために、どの単語をどれだけ見るか」を動的に重み付けするしくみだと説明しました。ここではその中身を、Attention(Q,K,V)=softmax(QKᵀ/√d_k)·V という1本の式まで導出します。記号に圧倒されず、**各ステップが「何を計算しているか」**を追えば、必ず腑に落ちます。
前提として、各トークンはすでに 埋め込み(Embedding) と位置情報を足したベクトルになっています。系列長を n、各ベクトルの次元を d_model とすると、入力は X(形状 n × d_model)という行列です。
Q・K・V:1つの入力を3つの役割に分ける
Self-Attention の出発点は、同じ入力 X を3つの異なる線形変換で投影することです。学習対象の重み行列 W_Q・W_K・W_V を使って、次の3つを作ります。
Q = X · W_Q (Query : 「私は何を探しているか」)
K = X · W_K (Key : 「私は何として参照され得るか」)
V = X · W_V (Value : 「私が実際に渡す中身」)
W_Q・W_K は d_model × d_k、W_V は d_model × d_v の形状で、結果 Q・K は n × d_k、V は n × d_v になります(多くの実装で d_k = d_v)。比喩で言えば、Q は検索窓に打ち込むクエリ、K は各文書に付いた見出しタグ、V はその文書の本文です。同じトークンでも「探す側」と「探される側」と「渡す中身」で別ベクトルを持つのが、表現力の源泉です。
もし Q と K を共通にすると、類似度行列が対称になり「AがBに注目する度合い」と「BがAに注目する度合い」が常に一致してしまいます。文脈の依存関係は本来非対称(修飾語は被修飾語を見るが逆は薄い等)なので、W_Q と W_K を別に学習させて非対称な注目を表現できるようにしています。
内積で類似度スコアを作る
次に、**各 Query が各 Key とどれだけ「合っているか」**を測ります。これに使うのが内積です。Query ベクトル q_i と Key ベクトル k_j の内積 q_i · k_j は、両者の向きが揃っているほど大きくなります。
全ペアを一気に計算するのが行列積 Q · Kᵀ です。
S = Q · Kᵀ (形状 n × n のスコア行列)
S[i][j] = q_i · k_j (トークン i が トークン j を見る“生”のスコア)
S は n × n の正方行列で、i 行 j 列が「i 番目のトークンから見た j 番目のトークンへの注目スコア」です。内積を類似度として使う根拠は、q·k = |q||k|cosθ という関係にあります。向き(cosθ)が近いほど大きく、加えてベクトルの大きさも効くため、学習を通じて「関連するトークン同士の Q・K が大きな内積を生む」よう W_Q・W_K が調整されていきます。この重みの調整自体は 勾配降下法 で行われます。
√d_k で割る:スケーリングの導出
ここが本記事の核心です。スコア S を softmax に通す前に √d_k で割ります。なぜこの一手間が必要なのかを、分散の観点から導出します。
q と k の各成分が、平均0・分散1で独立だと仮定します。内積は成分ごとの積の和です。
q·k = Σ (q_m * k_m) (m = 1 .. d_k)
各項 q_m * k_m は平均0・分散1(独立な平均0・分散1の積の分散は1)。独立な項を d_k 個足すと、和の分散は各分散の合計になるので、
平均: E[q·k] = 0
分散: Var[q·k] = d_k → 標準偏差 = √d_k
つまり 次元 d_k が大きいほど、内積の値は ±√d_k 程度まで大きく振れるようになります。例えば d_k = 64 なら標準偏差は8、d_k = 128 なら約11。スコアの絶対値が大きくなると、softmax が問題を起こします。
softmax は入力差が大きいほど、最大要素の確率を1に、残りを0に近づけます。スコアが ±√d_k まで膨らむと softmax はほぼ one-hot に飽和し、出力がほぼ1点だけを見る硬い分布になります。飽和領域では softmax の勾配がほぼ0になり、誤差逆伝播で学習信号が流れません(勾配消失)。√d_k で割ると分散が1に戻り、softmax が適度に滑らかな分布を保ち、勾配が健全に流れます。
√d_k で割ると、スケール後のスコア S / √d_k の分散は d_k / (√d_k)² = 1 に正規化されます。d_k をどう変えても入力スケールが一定に保たれる——これが「√d_k であって d_k や定数ではない」理由です。分散を1に戻すには標準偏差 √d_k で割るのが過不足ない正解だからです。
softmax で重みに正規化する
スケール済みスコアを、行ごとに softmax にかけて合計1の注目重みにします。
A = softmax(Q·Kᵀ / √d_k) (行ごとに softmax、形状 n × n)
softmax(z)_j = exp(z_j) / Σ_p exp(z_p)
i 行目の softmax は、トークン i から見た全トークンへの注目を確率分布にします。A[i][j] は「i を更新するとき j をどれだけ参照するか」を表す 0〜1 の重みで、i 行の総和は必ず1です。指数関数を使うので、スコアの大きいペアが強調され、小さいペアは相対的に薄まります。
softmax は必ず**行方向(各 Query について全 Key を横断)**にかけます。「トークン i が、自分を含む全トークンにどう注目を配分するか」を1つの分布にまとめる操作だからです。列方向に正規化すると意味が変わってしまうので、実装時の軸指定ミスに注意。
Value の重み付き和:出力の完成
最後に、注目重み A で Value を加重平均します。
Output = A · V (形状 n × d_v)
Output[i] = Σ_j A[i][j] * v_j
i 番目の出力は、各トークンの Value v_j を注目重み A[i][j] で混ぜ合わせたベクトルです。注目度が高いトークンの中身ほど強く反映されます。これで冒頭の式が完成しました。
Attention(Q,K,V) = softmax(Q·Kᵀ / √d_k) · V
各ステップの形状を一望すると、行列演算の流れがはっきりします。
| ステップ | 計算 | 出力の形状 | 意味 |
|---|---|---|---|
| 1. 投影 | Q=X·W_Q, K=X·W_K, V=X·W_V | 各 n × d_k(V は n × d_v) | 入力を3つの役割に分ける |
| 2. スコア | S = Q · Kᵀ | n × n | 全ペアの生の類似度 |
| 3. スケール | S / √d_k | n × n | 分散を1に正規化 |
| 4. softmax | A = softmax(行方向) | n × n | 合計1の注目重み |
| 5. 加重和 | Output = A · V | n × d_v | Value の重み付き平均 |
補足:マルチヘッドと計算量
実際の Transformer は、この Self-Attention を 複数ヘッドに分割して並列に走らせます。d_model を h 個のヘッドに分け、各ヘッドが小さな d_k = d_model / h で独立にアテンションを計算し、結果を連結して再投影します。各ヘッドが「文法的なつながり」「共参照」など異なる種類の関係を担当でき、表現力が上がります。
| 観点 | シングルヘッド | マルチヘッド |
|---|---|---|
| 注目の観点 | 1種類の関係しか捉えられない | ヘッドごとに別の関係を並列に捉える |
| 各ヘッドの d_k | d_model(大きい) | d_model / h(小さく分割) |
| 総計算量 | ほぼ同等 | ほぼ同等(分割するため) |
| 最後の処理 | そのまま出力 | 全ヘッドを連結し W_O で再投影 |
計算量の面では、Q·Kᵀ が n × n 行列を生むため、系列長 n の二乗 O(n²·d_k) がボトルネックです。長文ほどメモリと計算が急増するのが、コンテキスト長を伸ばす際の根本的な壁になります。
- 式そのもの:
softmax(QKᵀ/√d_k)·Vを、各記号の形状と役割つきで説明できること。 - √d_k の理由:内積の分散が
d_kに比例して増え、softmax 飽和による勾配消失を招くため、標準偏差√d_kで割って分散1に正規化する——分散の議論まで言えると満点。 - 計算量:
O(n²)で系列長に二乗で効くこと。 - Q/K を分ける理由:注目の非対称性を表現するため。
まとめ
Self-Attention は、難解な魔法ではなく**「投影 → 内積 → スケール → softmax → 加重和」という線形代数の素直な連鎖**です。ポイントは、(1) 入力を Q・K・V の3役に分けて非対称な注目を可能にしたこと、(2) 内積で類似度を測ること、(3) 次元増加に伴う内積の分散膨張を √d_k で打ち消し、softmax の勾配を守ったこと。この導出を押さえれば、LLM と Transformer の「動的な重み付け」という説明が、式の裏付けつきで完全に腑に落ちるはずです。土台のネットワークは ニューラルネットワーク も合わせて参照してください。
AI/機械学習 Article
Self-Attention の計算:QKV とスケーリングの導出を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
アテンション
比較で見る軸
難易度: advanced / カテゴリ: AI/機械学習 / タグ数: 5
導入後に効く点
スコアを √d_k で割って softmax にかけ、合計1の重みに正規化。これを Value の重み付き和にしたものが出力。式は Attention(Q,K,V)=softmax(QKᵀ/√d_k)·V。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- AI/機械学習
- タグ数
- 5
判断チェックリスト
- 自社の用途が「アテンション / Transformer」に近いか確認する。
- 強みである「各トークンを Query・Key・Value の3つのベクトルに線形変換し、QとKの内積で「どのトークンをどれだけ見るか」の類似度スコアを作る。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。