深入浅出 Self-Attention:原理 + 例子 + PyTorch 实现

发布于:2025-04-18 ⋅ 阅读:(25) ⋅ 点赞:(0)

Transformer 的核心机制就是 Self-Attention,它赋予模型强大的“理解上下文”能力。本文从零开始,详细解析 Self-Attention 的原理、Q/K/V 向量的含义、举例说明并用 PyTorch 代码实现,助你彻底搞懂这项技术!


 什么是 Self-Attention?

Self-Attention(自注意力)是一种机制,它让模型在处理某个词时,能够“感知”到句子中其它词,并根据它们的重要程度加权组合信息。

在传统的 RNN 中,信息只能通过固定顺序传播;而在 Transformer 中,Self-Attention 允许每个词同时访问整个序列,从而极大提升模型的表现力与并行性。


 Q / K / V 是什么?(关键点)

在 Self-Attention 中,每个词的向量表示会被映射为 3 个不同的向量:

  • Query(Q):我想找什么内容?

  • Key(K):你提供了哪些“关键词”?

  • Value(V):你具体包含了哪些信息?

类比解释:

想象你在搜索文档内容:

  • 你有一个查找目标(Query)

  • 每篇文章有它的关键词标签(Key)

  • 每篇文章本身的内容就是 Value

你计算目标和标签(Q 和 K)之间的匹配程度(比如用点积),然后根据匹配度加权文章内容(V)来生成你最终关注的结果。

数学表达:

输入词向量:
假设每个词的维度是 d_model = 512,我们会训练三个参数矩阵:

  • WQ ∈ ℝ512×64

  • WK ∈ ℝ512×64

  • WV ∈ ℝ512×64

每个词向量 X(shape 为 [batch, seq_len, d_model]) 乘以这三个矩阵得到:

Q = X @ W_Q
K = X @ W_K
V = X @ W_V

生成的 Q、K、V 都是 [batch, seq_len, d_k] 维度。

当然可以!下面是一篇面向开发者社区(比如 CSDN、知乎、掘金、微信公众号)的技术文章草稿,清晰介绍 Self-Attention 原理 + 例子讲解,适合发布在论坛或博客平台上:


Self-Attention 原理

Self-Attention 的计算过程大致分为以下几步:

1. 输入表示(嵌入向量)

假设我们有一句话:"The cat sat",它被转成 embedding 向量后,shape 是 [seq_len, d_model]。假设每个词的向量为 4 维:

The: [1, 0, 1, 0]
cat: [0, 2, 0, 2]
sat: [1, 1, 1, 1]

2. 生成 Q / K / V 向量

我们定义三个训练得到的权重矩阵:WQ、WK、WV(常设为 4×2,输出向量维度为 2):

W_Q = [[1, 0],
       [0, 1],
       [1, 0],
       [0, 1]]

然后用它们乘以嵌入向量,生成每个 token 的 Query、Key、Value 向量:

Q = X @ W_Q
K = X @ W_K
V = X @ W_V

3. 计算打分矩阵

通过 Q × K^T 得到每个 token 对其它 token 的相关性打分(注意力权重前的 raw score):

scores = Q @ K.transpose(-2, -1)  # shape: [seq_len, seq_len]

这一步的输出 shape 是 [seq_len, seq_len],表示每个词和其它词之间的关系强弱。

4. softmax 归一化

为了得到每个词应该“关注”其它词的程度,我们对每一行做 softmax:

p_attn = softmax(scores, dim=-1)

它的结果是一个概率分布,越大的表示当前词越关注对应位置的词。

5. 加权求和得到输出

最后我们将 Value 向量按权重加权求和:

output = p_attn @ V

这样就得到了每个词的新表示,它融合了上下文中的相关信息。


举个具体例子(简单演示)

假设有一组 Query、Key 向量如下:

Q = [[1, 0],
     [0, 1],
     [1, 1]]

K = [[1, 0],
     [0, 1],
     [1, 1]]

转置 K 得到:

K^T = [[1, 0, 1],
       [0, 1, 1]]

执行打分:

scores = Q × K^T = [
  [1, 0, 1],  # token 1 对 3 个 token 的打分
  [0, 1, 1],  # token 2
  [1, 1, 2]   # token 3
]

对每一行做 softmax:

softmax([1, 0, 1]) ≈ [0.42, 0.15, 0.42]
softmax([0, 1, 1]) ≈ [0.21, 0.39, 0.39]
softmax([1, 1, 2]) ≈ [0.21, 0.21, 0.58]

最后再用这些权重去加权 Value 向量,得到新的输出。


 PyTorch 实现一把

import torch
import torch.nn.functional as F

# 模拟 batch=2, seq_len=5, dim=64
Q = torch.randn(2, 5, 64)
K = torch.randn(2, 5, 64)
V = torch.randn(2, 5, 64)

# 打分
scores = torch.bmm(Q, K.transpose(1, 2))  # shape: [2, 5, 5]

# softmax 归一化
p_attn = F.softmax(scores, dim=-1)

# 加权求和
output = torch.bmm(p_attn, V)  # shape: [2, 5, 64]

总结

Self-Attention 的关键步骤:

  1. 生成 Q/K/V

  2. 用 Q × Kᵀ 计算相关性打分

  3. 用 softmax 转为注意力分布

  4. 用这个分布去加权 V 得到输出

通过这个机制,模型可以动态调整每个词关注的信息范围,从而更好地理解上下文。


网站公告

今日签到

点亮在社区的每一天
去签到