


前序:注意力机制使机器学会了“关注”
想象你在一个嘈杂的酒会上,周围人声鼎沸,觥筹交错。奇妙的是,你依然能听清对面朋友说的每一句话——你的大脑自动过滤掉了背景噪音,将听觉的聚光灯锁定在朋友的声音上。如果这时突然有人喊你的名字,你的注意力又会瞬间转移过去。
这种在纷繁信息中筛选重点、分配资源的能力,对人类而言轻而易举,但对机器来说,却曾是难以逾越的天堑。
在很长一段时间里,人工智能处理信息的方式就像“囫囵吞枣”。无论是机器翻译还是文本理解,模型都试图把整个输入压缩成一个固定长度的向量,仿佛要求一个人仅凭“第一印象”就记住整本小说。结果可想而知:句子稍长,模型就遗忘了开头;信息稍多,关键细节便淹没在噪声中。
直到注意力机制(Attention Mechanism)的出现,彻底改变了这一切。
它的灵感正来源于我们自身的视觉和认知系统。注意力机制让模型不再一视同仁地对待所有数据,而是学会动态地分配“关注度”——对重要的信息投入更多权重,对次要的信息则适度忽略。这就像给深度学习模型安装了一盏智能探照灯,告诉它:“看这里,这才是重点。”
而这一切魔法,由三个环环相扣的核心步骤构成:线性变换、归一化与加权求和。
线性变换,是信息的“角色扮演”。它将原始数据映射到不同的语义空间,让模型能够从不同角度“审视”信息。
归一化,是注意力的“决策天平”。它将原始分数转化为清晰的概率分布,回答“谁更重要,重要多少”的问题。
加权求和,则是信息的“整合提炼”。它根据决策结果,将分散的信息聚合成一个富含上下文的新表示。
正是这套精巧的设计,催生了席卷全球的Transformer架构,也孕育了你所熟知的BERT、GPT等大语言模型。可以说,没有注意力机制,就没有人工智能的今天。
在接下来的内容中,我们将一同拆解这三个步骤,看看这场改变AI世界的“注意力革命”,究竟是如何发生的。
首先我们引入一个完整注意力机制流程,再清晰一下每个环节的概念,让我们用翻译"我爱AI"→"I love AI"为例:
第1层:输入编码
输入词向量:[我:0.3, 爱:0.5, AI:0.2]第2层:生成Q、K、V(线性变换)
Q = [0.3, 0.5, 0.2] × Wᑫ = [查询向量]
K = [0.3, 0.5, 0.2] × Wᴷ = [键向量]
V = [0.3, 0.5, 0.2] × Wⱽ = [值向量]第3层:计算注意力
计算"爱"这个词的注意力:
原始分数 = Q_爱 · [K_我, K_爱, K_AI]
= [0.8, 2.1, 1.3]
# 假设值
权重 = softmax([0.8, 2.1, 1.3]/√d)
= softmax([0.5, 1.31, 0.81]) # 缩放后
= [0.18, 0.55, 0.27] # 总和=1第4层:加权求和
输出_爱 = 0.18×V_我 + 0.55×V_爱 + 0.27×V_AI
= [新的表示向量]第5层:多头整合(如果有多个头)
最终输出 = [头1_输出, 头2_输出, ...] × W_0四、各类注意力机制的具体差异
MHA(多头注意力):
# 每个头独立变换
头1_Q = 输入 × Wᑫ¹
头1_K = 输入 × Wᴷ¹
头1_V = 输入 × Wⱽ¹
头2_Q = 输入 × Wᑫ²
头2_K = 输入 × Wᴷ²
头2_V = 输入 × Wⱽ²
# ... 共h个头
最终输出 = Concat(头1, 头2, ..., 头h) × WᵒMQA(多查询注意力):
# 多个Q,共享K和V
头1_Q = 输入 × Wᑫ¹
头2_Q = 输入 × Wᑫ²
...
头h_Q = 输入 × Wᑫʰ
# 共享的K和V
共享_K = 输入 × Wᴷ
共享_V = 输入 × Wⱽ
# 每个头使用相同的K和V
头1_输出 = softmax(头1_Q × 共享_Kᵀ) × 共享_V
头2_输出 = softmax(头2_Q × 共享_Kᵀ) × 共享_V
...
最终输出 = Concat(头1, 头2, ..., 头h) × WᵒGQA(分组查询注意力):
# 假设4个查询头,2个KV组(g=2)
头1_Q = 输入 × Wᑫ¹
# 属于组1
头2_Q = 输入 × Wᑫ²
# 属于组1
头3_Q = 输入 × Wᑫ³
# 属于组2
头4_Q = 输入 × Wᑫ⁴
# 属于组2
# 组1的KV
组1_K = 输入 × Wᴷ¹
组1_V = 输入 × Wⱽ¹
# 组2的KV
组2_K = 输入 × Wᴷ²
组2_V = 输入 × Wⱽ²
# 计算(头1、头2用组1的KV,头3、头4用组2的KV)
头1_输出 = softmax(头1_Q × 组1_Kᵀ) × 组1_V
头2_输出 = softmax(头2_Q × 组1_Kᵀ) × 组1_V
头3_输出 = softmax(头3_Q × 组2_Kᵀ) × 组2_V
头4_输出 = softmax(头4_Q × 组2_Kᵀ) × 组2_V
最终输出 = Concat(头1, 头2, 头3, 头4) × W_001、线性变换的作用
我来详细解释这个关键步骤,注意力的完整计算流程,先看完整公式:
注意力权重输出 = softmax(QKᵀ/√d) · V
让我们分解每一步:
步骤1:计算原始分数
原始分数 = Q × Kᵀ / √d
QKᵀ:每个查询和所有键的点积
√d:缩放因子,防止softmax梯度消失步骤2:归一化为权重(使用softmax)
注意力权重 = softmax(原始分数)
softmax做了什么?
# 简单示例:将[2, 4, 6]转换为概率分布
def softmax(x):
exp_x = np.exp(x)
return exp_x / np.sum(exp_x)
# 输入:原始分数 [2, 4, 6]
# 输出:归一化权重 [0.015, 0.117, 0.868]
# 总和为1,形成了概率分布softmax的关键作用:
1.归一化:确保所有权重之和为1
2.突出主要:通过指数放大最大值
3.可微:方便反向传播
步骤3:加权求和得到输出
输出 = 注意力权重 × V
在单头注意力机制中这就是简单的矩阵乘法,没有额外变换,但在多头注意力中需要在输出处进行"线性变换"。线性变换主要发生点有两种情况:
情况1:最终的输出投影(多头注意力中)
最终输出 = Concat(头1, 头2, ..., 头n) × W_0
这里的W_0是一个线性变换矩阵,相当于把多个专家的结论整合成最终报告反馈给用户。
具体流程:
1.每个头计算自己的注意力:头i = softmax(QᵢKᵢᵀ/√d) · Vᵢ
2.将所有头的输出拼接:拼接输出 = [头1, 头2, ..., 头n]
3.线性变换:最终输出 = 拼接输出 × W_0
W_0是一个可学习的参数矩阵,是由模型训练期间根据维度特征进行动态变换,其维度为(n×d_v) × d_model。
情况2:生成Q、K、V的线性变换
在注意力计算之前,计算QKV时会发生线性变换。
Q = 输入 × Wᑫ
K = 输入 × Wᴷ
V = 输入 × Wⱽ这里的Wᑫ、Wᴷ、Wⱽ都是线性变换矩阵。那不做线性转换不行吗,直接用序列向量为什么不可以?
简单直接地回答:如果直接用原始序列(即原始的词向量)来计算注意力,模型会变成"自己跟自己比较",能力会非常受限。
下面从三个核心层面,深入解释为什么必须要有线性变换:
1. 打破"对称性":让模型分清"角色"
如果不做线性变换,直接使用原始的输入向量 ( X ) 来同时扮演查询、键和值,那么数学上就变成了:
Query = ( X )
Key = ( X )
Value = ( X )这时,计算Query和Key的匹配度,本质上就是计算( X ) 自己和自己的点积。
这会导致两个严重问题:
线性变换的作用:通过三个不同的权重矩阵(( W^Q, W^K, W^V )),将原始输入 ( X ) 投影到三个不同的向量空间。这就好比给同一个原始信息穿上了不同的马甲,让它们能够各司其职。
原始序列(比如词向量)通常是固定的,或者是通过浅层网络初步生成的。如果直接用原始序列做计算,模型能调整的参数就很少。
线性变换引入了可学习的参数矩阵(即 ( W^Q, W^K, W^V ))对比二者如下:
线性变换的本质,是给神经网络提供了"调参"的空间,让它能根据任务需求,动态地决定从哪个角度去计算注意力。 如果任务需要关注语义,矩阵就学会捕捉语义;如果任务需要关注词性,矩阵就学会捕捉词性。
线性变换不仅仅是复制,它通常还伴随着维度变化。
在标准的Transformer(如BERT、GPT)中,通常会对维度进行压缩或扩展(比如输入是512维,通过变换变成64维的Q/K,再变回512维的V,这是因为神经网络的层数和神经元的数量不同导致)。
为了更直观地理解,可以看这个对比:

所以,"直接用序列不行"的根本原因在于:如果不经过线性变换,注意力机制就退化成了"固定的、静态的"模式匹配,失去了神经网络最宝贵的"可学习"和"自适应"的能力。
02、归一化的作用
归一化就是将多个注意力权重转化成和为1的概率分布,同时这也是softmax激活函数的作用:将注意力分数(一个向量)转换为一个概率分布(即权重,各元素非负且和为1)。所以,softmax是用来得到权重的,并且这个过程就是归一化。
为什么要归一化?不归一化不是也有注意力权重嘛?不是也能够知道哪些更相近嘛?
原始分数确实能反映相似度。比如点积结果10比1大,模型确实"知道"这两个更相近。但问题在于:注意力机制最终要做的是"资源的分配",而不是"相似度的展示"。
打个比方:你知道A比B重要(原始分数能告诉你),但你得决定给A拨80%的预算,还是40%的预算(这才是注意力权重的作用)。不归一化,你只有排序,没有预算。
具体来说,如果不做归一化(Softmax),直接用原始分数加权求和,会面临三个致命问题:
假设有一个句子,计算出的注意力分数是 [100, 90, 10];另一个句子,分数是 [0.1, 0.09, 0.01]。
归一化的作用:不管输入的分数是 [100, 90, 10] 还是 [0.1, 0.09, 0.01],经过Softmax归一化后,都会变成类似 [0.5, 0.4, 0.1] 这样分布清晰的概率。它把分数拉到了一个稳定、可控的尺度(0到1之间)上,让神经网络的训练更稳定。
如果不归一化,你只知道10比1大。但归一化(Softmax)带来的不仅仅是压缩数值,它还引入了竞争机制——因为所有权重加起来必须等于1。
[10, 9, 1]。模型会同等程度地关注前两个(10和9)。[0.5, 0.45, 0.05]。模型被迫做出选择:把最多的资源分配给第一个,第二个少一点,第三个几乎忽略。这种"总和为1"的约束,迫使模型拉开差距,进行软性选择。它不仅仅是告诉你谁相近,而是在资源有限的前提下(权重总和=1),帮你决定如何取舍。这才是注意力中"注意"二字的精髓——集中资源关注重点。
如果不归一化,假设某个词和自己做点积,算出来的分数极大(比如100),其他词都是1。直接加权求和时,输出几乎完全等于这个词本身的值,其他词的信息完全丢失了,这类似于梯度消失了。
Softmax归一化中带有一个温度调节的作用。虽然原始分数差异很大,但通过指数运算和除法,它依然能保留一定的平滑度(除非温度极低),让模型在关注主要目标的同时,依然能给次要目标分配一点点权重,从而保留了微小的梯度信号,让模型可以持续优化。
假设你在做阅读理解,问:"主人公叫什么名字?"
上下文里有三个词:[张三](相关)、[李四](不太相关)、[桌子](无关)。
[20, 5, 1]。20*张三 + 5*李四 + 1*桌子。这个结果里混合了大量李四和桌子的信息,导致最终向量不再是纯粹的"张三"。[20,5,1]) 约等于 [0.999, 0.001, 0.000]。加权求和的结果是 0.999*张三 + 0.001*李四 + 0*桌子,几乎完美地提取出了正确答案"张三"。不归一化,你确实能得到一组表示"相近程度"的数值,但这组数值不能直接作为权重使用:
归一化的本质,是把"相似度分数"转换成"概率分布"。只有概率分布,才能名正言顺地用于"加权求和",因为它确保了权重的可解释性(重要性占比)和数学上的稳定性。
03、加权求和原理
为什么需要加权求和?
因为我们需要从所有的信息(值V)中,根据重要性(权重)提取出当前最需要的信息。
想象你在撰写一篇关于“深度学习”的论文综述。
步骤:
为什么不直接取最相关的一篇文献? 因为单篇文献可能不全面,加权求和可以融合多篇文献的信息,得到更全面、更平衡的内容。
为什么不直接拼接所有文献? 因为那样会包含大量无关信息,让重点不突出。加权求和可以强调重要信息,弱化无关信息。
为什么不是其他操作(如拼接、最大值)?
在信号处理中,加权求和相当于一个滤波器。
通过调整权重,我们可以让某些信号通过(重要信息),同时抑制其他信号(无关信息)。
值V中的每一个向量都位于高维空间中。加权求和实际上是在这个空间中,根据权重组合出新的向量。
几何意义:新向量是原始向量组的加权平均点,但这个平均点可以偏向于权重大的向量。
例如,在句子“猫在垫子上睡觉”中:
[猫, 在, 垫子, 上, 睡觉][0.8, 0.05, 0.1, 0.02, 0.03]这样,新向量既聚焦于“猫”,又保留了上下文信息。
加权求和的原因可以归结为以下几点:
这就是注意力机制使用加权求和的根本原因:它创造了一种灵活的、可学习的、信息丰富的信息融合方式,这种设计使得注意力机制既能够聚焦于重要信息,又不会完全丢弃其他信息,从而在多项任务中取得了优异的表现。这是深度学习中许多突破性进展的关键所在。

