首页/在线代码库/demo17_attention.py

demo17_attention.py

手写 scaled dot-product attention: Query 与 Key 做点积 -> softmax 归一化 -> 加权求和 Value。 用一句话(3 个词)的简单向量演示: 每个词如何"关注"其他词。

Python 56 行 系列:核心讲义 🔒 源码仅供在线学习,不提供文件下载
完整源码 · 在线查看demo17_attention.py
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
"""演示17: 注意力机制 — 全局关联的"聚光灯"。

手写 scaled dot-product attention:
Query 与 Key 做点积 -> softmax 归一化 -> 加权求和 Value。
用一句话(3 个词)的简单向量演示: 每个词如何"关注"其他词。
"""
import os
import numpy as np
import matplotlib.pyplot as plt
from figure_style import figures_dir, configure

configure()

OUT = figures_dir()
os.makedirs(OUT, exist_ok=True)


def softmax(x):
    e = np.exp(x - x.max(axis=-1, keepdims=True))
    return e / e.sum(axis=-1, keepdims=True)


def attention(Q, K, V):
    """Scaled Dot-Product Attention: softmax(QK^T / sqrt(dk)) V"""
    dk = K.shape[1]
    scores = Q @ K.T / np.sqrt(dk)
    weights = softmax(scores)
    return weights @ V, weights


# 3 个词的随机向量, 构造出明显的关注关系(手工设定使第2个词主导)
words = ["w1", "w2", "w3"]
Q = np.array([[1.0, 0.0], [0.2, 1.0], [0.9, 0.1]])   # 3 个 query
K = np.array([[0.1, 1.0], [1.0, 0.2], [0.0, 1.0]])   # 3 个 key
V = np.array([[0.1, 0.1], [1.0, 1.0], [0.2, 0.5]])   # 3 个 value

out, attn = attention(Q, K, V)
print("注意力权重矩阵:\n", np.round(attn, 3))

fig, ax = plt.subplots(figsize=(6.5, 5.5))
im = ax.imshow(attn, cmap="YlOrRd")
ax.set_xticks(range(3)); ax.set_yticks(range(3))
ax.set_xticklabels([f"K:{w}" for w in words], fontsize=11)
ax.set_yticklabels([f"Q:{w}" for w in words], fontsize=11)
for i in range(3):
    for j in range(3):
        ax.text(j, i, f"{attn[i, j]:.2f}", ha="center", va="center", fontsize=11)
ax.set_title("注意力权重: 每个 Query 如何分配关注(行和为 1)\n"
             "Attention = softmax(QKᵀ/√dₖ)V", fontsize=11)
ax.set_xlabel("Key(被关注)"); ax.set_ylabel("Query(关注者)")
fig.colorbar(im, ax=ax)
fig.tight_layout()
out = os.path.join(OUT, "fig_ai_attention.png")
fig.savefig(out, dpi=150)
print(f"-> {out}")

输出图

fig_ai_attention.png
输出图 · fig_ai_attention.png