自注意力怎么计算?

访客 自然语言处理 2

计算原理、公式推导与实战问答

目录导读

  1. 自注意力是什么? —— 从直觉到数学定义
  2. 自注意力的核心计算步骤 —— 三步法拆解
  3. Q、K、V矩阵的生成与意义
  4. 注意力分数的计算:点积与缩放
  5. Softmax归一化与权重分配
  6. 加权求和与输出生成
  7. 自注意力在Transformer中的角色
  8. 常见问答:为什么需要多头?为什么用缩放?
  9. 总结与延伸阅读

自注意力是什么?

问题:
自注意力和普通注意力有什么区别?为什么说它是“自”的?

回答:
自注意力(Self-Attention)让序列中的每一个元素都能关注到序列中其他所有元素,从而捕捉长距离依赖关系,普通注意力通常是“源-目标”之间的交互(如机器翻译中的编码器-解码器注意力),而自注意力是同一个序列内部的注意力,因此叫“自”,它的核心是让每个位置的表示不再是孤立的,而是基于全局上下文重新加权组合。


自注意力的核心计算步骤

自注意力的计算可归纳为 三步(以单头为例):

  1. 生成Q、K、V矩阵
  2. 计算注意力分数(Attention Scores)
  3. 加权求和得到输出

下面逐步骤深入。


Q、K、V矩阵的生成与意义

假设输入序列有 ( n ) 个token,每个token的原始嵌入向量维度为 ( d{\text{model}} )(例如512),那么输入矩阵 ( X ) 的形状为 ( n \times d{\text{model}} )。

自注意力需要三个可训练的参数矩阵:

  • ( WQ )(维度 ( d{\text{model}} \times d_k ))
  • ( WK )(维度 ( d{\text{model}} \times d_k ))
  • ( WV )(维度 ( d{\text{model}} \times d_v ))

计算: [ Q = X W_Q,\quad K = X W_K,\quad V = X W_V ]

  • Q(Query,查询):当前元素“想找谁”的向量表示。
  • K(Key,键):每个元素“我是谁”的标识向量。
  • V(Value,值):每个元素“我有什么信息”的实际内容。

注意:在Transformer原论文中,( d_k = dv = d{\text{model}} / h ),( h ) 是注意力头数。

直观比喻:
Q像是一个人在问“谁与我最相关?”,K像是每个人的名片,V像是每个人实际携带的信息,先通过Q与K的匹配度决定关注程度,再根据V提取内容。


注意力分数的计算:点积与缩放

1 点积注意力分数

对于矩阵 ( Q ) 和 ( K^T ) 进行矩阵乘法: [ \text{score}_{i,j} = Q_i \cdot K_j^T ] 即第 ( i ) 个查询与第 ( j ) 个键的内积,内积越大,表示两个向量越相似,注意力权重越高。

2 为什么需要缩放?

当 ( d_k ) 较大时(( d_k=64,128 )),点积的方差会变大,导致某些得分极大而其他得分极小,Softmax后梯度几乎消失。

解决方案:对点积除以 ( \sqrt{d_k} ),即 [ \text{scaled_score}_{i,j} = \frac{Q_i \cdot K_j^T}{\sqrt{d_k}} ]

问题:
为什么不直接除以 ( d_k ) 而用根号?

回答:
( Q, K ) 每个元素独立且服从均值为0、方差为1的分布,( Q_i \cdot K_j ) 的均值为0、方差为 ( d_k ),除以 ( \sqrt{d_k} ) 使方差变为1,保持数值稳定。


Softmax归一化与权重分配

对每个查询 ( i )(行),对其所有键的分数做Softmax: [ \text{attention_weights}{i,j} = \frac{\exp(\text{scaled_score}{i,j})}{\sum{k=1}^{n} \exp(\text{scaled_score}{i,k})} ]

这使每一行(对应一个token)的权重和为1,代表该token分配给其他token的“关注度”比例。

结果矩阵形状: ( n \times n )(每个token对其他所有token的注意力权重)。


加权求和与输出生成

用注意力权重矩阵乘以 ( V ) 矩阵: [ \text{Output} = \text{AttentionWeights} \times V ]

输出矩阵形状为 ( n \times d_v ),对于第 ( i ) 个位置: [ \text{output}i = \sum{j=1}^{n} \text{weight}_{i,j} \cdot V_j ]

即重新用Value信息加权组合,得到融合了全局上下文的新表示。


自注意力在Transformer中的角色

在Transformer中,自注意力模块是 编码器解码器 的核心组件:

  • 编码器层:每个token都可以看到整个输入序列(包括自己)。
  • 解码器层:使用 掩码自注意力(Masked Self-Attention),只允许看到当前位置及之前的token,防止未来信息泄露。

Transformer会叠加 多头注意力(Multi-Head Attention),即并行计算多组Q、K、V,然后将输出拼接,再通过一个线性层整合。


常见问答

Q1:为什么需要多头注意力而不是单头?
A:单头自注意力可能只关注到一种模式(如语义相似性),多头允许模型在不同子空间中学习不同的关系模式(如语法关系、语义关联、距离依赖等),提高表达能力。

Q2:自注意力的计算复杂度是 ( O(n^2 d) ),对长序列不友好怎么办?
A:对,这是自注意力的主要瓶颈,改进方案包括:稀疏注意力(仅关注局部窗口)、线性注意力(如LinFormer)、Longformer、Reformer等,以及用滑动窗口或哈希方法降低复杂度。

Q3:自注意力可以替代RNN和CNN吗?
A:在序列建模任务中,自注意力已基本替代RNN,因为它能并行计算、捕捉长距离依赖,但CNN在某些局部特征提取场景(如图像)仍有一席之地,不过Transformer在CV领域也已崛起(ViT)。


自注意力的计算本质是一个 可微的、基于内容的寻址机制:通过Q与K的匹配度生成权重,再根据V提取内容,它的成功在于让每个位置能够动态地、全局地整合上下文信息,且计算高度并行化,理解这个流程(生成QKV → 缩放点积 → Softmax → 加权求和)是掌握Transformer一切变体的基石。

延伸阅读建议:

  • 阅读《Attention Is All You Need》原始论文。
  • 动手实现一个简单的自注意力层(如用PyTorch)。
  • 研究多头注意力与位置编码的互动关系。

如果你正在搭建一个需要长文本理解的模型(如文档摘要、代码生成),请务必评估自注意力在序列长度超过2048时的显存消耗,并考虑采用滑动窗口或分段注意力策略,对于大多数中等长度任务(如句子级或段落级),标准自注意力仍然是最佳选择。

标签: K V

抱歉,评论功能暂时关闭!