「アテンション」「Q・K・V」「内積を取ってソフトマックス」が、何を突き合わせているのか像が結べない。
各位置がクエリ Q を出し、過去の各位置のキー K との一致度(内積)を測り、ソフトマックスで配分ウェイトに直して、過去のバリュー V を加重平均する。「いまの文字が、過去のどの文字に注目すべきか」を決める仕組み。
入金消込の突合そのもの。当月の入金(クエリ Q)を、過去に切った請求の一覧(キー K)と1件ずつ突き合わせ、金額・取引先・日付の近さで一致度スコアを出す。
その一致度を softmax で「合計100%の配分ウェイト」に直し、各請求の金額(バリュー V)を加重平均する。一致度の高い請求に多く引き当て、関係ない請求はほぼ0。これが「過去のどこに注目するか」の重み付け。
内積 Q·K が一致度、√次元での割り算はスコアが暴れないようにする調整、softmax が配分、Σ ウェイト×V が引当結果。複数ヘッドは「金額観点の突合」「取引先観点の突合」を別々に走らせて結合する、いわば複数の照合基準の併用。
クエリ(当月入金)と各キー(過去の請求)の内積 Q·K が一致度。それを softmax で 合計100%の配分ウェイトに直し、各請求の金額(V)を加重平均します。 入金特徴を動かすと、一致度の高い請求にウェイトが集中し、引当額がそちらへ寄るのが見えます。これが「過去のどこに注目するか」の突合です。
⚠️ 実際は多ヘッド・因果マスク付きで、V は金額そのものでなく学習された値。突合の直感に寄せた例示。
この簿記アナロジーが、Karpathy のオリジナル200行のどの行に当たるか。
for h in range(n_head): # ヘッド=照合基準ごとに突合
q_h = q[hs:hs+head_dim]
k_h = [ki[hs:hs+head_dim] for ki in keys[li]]
v_h = [vi[hs:hs+head_dim] for vi in values[li]]
# 一致度=Q·K を √次元 でスケール(入金×各請求の突合スコア)
attn_logits = [sum(q_h[j] * k_h[t][j] for j in range(head_dim)) / head_dim**0.5
for t in range(len(k_h))]
attn_weights = softmax(attn_logits) # 配分ウェイト(合計1)に正規化
head_out = [sum(attn_weights[t] * v_h[t][j] for t in range(len(v_h)))
for j in range(head_dim)] # 一致度で V を加重平均=加重引当q·k/√d で一致度を測り、softmax で配分ウェイトに直し、Σ weight×v で過去の値を加重平均=入金消込の突合と加重引当。
出典: karpathy / microgpt.py (本体は原文ママ、コメントのみ日本語に補足)