想象你走进一个热闹的派对,灯光昏暗,人声嘈杂。你想找到好朋友小美,但你不会挨个拉住每个人细细盘问——你会快速扫过每个人的脸,心里默默打分:“这个人像小美,三分;那个人戴着红围巾,像七分;那边那个笑起来的弧度,九分!”你的目光会不自觉地越过高个子,绕过端着酒杯的人群,最终牢牢锁定在最像小美的那个人身上。你没有忽略其他人,只是把注意力按“相似程度”分配出去。Attention 机制(注意力机制)做的是完全相同的事:在一条句子里,每个词都会“扫视”其他所有词,给它们打分,然后把注意力按照分数分配过去,最终从众人身上提炼出一个最合适的“印象”。这篇指南将带你把 Attention 的每一步拆解成派对上的一次次“找人”:谁在找、谁是目标、怎么打分、怎么聚焦、怎么多视角观察、怎么在面试时把这个故事讲得漂亮。

岗位关联

掌握 Attention 的数学直觉和讲解框架,你将在 AI 面试中展现出 Transformer 深度理解者的底气——这是大模型时代最核心的必考知识之一。

目录
  1. 可视化演示
  2. 认识注意力
  3. 三要素QKV
  4. 点积打分
  5. 缩放归一化
  6. 加权求和
  7. 多头注意力
  8. 可视化解读
  9. 面试要点
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

本节配有交互动效(进入视口后自动加载,约 3KB)。

认识注意力

在派对上找小美之前,你其实无意中已经“训练”好了自己的注意力系统。你小时候经过很多次聚会,见过形形色色的朋友,逐渐总结出“小美的特征”:笑起来有酒窝、爱穿红色连衣裙、说话时爱用手比划。当天晚上,你的大脑不是把每个陌生人都单独研究一遍,而是先过滤掉明显不符合的背景,再把候选者的面容与“小美的印象”比对,最后锁定目标。这就是注意力的雏形:不需要平等对待每个信息,只把资源投向最相关的部分。

在深度学习的世界里,“派对”就是一条输入序列(比如一句英文句子),“朋友”就是序列中的每个词向量。早期自然语言处理模型(如循环神经网络 RNN)处理句子时,必须按顺序从头读到尾,读到最后一个词时,前面的信息往往已经模糊了——就像你在派对上转了一圈,结果把最先见过谁给忘了。Attention 机制的提出,正是为了解决这个“健忘”问题:不依赖顺序,而是让每个词直接“看向”所有其他词,按相关性提取信息。

具体来说,给定句子中第 \( i \) 个词,Attention 会计算它对句子中所有词的“关注程度”,然后按这些程度把它们的表示融合起来,得到一个“懂上下文”的新表示。关注程度高的词(比如代词 it 真正指代的名词 animal)会被突出放大,关注程度低的词(比如语气词 the)会被弱化。这种“按需聚焦”的能力,让模型在翻译中能对齐源语言和目标语言的词,在摘要中能抓住最关键的句子。

回想派对:你并没有真正走到每个人面前交谈,你只是站在原地,用目光完成了一场“大规模扫描 + 打分 + 聚焦”的认知过程。Attention 机制也一样,它用矩阵运算一次完成所有词之间的扫描与打分,再以加权求和的方式把“目光”落到实处。明白了整体轮廓,接下来的问题就很自然了:这场扫描中的“你”、“;被扫的人”和“信息内容”分别是什么?这就是三要素——Query、Key、Value 登场的时候。

三要素QKV

你的寻人过程其实涉及两套信息。第一套是你脑子里关于小美的“印象模板”,用来比对;第二套是派对现场每个人的“姓名牌”和“谈吐举止”,分别是他们对外展示的标签和真实的信息内容。在 Attention 机制中,这三样东西被命名为:Query(查询,Q)、Key(键,K) 和 Value(值,V)。

  • Query(你):代表“我想找什么”。在一条句子里,当前正在处理的词就是 Query,它携带自己的语义去询问别人:“你们谁跟我相关?”
  • Key(姓名牌):代表“我是谁”。序列中每个被查询的词都挂着一张“姓名牌”,也就是一个向量化的标识,用来供 Query 与它做匹配。
  • Value(真实信息):代表“我有什么”。当确定某个词和 Query 很匹配时,Query 需要把它的“内容”取过来,这个内容就是 Value。

在原始输入中,每个词只有一个向量 \( x_i \)。要得到三种角色,需要三组“滤镜”(可学习的权重矩阵)。这个过程叫线性投影:把同一个输入分别乘上三个不同的变换矩阵,得到三种不同语义视角的表示。公式如下:

回到派对:小美的“印象模板”不是凭空冒出来的,它是你过往记忆(经过训练的模型参数)在这个场景下的投影。不同场合你会用不同的模板——找小美当舞伴时关注身高,找小美问作业时关注眼镜。同理,任务不同,学习到的 \( W^Q \) 就不同,同一个词在不同任务里派生的 Q、K、V 也就不同。三要素备齐,接下来就是最关键的环节:如何“打分”来判断一个人像不像小美。

qi=WQxi,ki=WKxi,vi=WVxiq_i = W^Q x_i, \quad k_i = W^K x_i, \quad v_i = W^V x_i
  1. 输入词向量 \( x_i \)派对上的第 \( i \) 位朋友的原始信息,它本身只是个普通的词向量,还没有区分“问别人的人”和“被别人问的人”。
    xi=第 i 个词的嵌入向量x_i = \text{第 } i \text{ 个词的嵌入向量}
  2. 投影矩阵 \( W^Q, W^K, W^V \)三组可学习的参数,相当于三副不同颜色的眼镜。戴上 \( W^Q \) 眼镜,你看到的是“这个朋友像不像我要找的人”;戴上 \( W^K \) 眼镜,你看到的是“这位朋友的自我介绍”;戴上 \( W^V \) 眼镜,你看到的是“这位朋友的真实内涵”。
    WQ,WK,WV∈Rdmodel×dkW^Q, W^K, W^V \in \mathbb{R}^{d_{\text{model}} \times d_k}
  3. 角色分工投影后,\( q_i \) 是“寻找者”向量,\( k_i \) 是“姓名牌”向量,\( v_i \) 是“内容”向量。每个词都同时扮演三种角色:它既在寻找别人(作为 Query),也在等待被别人寻找(作为 Key),还随时准备贡献自己的信息(作为 Value)。
    qi=WQxi,    ki=WKxi,    vi=WVxiq_i = W^Q x_i, \;\; k_i = W^K x_i, \;\; v_i = W^V x_i

点积打分

你和一个人的相似度怎么量化?假设你脑子里有一套“小美特征向量”:酒窝 +2、红裙子 +3、爱比划 +1。眼前这位朋友的“特征向量”是:酒窝 +2、蓝衬衫 +0、爱比划 +1。你只需要把两个向量对应位置相乘再相加:\( 2\times2 + 3\times0 + 1\times1 = 5 \)。用数学语言说,这就是点积。点积越大,表示两个向量方向越一致,也就是“越相似”。

在大规模派对上,你不能只比对一个人,而是要把脑子里的小美模板(Query)和在场所有人的姓名牌(Key)逐一做点积。写成矩阵形式,就是让每个 Query 去点积所有 Key,得到一张 \( n \times n \) 的“分数表”。行代表当前词,列代表被关注的词,数值越高代表当前词应该越关注那个词。具体公式为:

这个打分过程可以用矩阵乘法一次性完成:所有 Query 组成矩阵 \( Q \),所有 Key 组成矩阵 \( K \),分数表就是 \( QK^T \)。计算时,维度越高的向量,点积的数值通常越大——就像你在派对上用越多的特征去比对人,累计的相似度分数天然就越高。这会导致一个问题:分数普遍偏大时,后面的 Softmax 会进入饱和区,梯度变得非常小,模型学不动。所以我们需要一个“调光旋钮”,把分数的量级压回合理范围。

scoreij=qi⋅kj=∑m=1dkqi,m kj,m\text{score}_{ij} = q_i \cdot k_j = \sum_{m=1}^{d_k} q_{i,m} \, k_{j,m}
  1. 点积符号 \( q_i \cdot k_j \)两个向量在数学上做“内积”,直观含义是“二者的相似程度”。如果两个向量同向,点积为正;反向,点积为负;垂直,点积为零。
    qi⋅kjq_i \cdot k_j
  2. 求和符号把两个向量的每一维对应相乘,再把这些乘积加起来。维度 \( m \) 从 1 遍历到 \( d_k \),也就是 Key 向量的长度。
    ∑m=1dkqi,m kj,m\sum_{m=1}^{d_k} q_{i,m} \, k_{j,m}
  3. 分数含义\( \text{score}_{ij} \) 是第 \( i \) 个词对第 \( j \) 个词的原始关注分数。分数高,表示第 \( j \) 个词与第 \( i \) 个词语义上“有话可聊”——就像你认为某个人长得很像小美。
    scoreij∈(−∞,+∞)\text{score}_{ij} \in (-\infty, +\infty)

缩放归一化

想象一下,你用两百个特征去比对人,所有人的分数都算出来是几百上千,你被这堆巨大的数字搞得眼花缭乱,根本无法分辨谁更接近小美。这时候正确的做法是:把分数除以一个标准值,让量级回到个位数级别。在缩放点积注意力中,这个标准值就是 \( \sqrt{d_k} \)(Key 向量维度的平方根)。为什么偏偏是它?因为当向量各维度独立同分布时,两个随机向量的点积方差大约是 \( d_k \),而标准差正好是 \( \sqrt{d_k} \),所以直接除以它,就能让分数保持稳定的方差。

分数缩放之后,还需要把分数变成“百分比式”的注意力权重。Softmax 函数会做两件事:先用指数运算把分数变成正数,并拉开差距;再除以所有分数的总和,使得所有权重加起来等于 1。这样一来,每个词分到的注意力就变成了一个合法的概率分布。完整公式如下:

此时你的“目光”已经有了清晰的分配方案:不再均匀地扫视全场,而是像聚光灯一样,把最亮的光束打在最像小美的那个人身上,其余人只留一点余光。注意这个步骤没有任何“魔法”,完全是可微的数学运算,因此整个 Attention 模块可以端到端地通过反向传播学习——“印象模板”和“打分标准”都会在训练中被自动调优。现在,权重已经就绪,最后一步就是“取货”。

αij=softmax⁡(scoreijdk)=exp⁡(qi⋅kjdk)∑l=1nexp⁡(qi⋅kldk)\alpha_{ij} = \operatorname{softmax}\left(\frac{\text{score}_{ij}}{\sqrt{d_k}}\right) = \frac{\exp\left(\frac{q_i \cdot k_j}{\sqrt{d_k}}\right)}{\sum_{l=1}^{n}\exp\left(\frac{q_i \cdot k_l}{\sqrt{d_k}}\right)}
  1. 缩放除数 \( \sqrt{d_k} \)把点积的数值压缩到标准范围。\( d_k \) 是 Key 向量的维度,比如 64。除以 8 后,一个原本 30 分的相似度会变得平缓可控。
    scoreijdk\frac{\text{score}_{ij}}{\sqrt{d_k}}
  2. 指数函数 \( \exp(\cdot) \)把任意实数变成正数,且原始分数越高,指数放大越猛。这会让高相似度的词获得压倒性的注意力,低相似度的词被压低。
    exp⁡(qi⋅kjdk)\exp\left(\frac{q_i \cdot k_j}{\sqrt{d_k}}\right)
  3. 分母求和对第 \( i \) 行所有词的指数值求和,作为归一化常数。用每个词的指数值除以这个总和,就能确保权重之和为 1。
    ∑l=1nexp⁡(qi⋅kldk)\sum_{l=1}^{n}\exp\left(\frac{q_i \cdot k_l}{\sqrt{d_k}}\right)
  4. 最终权重 \( \alpha_{ij} \)第 \( i \) 个词分配给第 \( j \) 个词的注意力比重。它是 0 到 1 之间的小数,所有 \( \alpha_{ij} \) 加起来正好等于 1。
    αij∈[0,1],∑j=1nαij=1\alpha_{ij} \in [0,1], \quad \sum_{j=1}^{n} \alpha_{ij} = 1

加权求和

打分、归一化都完成了,接下来就是取走融合后的信息。假设你认定“那个人七分像小美”,你既不会完全不看他,也不会只盯着他一个人——你会把他提供的信息乘以 0.7,把另一个有三分像的朋友的信息乘以 0.3,其他人各乘一点极小权重,最后把它们混合成一个综合印象。这个“综合印象”就是 Attention 的输出向量 \( z_i \)。

在数学上,这一步是纯粹的线性加权求和:每个 Value 向量乘上对应的注意力权重,然后全部相加。权重越大,该词的信息在输出中占比越高;权重越小,信息越被背景化。公式如下:

这一步让人想到派对结束后的默默回想:你并没有跟每个人深聊(没有把全部信息塞进脑子),但你已经对每个人的“轮廓”有了加权后的综合印象。对一个词来说,这个综合印象就是模型理解的“这个词在当前语境里的意思”。例如句子 “The animal didn't cross the street because it was too tired“ 中,处理 it 这个词时,模型会给 animal 分配很高的权重,让 it 的输出向量里充满 animal 的气息,这样就完成了指代消解。至此,单个 Attention 头的完整流程已经走完:Q 问 K 打分,Softmax 归一,V 按权重汇聚。但只用一套”小美模板”来观察,会不会漏掉其他重要关系?这就是多头注意力要解决的。

zi=∑j=1nαij vjz_i = \sum_{j=1}^{n} \alpha_{ij} \, v_j
  1. 加权项 \( \alpha_{ij} v_j \)第 \( j \) 个词的内容向量先乘上第 \( i \) 个词分给它的注意力权重。权重为 0 时,贡献为零;权重接近 1 时,几乎原样保留。
    αijvj\alpha_{ij} v_j
  2. 对全部词求和 \( \sum_{j=1}^{n} \)把句子中所有词(从第 1 个到第 \( n \) 个)的加权内容累加起来。这等价于把所有人的信息“对齐到同一个方向”后做混合。
    ∑j=1n\sum_{j=1}^{n}
  3. 输出向量 \( z_i \)第 \( i \) 个词的新表示,它不再是孤立的词向量,而是“戴着上下文眼镜”看世界后的结果——已经融入了与它相关的所有词的语义。
    zi∈Rdvz_i \in \mathbb{R}^{d_v}

多头注意力

你在派对上找小美时,其实不只用一套标准。你可能同时用“外貌”找她、“声音”找她、“聊天内容”找她,甚至用“她身边站着的老朋友”来侧面确认。每一套标准都是一次独立的“打分—聚焦—融合”过程。Multi-Head Attention(多头注意力) 正是这个思路:不用一套 Q/K/V 投影,而是用多组投影并行地做多次 Attention,每次捕获一种类型的关系,最后把所有结果拼接起来。

为什么多头有效?因为真实语言里的相关性非常复杂:一个词可能既在语法上和某个词有主谓关系,又在语义上和另一个词有关联,还在位置上和远处某个词呼应。单一注意力头只能“顾此失彼”,而多头让不同的头各司其职——有的头学的是“指代关系”,有的头学的是“相邻词依赖”,有的头学的是“长距离语义关联”。每个头都有自己的 \( W_h^Q, W_h^K, W_h^V \),独立作用于同样的输入。公式如下:

多头机制让 Transformer 像一支配合默契的侦查小队:每个头独立勘察,最后在指挥部把情报汇总。常见的头数是 8 或 16,通常每个头的维度设置为 \( d_k = d_{\text{model}} / H \),保证总体计算量相对稳定。也正因为有了多头,模型才能在机器翻译中同时考虑“词义搭配”和“语序结构”这些截然不同的关系,而不必靠单一模板硬扛全局。理解了多头,Attention 的完整流程已经全部展开,下一步,我们看看训练好的注意力长什么样。

head⁡h=Attention⁡(QWhQ, KWhK, VWhV)\operatorname{head}_h = \operatorname{Attention}\left(QW_h^Q, \, KW_h^K, \, VW_h^V\right)
MultiHead⁡(Q,K,V)=Concat⁡(head⁡1,…,head⁡H)WO\operatorname{MultiHead}(Q,K,V) = \operatorname{Concat}\left(\operatorname{head}_1, \dots, \operatorname{head}_H\right) W^O
  1. 第 \( h \) 个头的投影 \( QW_h^Q \)每个头使用自己专属的投影矩阵 \( W_h^Q \),把原始 Query 变换到不同的子空间。这就像给每个“观察员”发一副特殊滤镜,让他只注意某种特定特征。
    QWhQ,KWhK,VWhVQW_h^Q, \quad KW_h^K, \quad VW_h^V
  2. 独立注意力 \( \operatorname{Attention}(\cdot) \)每个头内部执行完整的缩放点积注意力(打分、缩放、Softmax、加权求和),输出该视角下的融合向量。
    head⁡h=Attention⁡(QWhQ,KWhK,VWhV)\operatorname{head}_h = \operatorname{Attention}\left(QW_h^Q, KW_h^K, VW_h^V\right)
  3. 拼接 \( \operatorname{Concat}(\cdot) \)把 \( H \) 个头各自产出的向量在特征维度上首尾相接,形成一个更长的向量。它完整保留了每个观察视角的结论,而不是粗暴地平均。
    Concat⁡(head⁡1,…,head⁡H)\operatorname{Concat}\left(\operatorname{head}_1, \dots, \operatorname{head}_H\right)
  4. 输出投影 \( W^O \)拼接后的长向量再乘一个可学习的矩阵 \( W^O \),把多个视角的信息混合压缩回模型的隐藏维度 \( d_{\text{model}} \),以便后续层正常处理。
    MultiHead⁡(Q,K,V)=Concat⁡(⋯ )WO\operatorname{MultiHead}(Q,K,V) = \operatorname{Concat}(\cdots) W^O

可视化解读

你在派对上的目光分配,其实可以被记录下来:在每个人脸旁边标一个数字(0% 到 100%),画成一张“谁在看谁”的热力图。Attention 的可视化就是做这样的事——训练好的模型里,每个头的注意力权重矩阵可以直接画成热力图,一眼看出句子中哪些词之间存在强关联。

著名的 “Attention is All You Need“ 论文中,作者就展示了多头注意力的可视化结果。比如在英语翻译任务中,有一个头会特别关注句子的句法结构:动词和它的宾语之间会出现很亮的格子;另一个头则更关注”距离较远的语义关联“,比如句首的指代词和句尾的实际名词。你还能观察到,不同头处理同一个句子时,它们的注意力模式明显不同——这印证了”多视角“的价值。对于 ”it“ 这样的歧义词,热力图会清楚显示它把最多的注意力分配给了前文的 ”animal”,这就是模型解决指代消解的方式。

注意可视化有两个层次的信息。第一是权重本身:热力图中格子的亮度即 \( \alpha_{ij} \),它展示的是模型当前关注什么,这是一个定量结果。第二是模式归纳:通过对大量句子的观察,研究者能总结出某个头倾向于关注相邻词还是远距离词,从而推断它扮演的“角色”。这种可解释性,正是传统 RNN 难以提供的——RNN 的中间状态很难直观映射到某个词与另一个词的关系上。

用派对的比喻来收尾:热力图就像一张“目光交流记录表”,看到它,你就知道刚才那场派对中谁在频繁看向谁、谁和谁之间有微妙的眼神互动。当我们需要调试一个翻译模型时,先看热力图往往比直接拍脑袋调参数更有效。搞懂了 Attention 的原理和可视化,最后一步就是把这些理解组织成面试官听得懂、记得住的回答。

面试要点

面试官问起 Attention 时,最常见的要求是:“用一个例子讲清楚它是什么,再说说公式里每个符号的含义。”这正好用上我们的派对比喻:你站在派对中,用脑子里的“小美模板”(Query)去比对每个人的“姓名牌”(Key),打完分后按比例去取每个人的“信息”(Value),最后混合成对全场的一个综合印象。用故事开场,能让对方 30 秒内建立画面感,再自然地引出公式。

讲解公式时,建议采用递进路线:先讲 \( q_i \cdot k_j \) 是打分,再讲除以 \( \sqrt{d_k} \) 是为了防止点积过大导致 Softmax 饱和,再讲 Softmax 把分数变成和为 1 的权重,最后讲加权求和得到输出。如果面试官追问“为什么 Transformer 不用 RNN”,你要答出核心:Self-Attention 是并行计算的,它的每一步都是矩阵运算,不依赖上一个时间步的输出;同时它能直接建模任意两个词之间的依赖,而不像 RNN 那样需要信息逐时间步传递,因此长距离依赖问题得到缓解。代价是复杂度从 RNN 的 \( O(n) \) 升到了 \( O(n^2) \),所以会有稀疏注意力等改进方向。

还有一类面试题是手写缩放点积注意力。写代码时抓住三个要点:一是不要忘了除以 \( \sqrt{d_k} \);二是为了数值稳定性,Softmax 前要先减去最大值;三是如果传入 mask(比如 padding 位置),要在 Softmax 前把被遮蔽的位置设为一个极大的负数比如 \(-1e9\),使它们指数后趋近于零。全程用批处理思维,把注意力写成矩阵乘法,而不是 Python 循环,就能体现出工程素养。

面试最后往往还有一题:“多头注意力的每个头都在学什么?”你可以回答:不同的头在学习不同类型的相关性——语法关系、共指关系、相邻依赖等,这是可视化实验反复观察到的结论。用派对故事收束全文:一个头负责看外貌,一个头负责听声音,再有一个头观察她和谁交谈,多视角综合,才形成一个真正立体的判断。把故事、公式、代码三段打通,面试官自然会记住你。

AI 应用场景

机器翻译:让源语言与目标语言自动对齐

阶段:模型架构设计

解决的问题:传统机器翻译用 RNN 编码器把整个源句压缩成一个固定向量,再逐词生成译文。句子一长,开头的信息到结尾就严重衰减,译文质量急剧下降。Attention 让解码器在生成每一个目标词时,都主动“回望”源句中的所有词,并给予语义相关词更高的权重,相当于译员每翻一个词都重新扫一眼原文中最相关的部分。

具体案例:Google 翻译的 Transformer 系统在处理中文“我喜欢那个穿红裙子的女孩”时,生成英文 “the girl in the red dress“ 的过程中,”girl“ 这个词会通过 Attention 把最大的权重放在”女孩“上,”red“ 对应”红”,从而精准完成词对齐,而不需要把整个句子先装进一个压缩瓶。

文本摘要:抓取文章中最关键的信息

阶段:特征提取与内容选择

解决的问题:生成式摘要需要从长文档中选出最重要的句子或短语,并在摘要中复述。传统抽取式方法依赖人工设定的词频、位置特征,容易抓偏重点;基于 Attention 的摘要模型会让摘要中的每个词去关注原文中与之语义最相关的片段,自动形成“文档信息的地图”。

具体案例:新闻 App 的智能摘要系统在处理一篇体育赛事报道时,Attention 热力图显示摘要中的“绝杀”一词主要关注原文第二节中描述最后 30 秒进球的内容,而“观众沸腾”则关注结尾氛围描写,说明模型准确抓住了事件主线与情绪亮点。

向量检索与推荐:在候选集中“一眼锁定”目标

阶段:召回与排序

解决的问题:在海量商品或文档中检索与用户查询最匹配的条目时,本质也是“Query 扫视所有 Key 并打分”。传统方法依赖关键词精确匹配,无法理解“适合下雨天的运动鞋”这种语义化查询;Attention 风格的双塔模型通过点积相似度计算用户向量与商品向量的匹配分数,天然支持语义检索。

具体案例:电商平台的语义搜索中,用户输入“通勤百搭的黑色皮鞋”,系统利用 Attention 分数向量将 query 中的“百搭”与商品标签“休闲”“商务”建立软关联,排序模型综合多路注意力分数给出结果,比单一关键词匹配的点击率提升了 18%。

Python 演示

python43 行
import numpy as np  def scaled_dot_product_attention(Q, K, V, mask=None):    d_k = K.shape[-1]    scores = Q @ K.T / np.sqrt(d_k)    if mask is not None:        scores = np.where(mask == 0, -1e9, scores)    weights = np.exp(scores - scores.max(axis=-1, keepdims=True))    weights = weights / weights.sum(axis=-1, keepdims=True)    out = weights @ V    return out, weights  def multi_head_attention(X, W_Q, W_K, W_V, W_O, num_heads=4):    batch, seq, d_model = X.shape    d_head = d_model // num_heads    Q = X @ W_Q    K = X @ W_K    V = X @ W_V    Q = Q.reshape(batch, seq, num_heads, d_head).transpose(0, 2, 1, 3)    K = K.reshape(batch, seq, num_heads, d_head).transpose(0, 2, 1, 3)    V = V.reshape(batch, seq, num_heads, d_head).transpose(0, 2, 1, 3)    heads = []    for h in range(num_heads):        out_h, _ = scaled_dot_product_attention(Q[:, h], K[:, h], V[:, h])        heads.append(out_h)    concat = np.concatenate(heads, axis=-1)    return concat @ W_O  if __name__ == "__main__":    np.random.seed(0)    X = np.random.randn(2, 4, 8)    W_Q = np.random.randn(8, 8)    W_K = np.random.randn(8, 8)    W_V = np.random.randn(8, 8)    W_O = np.random.randn(8, 8)    out = multi_head_attention(X, W_Q, W_K, W_V, W_O, num_heads=4)    print("输出形状:", out.shape)    sample = X[0]    _, attn = scaled_dot_product_attention(sample[0], sample, sample)    print("单头注意力权重:\n", np.round(attn, 3))
目的:用 NumPy 从零实现缩放点积注意力与多头注意力,验证 “Q 打分 → Softmax 归一 → 加权求和” 的完整流程。
  1. scores = Q @ K.T / np.sqrt(d_k)一次矩阵乘法算出所有 Query 与 Key 的点积分数,并除以维度平方根做缩放。
  2. np.where(mask == 0, -1e9, scores)把被遮蔽的位置的分数设成极大的负数,使它们在 Softmax 后趋近于零。
  3. np.exp(scores - scores.max(axis=-1, keepdims=True))先减去每行最大值再取指数,是数值稳定版的 Softmax,防止指数爆炸。
  4. out = weights @ V注意力权重矩阵与 Value 矩阵相乘,等价于所有权重的加权求和。
  5. Q.reshape(...).transpose(0, 2, 1, 3)把原始序列拆成 num_heads 个头,每个头分到 d_head 维,完成后维度为 [batch, heads, seq, d_head]。
  6. np.concatenate(heads, axis=-1)把各个头在特征维度上拼接,模拟 Multi-Head 的 “多视角信息汇总”。

常见误区

误区我刚开始学的时候,以为注意力权重是模型额外“脑补”出来的东西,跟输入词本身没关系,只要网络训练好了,权重就是一个固定的表。

正解注意力权重是对当前输入实时计算的结果。它由 Query 和 Key 的点积经过 Softmax 得到,每个句子每个词都会生成不同的权重分布。这就像你在派对上遇到不同的人,目光分配也会随之改变——权重永远是“这一场派对”的权重,而不是一张通用的寻人地图。

为何常见:因为看到可视化热力图是静态的,会误以为权重是训练后固定的;实际上热力图只是某一条测试样本的“快照”。

误区同一时刻 Q=K=V 就是完全相同的向量,Self-Attention 里 Q 和 K 没有区别,都是一个词向量本身。

正解Q、K、V 是对输入 \( X \) 分别施加三组不同线性变换 \( W^Q, W^K, W^V \) 后得到的结果。即使输入相同,经过不同的投影矩阵后,三者处于不同的语义空间。派对比喻里,同一个人可以同时是“被观察者”(Key)、“信息提供者”(Value)和“观察者”(Query),但他在三个角色中呈现的面向完全不同。

为何常见:因为 Self-Attention 的输入确实是同一份 \( X \),有人就误以为三个矩阵完全一样,忽略了三组投影矩阵的存在。

误区一个头只能看到部分信息,必须靠多头才能看到全局;头数越多,模型效果一定越好。

正解每一个注意力头本身观察的已经是“全局”——它会对序列中所有 token 打分,只是它学习到的“关注偏好”各有侧重。多头把多种偏好组合起来,增强了表达能力,但也不是头数越多越好:头数过多会摊薄每个头的维度,导致训练困难、效果下降。派对里找一个人,十个朋友帮忙看是全面,一百个人反而会把目标吵没。

为何常见:把“多视角”误解成“更多视野范围”,而忽略了每个头的注意力范围本身覆盖全部序列。

误区注意力权重包含了词与词之间的位置关系,词在句子里的先后顺序模型自然能感知到。

正解缩放点积注意力对 token 的排列是“置换等变的”——你把句子里的词打乱顺序重新排列,注意力输出的集合完全不变(只是跟着换了位置)。模型完全不知道谁先谁后,所以才需要额外加入位置编码来注入顺序信息。就像派对上的你如果闭着眼睛听声音,将无法判断谁站在你左边还是右边,必须有人告诉你每个人的方位。

为何常见:因为人看热力图时能“看见”矩阵的排列,误以为模型也有这种空间感知,实际上矩阵的每一行是模型无法区分的。

误区注意力权重高 = 这个词本身重要,所以可以把权重最大的词当作关键词提取出来。

正解注意力权重衡量的是“当前 Query 对这个 Key 的相关性”,不是词的全局重要性。同一个词在不同句子、不同位置作为 Query 时,它的注意力分布完全不同;而且一个词作为 Key 被大家关注的总量也可能与它的语义重要性无关。派对中你频繁看向某个人,可能只是因为你们恰好站得近,而不是那个人有多重要。

为何常见:把“相对相关性”误解为“绝对重要性”,忽略了 Query 的存在——没有 Query 的上下文,权重就没有意义。

面试题

Q1. 缩放点积注意力中,为什么要除以 \(\sqrt{d_k}\)?

单选题 · easy

  • A.防止分数过大导致 Softmax 梯度消失← 正确答案
  • B.加速矩阵乘法的运行
  • C.减少模型的总体参数
  • D.保持维度之间的一致性

答案:A。当维度 \( d_k \) 较大时,点积数值的方差会随之增大,极端情况下 Softmax 的输入进入饱和区,梯度趋近于零,模型难以训练。除以 \(\sqrt{d_k}\) 能让分数保持稳定的方差。这就像派对上的分数如果不除以标准值,你会被巨大的数字淹没,无法分辨相似度高低。

Q2. Q、K、V 三个矩阵分别由什么得到?

单选题 · easy

  • A.输入 X 分别乘上 W^Q、W^K、W^V← 正确答案
  • B.输入 X 被直接复制三次
  • C.由输出信号反向推导而来
  • D.通过卷积网络逐层提取

答案:A。Q、K、V 是同一个输入序列 X 分别与三组可学习的投影矩阵相乘的结果,目的是让每个词在不同语义视角下呈现不同表示。复制三次不会引入任何新信息,反向推导和卷积都不是 Attention 的标准做法。

Q3. 在 Self-Attention 中,Query、Key、Value 的来源是?

单选题 · mid

  • A.三者都来自同一个输入序列的线性变换← 正确答案
  • B.Q 来自解码器,K 和 V 来自编码器
  • C.Q、K、V 分别来自三个不同序列
  • D.三者来自随机初始化且不参与训练

答案:A。Self-Attention 的"Self"正是指 Q、K、V 都源自同一个序列本身,让序列中的每个 token 与同序列的其他 token 建立关系。B 描述的是 Transformer 解码器中的 Cross-Attention,而不是 Self-Attention。

Q4. Softmax 在注意力机制中的核心作用是什么?

单选题 · mid

  • A.把分数转成和为 1 的权重分布← 正确答案
  • B.压缩分数但总和不一定为一
  • C.把负分数全部变成正数
  • D.让模型拥有更多的非线性

答案:A。Softmax 在指数化分数后除以总和,使所有权重落在 0 到 1 之间且和为 1,从而形成合法的概率分布,供后续加权求和使用。B 是 Sigmoid 的行为;C 只是 Softmax 的副作用,不是核心目的。

Q5. 相比 RNN,Transformer 的 Self-Attention 有哪些优势?

多选题 · mid

  • A.可以并行计算← 正确答案
  • B.捕捉长距离依赖← 正确答案
  • C.参数总量一定更少
  • D.完全不需要任何编码

答案:AB。Self-Attention 是矩阵运算,不依赖上一步输出,因此可并行;且任意两个词之间都直接建立联系,能有效缓解长距离依赖问题。C 不成立,Transformer 参数不一定更少;D 错误,Self-Attention 没有顺序信息,必须加位置编码。

Q6. Multi-Head Attention 输出的最后一步操是什么?

单选题 · mid

  • A.拼接各头输出后乘权重 W^O← 正确答案
  • B.各头输出取一次简单的平均
  • C.各头输出相加后除以头数
  • D.各头输出进行逐元素取最大值

答案:A。多头注意力把每个头的输出在特征维度上拼接起来,得到一个维度为 \( H \times d_v \) 的向量,再通过输出投影矩阵 \( W^O \) 压缩回模型维度。平均或取最大值都会丢失每个头独有的视角信息。

Q7. 为什么 Transformer 必须额外加入位置编码?

单选题 · hard

  • A.Self-Attention 本身不含序列顺序信息← 正确答案
  • B.为了让模型的参数数量变得更多
  • C.防止 Self-Attention 过拟合
  • D.让注意力权重能够归一化

答案:A。Self-Attention 对 token 的排列是置换等变的,把句子中的词打乱顺序,输出的集合不变,模型无法感知先后关系。因此必须通过位置编码注入顺序信息。这与参数量、过拟合和归一化都没有关系。

Q8. 多头注意力中,不同头的投影矩阵之间是什么关系?

单选题 · mid

  • A.每个头拥有独立的一组 W^Q、W^K、W^V← 正确答案
  • B.所有头共享同一组投影矩阵
  • C.只有 W^Q 是每个头独立的
  • D.只有 W^V 是每个头独立的

答案:A。每个头都使用自己专属的三组投影矩阵,将输入映射到不同的子空间,从而学习不同类型的关系。若所有头共享同一组矩阵,多头就退化成了单头,无法实现多视角观察。

Q9. 关于注意力可视化的描述,正确的有哪些?

多选题 · hard

  • A.可以生成 token 间注意力权重的热力图← 正确答案
  • B.能看出不同头关注不同语法关系← 正确答案
  • C.展示的是训练好的模型权重← 正确答案
  • D.展示的是梯度值的大小

答案:ABC。注意力权重矩阵可以直接画成热力图,研究者能从中观察各头关注的语法模式,所以 A、B、C 正确。可视化展示的是注意力权重而非梯度,D 错误。简言之,热力图是对“目光分配”的记录,不是对“学习信号”的记录。

Q10. 长度为 n 的序列,Self-Attention 的计算复杂度是多少?

单选题 · easy

  • A.O(n²)← 正确答案
  • B.O(n log n)
  • C.O(n)
  • D.O(n³)

答案:A。Self-Attention 需要计算 n 个 Query 与 n 个 Key 的两两点积,得到 n×n 的分数矩阵,因而时间和空间复杂度都是 O(n²)。这与 RNN 的 O(n) 串行计算形成对比,也是后续稀疏注意力等改进的出发点。