← STEP 5・モデル本体(Transformer) に戻る

アテンション ― 入金消込の突合(マッチング)

記事で詰まったところ

「アテンション」「Q・K・V」「内積を取ってソフトマックス」が、何を突き合わせているのか像が結べない。

機械学習ではこう言う

各位置がクエリ Q を出し、過去の各位置のキー K との一致度(内積)を測り、ソフトマックスで配分ウェイトに直して、過去のバリュー V を加重平均する。「いまの文字が、過去のどの文字に注目すべきか」を決める仕組み。

入金消込の突合(マッチング)

入金消込の突合そのもの。当月の入金(クエリ Q)を、過去に切った請求の一覧(キー K)と1件ずつ突き合わせ、金額・取引先・日付の近さで一致度スコアを出す。

その一致度を softmax で「合計100%の配分ウェイト」に直し、各請求の金額(バリュー V)を加重平均する。一致度の高い請求に多く引き当て、関係ない請求はほぼ0。これが「過去のどこに注目するか」の重み付け。

内積 Q·K が一致度、√次元での割り算はスコアが暴れないようにする調整、softmax が配分、Σ ウェイト×V が引当結果。複数ヘッドは「金額観点の突合」「取引先観点の突合」を別々に走らせて結合する、いわば複数の照合基準の併用。

言葉の対応表

microGPT(機械学習)
会計・簿記の言葉
クエリ Q
消し込みたい当月の入金
キー K
過去に切った請求(突合の候補)
Q·K(内積)
入金と請求の一致度スコア
softmax(Q·K)
一致度を配分ウェイト(合計100%)に正規化
Σ ウェイト×V
一致度で加重した引当(注目先の値の取り込み)

触って確かめる

当月の入金(クエリ Q)― 突き合わせたい側
過去の請求(キー K・金額 V)一致度 Q·K → 配分ウェイト
請求A特徴[1, 0] / 金額 50万
一致度 0.5733.0%
請求B特徴[0, 1] / 金額 30万
一致度 0.1421.6%
請求C特徴[0.7, 0.7] / 金額 80万
一致度 0.4930.7%
請求D特徴[-0.5, 0.3] / 金額 20万
一致度 -0.2414.7%
加重引当(Σ ウェイト × 金額)50.5 万円最も一致 → 請求A

クエリ(当月入金)と各キー(過去の請求)の内積 Q·K が一致度。それを softmax で 合計100%の配分ウェイトに直し、各請求の金額(V)を加重平均します。 入金特徴を動かすと、一致度の高い請求にウェイトが集中し、引当額がそちらへ寄るのが見えます。これが「過去のどこに注目するか」の突合です。

⚠️ 実際は多ヘッド・因果マスク付きで、V は金額そのものでなく学習された値。突合の直感に寄せた例示。

実際のコード(microgpt.py L123-133)

この簿記アナロジーが、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 (本体は原文ママ、コメントのみ日本語に補足)