Transformer注意力机制的核心是让序列中的每个位置都能直接关注其他所有位置,通过动态计算相关性权重来聚合信息,从而高效捕捉长距离依赖。
🧠 直观理解:什么是注意力?
传统RNN处理序列时,信息必须一步步传递(从第一个词到最后一个词),这导致长距离依赖很难捕捉。
注意力机制的核心思想是:让序列中的每个位置都能"看到"其他所有位置,并根据相关性动态分配权重。
打个比方:你在读一句话时,理解某个词的含义会同时参考句中的其他词,而且对不同词的"关注度"不同。注意力机制就是让模型学会这种"关注分配"的能力。
📐 核心公式:Scaled Dot-Product Attention
注意力机制的数学表达为:
其中涉及三个关键向量:
- Q(Query,查询):当前词"想要查找什么信息"
- K(Key,键):每个词"能被查到的标签"
- V(Value,值):每个词"实际携带的信息内容"
🔀 多头注意力(Multi-Head Attention)
单一注意力只能学到一种"关注模式"。多头注意力将Q、K、V分别投影到多个不同的子空间,让模型同时从不同角度关注信息:
其中每个头:
直觉理解:就像多个"审查员"同时审阅同一句话,有人关注语法结构,有人关注语义关系,有人关注位置关系,最后把各自的发现综合起来。
🎭 掩码机制(Masking)
Transformer中有两种掩码:
- Padding Mask:忽略填充token(如
[PAD]),不让它们参与注意力计算。 - Causal Mask(因果掩码):在解码器中使用,确保位置 i 只能关注位置 ≤i 的信息,防止"看到未来"。实现方式是在softmax之前,将未来位置的分数设为 −∞ 。
🏗️ 在Transformer中的位置
Transformer整体架构中,注意力机制出现在两个地方:
- 编码器(Encoder)中的自注意力(Self-Attention):每个位置关注序列中的所有位置(双向)。
- 解码器(Decoder)中:
- 掩码自注意力:只关注已生成的部分(单向)。
- 交叉注意力(Cross-Attention):Query来自解码器,Key和Value来自编码器的输出,实现编码器到解码器的信息传递。
💻 简化代码实现(PyTorch风格)
python
import torch import torch.nn.functional as F import math def scaled_dot_product_attention(Q, K, V, mask=None): d_k = Q.size(-1) # 1. 计算相似度并缩放 scores = torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(d_k) # 2. 应用掩码(如果有) if mask is not None: scores = scores.masked_fill(mask == 0, -1e9) # 3. Softmax归一化 attn_weights = F.softmax(scores, dim=-1) # 4. 加权求和 output = torch.matmul(attn_weights, V) return output, attn_weights📌 总结
| 概念 | 作用 |
|---|---|
| Q, K, V | 分别代表"查询"、"键"、"值",通过线性变换从输入得到 |
| QKT | 计算词与词之间的相关性 |
| dk 缩放 | 防止点积过大导致梯度消失 |
| Softmax | 将相关性转化为注意力权重 |
| 加权V | 根据权重聚合信息 |
| 多头 | 从多个子空间捕捉不同类型的依赖关系 |
| 掩码 | 控制信息的可见性(填充/因果) |
注意力机制之所以强大,是因为它不依赖序列顺序,能并行计算,且能直接建模任意两个位置之间的关系,这正是Transformer超越RNN的关键所在。