🧠 图解记忆:Q 和 K 算关注权重,缩放稳定 Softmax,再用权重汇总 V;点击图片可查看原图。
💡 答案要点
Self-Attention = 让序列中的每个元素都能关注其他所有元素
数学公式:
Attention(Q, K, V) = softmax(QK^T / √d_k) V详细步骤:
1. 生成 Q、K、V:
python
# 输入:X (batch_size, seq_len, d_model)
# 例如:(1, 5, 512)
# 通过线性变换生成 Q、K、V
Q = X @ W_Q # (batch_size, seq_len, d_k)
K = X @ W_K # (batch_size, seq_len, d_k)
V = X @ W_V # (batch_size, seq_len, d_v)
# W_Q, W_K, W_V 是可学习的权重矩阵
# d_k = d_v = d_model / num_heads (通常 64)2. 计算注意力分数:
python
# 点积计算相似度
scores = Q @ K.T # (batch_size, seq_len, seq_len)
# 例如:(1, 5, 5)
# 缩放(避免点积随维度增大,使 Softmax 过度饱和)
scores = scores / math.sqrt(d_k)
# 应用mask(可选,Decoder用)
if mask is not None:
scores = scores.masked_fill(mask == 0, -1e9)3. Softmax归一化:
python
# 每一行做softmax,得到注意力权重
attention_weights = softmax(scores, dim=-1)
# (batch_size, seq_len, seq_len)
# 权重和为1
assert attention_weights.sum(dim=-1) == 1.04. 加权求和:
python
# 用注意力权重加权V
output = attention_weights @ V
# (batch_size, seq_len, d_v)完整示例(序列长度=3):
展开 Python 代码示例(31 行)
python
# 输入
X = [[1.0, 0.5], # token 1
[0.8, 1.0], # token 2
[0.5, 0.9]] # token 3
# 假设 W_Q = W_K = W_V = I(单位矩阵)
Q = K = V = X
# 1. 计算相似度矩阵
scores = Q @ K.T
# [[1.25, 1.3, 0.95],
# [1.3, 1.64, 1.3],
# [0.95, 1.3, 1.06]]
# 2. 缩放(假设 d_k=2)
scores = scores / sqrt(2)
# [[0.88, 0.92, 0.67],
# [0.92, 1.16, 0.92],
# [0.67, 0.92, 0.75]]
# 3. Softmax
attention_weights = softmax(scores, dim=-1)
# [[0.32, 0.35, 0.33], # token 1 对 3 个token的注意力
# [0.28, 0.44, 0.28], # token 2 对 3 个token的注意力
# [0.29, 0.37, 0.34]] # token 3 对 3 个token的注意力
# 4. 加权求和
output = attention_weights @ V
# [[0.77, 0.80], # token 1的输出
# [0.76, 0.87], # token 2的输出
# [0.74, 0.82]] # token 3的输出为什么要缩放(除以√d_k)?
问题:
当 d_k 很大时(如512),QK^T 的值会很大
→ Softmax 梯度接近0(饱和)
→ 梯度消失
解决:
除以 √d_k,将方差缩放到1
→ 保持Softmax输入在合理范围
→ 梯度稳定面试话术:
"Self-Attention 先用 QK^T 计算相关性,再除以 √d_k,避免维度增大时点积过大导致 Softmax 饱和;随后归一化权重并对 V 加权求和。"
