🧠 图解记忆:Q 与 K 决定看谁,权重再聚合 V 的内容;点击图片可查看原图。
💡 答案要点
Q K V = Query(查询)、Key(键)、Value(值)
生成过程
步骤1: 输入embedding
python
# 输入序列: "我 爱 AI"
input_ids = [101, 234, 567] # token IDs
embeddings = embedding_layer(input_ids) # shape: (3, 512)
# 每个token → 512维向量
# 加上位置编码
position_encodings = get_position_encoding(3, 512)
input_repr = embeddings + position_encodings # shape: (3, 512)步骤2: 线性变换生成Q K V
python
# 3个可学习的权重矩阵
W_Q = nn.Linear(512, 512) # Query权重
W_K = nn.Linear(512, 512) # Key权重
W_V = nn.Linear(512, 512) # Value权重
# 生成Q K V
Q = W_Q(input_repr) # shape: (3, 512)
K = W_K(input_repr) # shape: (3, 512)
V = W_V(input_repr) # shape: (3, 512)为什么需要3个矩阵?
- Q(查询): "我想找什么信息?"
- K(键): "我能提供什么信息?"
- V(值): "我包含什么信息?"
类比搜索引擎:
Q = 用户搜索词 "Python教程"
K = 文档标题 ["Python入门", "Java教程", "Python高级"]
V = 文档内容 [实际的Python教程文本]
步骤:
1. Q与每个K计算相似度 → 注意力分数
2. 用分数加权V → 最终输出Multi-Head Attention详细计算
步骤1: 拆分成多个头
python
num_heads = 8
d_model = 512
d_k = d_model // num_heads # 512 / 8 = 64
# 将Q K V reshape成多头
Q_multi = Q.view(batch_size, seq_len, num_heads, d_k)
# shape: (batch, 3, 8, 64)
K_multi = K.view(batch_size, seq_len, num_heads, d_k)
V_multi = V.view(batch_size, seq_len, num_heads, d_k)
# 转置: (batch, num_heads, seq_len, d_k)
Q_multi = Q_multi.transpose(1, 2) # (batch, 8, 3, 64)
K_multi = K_multi.transpose(1, 2)
V_multi = V_multi.transpose(1, 2)步骤2: 每个头独立计算Attention
python
# Scaled Dot-Product Attention
scores = torch.matmul(Q_multi, K_multi.transpose(-2, -1))
# shape: (batch, 8, 3, 3)
# 3×3矩阵: 每个token对所有token的注意力分数
# 缩放(避免点积过大导致 Softmax 饱和)
scores = scores / math.sqrt(d_k) # 除以√64 = 8
# Softmax归一化
attention_weights = F.softmax(scores, dim=-1)
# shape: (batch, 8, 3, 3)
# 加权求和
output = torch.matmul(attention_weights, V_multi)
# shape: (batch, 8, 3, 64)步骤3: 拼接所有头
python
# 转置回来
output = output.transpose(1, 2) # (batch, 3, 8, 64)
# 拼接
output = output.contiguous().view(batch_size, seq_len, d_model)
# shape: (batch, 3, 512) # 8×64 = 512
# 最终线性变换
output = W_O(output) # W_O: (512, 512)完整示例(数值):
python
# 假设seq_len=3, d_k=4 (简化)
Q = [[1,0,1,0], # token1的Query
[0,2,0,2], # token2的Query
[1,1,1,1]] # token3的Query
K = [[0,1,0,1], # token1的Key
[1,1,1,1], # token2的Key
[2,2,2,2]] # token3的Key
# 步骤1: Q × K^T
scores = Q @ K.T
# [[1,2,4],
# [4,4,8],
# [2,4,8]]
# 步骤2: 缩放
scores = scores / sqrt(4) = scores / 2
# [[0.5,1,2],
# [2,2,4],
# [1,2,4]]
# 步骤3: Softmax
weights = softmax(scores, dim=-1)
# [[0.18, 0.24, 0.58], # token1关注token3最多
# [0.12, 0.12, 0.76], # token2关注token3最多
# [0.09, 0.24, 0.67]] # token3关注自己最多
# 步骤4: 加权求和Value
output = weights @ V面试话术:
"Q K V的本质是3种视角看同一个信息。Q是'我要找什么',K是'我能匹配什么',V是'我的内容是什么'。Multi-Head让模型从8个不同角度理解文本,比如一个头关注语法,另一个关注语义。"
