Attention · token mixing
让 position j 的 value 进入 position i。连接权重 A 随输入变化。
[N,K,M] → across K → [N,K,M]EECS498 · Transformer II · 10
不要从公式背 Q/K/V。先要求 slept 真正取得 animal 的信息,再一步步推到 softmax(QKᵀ)V。
30-second recall
你写过 two-loop、batched two-loop、no-loop attention,再封装 SelfAttention 与 MultiHeadAttention。
A[i,j] 到底是谁从谁读?1. A[2,1] 很大,正确解释是?
2. 真正把位置 j 的内容带进输出 i 的运算是?
3. 模型训练完成后,面对两句不同输入,什么会变?
subtract、两组符号与 digits 相互读取;本课先用 The animal slept 隔离机制,下一课再回到完整 arithmetic flow。句子 The animal slept 查表并加入位置后,得到三个 vectors:
The → x₀
animal → x₁
slept → x₂
若三个位置各自只通过 per-position MLP,x₂ 仍只来自 embedding(slept)+position(2);同一套 MLP 不会读取 x₁。它可以把“slept”这个特征变复杂,却没有一条 edge 把本句主语搬过来。
slept 在 “The animal slept” 和 “The machine slept” 中经过同一 per-position function 会得到同样结果(忽略位置外其他输入),无法成为真正的 contextual representation。
我们希望新的 slept 状态可以是其他位置所提供信息的组合:
new_slept
= 0.05 · information(The)
+ 0.80 · information(animal)
+ 0.15 · information(slept)这一步尚未回答权重从哪里来。它先明确目标:位置 2 的输出数值应该真的含有位置 1 的信息。
qᵢ·kⱼ 给 query i 与 key j 一个可微分的 compatibility score。yᵢ=ΣⱼAᵢⱼvⱼ。Q = XWQ [N,K,D]
K = XWK [N,K,D]
V = XWV [N,K,Dv]
S = QKᵀ/√D [N,K,K] matching scores
A = softmax(S) [N,K,K] dynamic read addresses
Y = AV [N,K,Dv] retrieved information
Q/K 决定本次输入中“去哪里读”;V 决定“读到后搬什么”。Attention 是输入相关、每次 forward 重新构造的 token-to-token 路由。
可以。这会形成一种合法 attention:原始 feature 同时承担匹配与传递。但它强迫“容易被找到的 feature”和“值得发送的 feature”完全相同。
独立 projections 让模型分别学习:如何提出查询、如何被匹配、实际发送什么。例如一个 token 可用“像名词”这一 feature 被匹配,却把数值、语义或位置信息的另一组合发出去。
加法本身只得到一条合成 vector,还需要另一个 function 才变成 scalar score。dot product 直接提供高维 feature matching,能以矩阵乘法并行计算所有 pairs,且可微分。它是高效 parameterization,不是数学宇宙中唯一可能的 attention;additive attention 也存在。
你只保留“从哪里读”的地址矩阵,却没有把源位置的 feature 内容搬到当前位置。A 可以用于分析路由,但不能替代新的 token representation。
对 K=3 的句子,一张可能的 attention matrix 是:
reader ↓ / source → The animal slept
The .70 .20 .10
animal .10 .80 .10
slept .05 .80 .15row i = 谁在读;column j = 从谁读。所以 A[2,1]=0.80 表示输出位置 slept 从 value 位置 animal 读取 80%。它不表示 animal 从 slept 读,也不证明两者 embedding 相同。
Inline check. 若 cross-attention A shape 是 [N,4,9],A[n,3,7] 是?
设 values 是二维 vectors:
V₀ = [1,0] V₁ = [0,2] V₂ = [1,1]
A₂ = [.05, .80, .15]
Y₂ = .05V₀ + .80V₁ + .15V₂
= [.05,0] + [0,1.60] + [.15,.15]
= [.20,1.75]
V₁ 的第二个分量以 0.80×2 真实进入 Y₂。这不是“模型仿佛知道 animal”;它是可在 tensor 中逐项核对的 value mixing。
Aᵢⱼ 确实控制这一 head、这一层的 value mixing;但大权重不等于该 token 是最终决策的唯一原因。residual 保留旧状态,多个 heads/layers 继续组合,MLP 改变 features,下游 logits 还依赖完整计算图。
Your code · 2023
win22/A5/transformers.py · scaled_dot_product_no_loop_batch()
scores = torch.bmm(query, key.transpose(1, 2))
scores /= math.sqrt(M)
scores = torch.masked_fill(scores, mask, -1e9)
weights_softmax = F.softmax(scores, dim=-1)
y = torch.bmm(weights_softmax, value)query[N,Kq,D]key.transpose(1,2)[N,D,Kv]scores[N,Kq,Kv]softmax(dim=-1)每个 reader 对所有 sources 归一化value[N,Kv,Dv]y[N,Kq,Dv]这段代码不仅是“vectorization trick”。它把 two-loop 中每一个 (i,j) dot product 汇总成 batch matrix multiply。Notebook 中 loop 与 no-loop 的小 relative error,是在验证两种执行方式表达同一机制。
若 q/k 各分量近似零均值、单位方差,D 项乘积相加使 dot product variance 约随 D 增长。D 大时 logits 绝对值变大,softmax 迅速接近 one-hot,非最大位置 gradient 变小。除 √D 把 score 的典型尺度拉回较稳定范围。它不是为了让 row sum=1——那是 softmax 的工作。
让 position j 的 value 进入 position i。连接权重 A 随输入变化。
[N,K,M] → across K → [N,K,M]对每个 position 独立应用同一 nonlinear function;主要在 M/hidden feature 轴上变换。
M → M_hidden → M, repeated over K“token mixing vs channel transformation”是好用视角,不是说模块绝对只做一种语义工作。关键结构事实是:标准 position-wise MLP 没有跨 K 轴读取;attention 有。
| 对象 | 训练后推理时 | 是否随输入改变 |
|---|---|---|
| WQ/WK/WV/WO | 固定 parameters | 否 |
| Q/K/V activations | 本次 forward 产生 | 是 |
| scores / A | 本次 forward 产生 | 是 |
| MLP weights | 固定 parameters | 否 |
句子 The animal didn't cross the street because it was tired. 中,不同 heads 可能形成不同匹配:代词↔实体、动词↔主语、局部邻接、结构标记。这里是 conceptual intuition,不代表人为指定每个 head 的功能,也不保证训练后出现整洁的可解释分工。
M = H × Dh
per head Q,K,V [N,K,Dh]
per head output [N,K,Dh]
concat H heads [N,K,H·Dh] = [N,K,M]
output projection [N,K,M]
Your code · 2023
win22/A5/transformers.py · MultiHeadAttention
heads = [head(query, key, value, mask)
for head in self.heads]
heads = torch.cat(heads, dim=-1)
output = self.linear_mult(heads)每个 head 有独立 projections,concat 汇总 payload,最后 projection 让不同 heads 的 feature 重新混合。
[32,9,9] 与 [32,9,24]。output feature width 来自 V,不来自 Q/K。
softmax 是均匀 1/K,输出是 values 的平均;本 row 没有内容选择性。
X 变导致 Q/K 变,dot products 随之改变。dynamic 指 routing activations 动态,不是 parameters 每次改写。
K 是寻址 feature,不必包含希望传输的 payload;V 允许匹配空间与内容空间解耦。
A 是 [N,4,9],若 V width Dv,output 为 [N,4,Dv];不同长度通常更像 cross-attention。
A[i,j]。Y=AV 证明了信息交换?Then I implemented: QKᵀ → scale → mask → softmax → ×V.
Now I understand: 当前 position 用 Q 寻址所有 K,得到本次输入特有的读取分布 A,再用 A 搬运 V;Q/K 决定怎么找,V 决定真正拿走什么。
Self-attention 规定 Q/K/V 来自同一组;cross-attention 允许 decoder queries 去读 encoder memory;causal mask 再限制哪些 sources 合法。下一课沿 arithmetic example 走完三条信息流。
Based on your implementation