注意力机制的核心是动态加权求和,三要素为Query(查询)、Key(键)、Value(值):Query与Key计算相似度得分数,softmax归一化为权重,再加权求和Value得到输出;自注意力通过全连接匹配突破距离限制,多头机制并行捕获多维特征;PyTorch手写实现含线性投影、缩放点积、softmax及加权求和;可视化注意力权重热力图可分析模型关注模式。

注意力机制不是让模型“看哪里”,而是让模型在处理信息时,动态分配不同权重——哪些词、哪些位置、哪些特征更关键,就给它更高权重。核心在于“加权求和”+“可学习的权重计算”。
注意力三要素:Query、Key、Value 是什么?
这是理解所有注意力变体的起点:
- Query(查询):当前正在处理的单元(比如解码器中第t个时间步的隐藏状态),它在“问”:我该关注输入里的哪些部分?
- Key(键):每个输入单元(如编码器每个时间步的输出)的“标签”,用于和 Query 匹配打分。
- Value(值):每个输入单元真正携带的信息内容,最终被加权聚合的结果。
简单说:Query 和 Key 算相似度 → 得到注意力分数(attention scores)→ 归一化成权重(softmax)→ 加权求和 Value → 输出上下文向量。这个过程可微、可训练。
自注意力(Self-Attention)为什么能捕获长程依赖?
传统RNN/LSTM靠逐步传递隐藏状态,距离越远信号越弱;CNN靠局部感受野,需多层堆叠才能覆盖全局。而自注意力一步到位:
立即学习“Python免费学习笔记(深入)”;
- 序列中任意两个位置可以直接计算 Query-Key 分数,不受距离限制;
- 同一词在不同语境下获得不同权重(例如“bank”在“river bank”和“bank account”中关注的上下文完全不同);
- 多个注意力头(Multi-Head)并行计算,让模型能同时关注语法、指代、情感等不同维度。
这也是 Transformer 能替代 RNN 成为大模型基座的关键原因。
如何用 PyTorch 手写一个基础注意力层?
不依赖 nn.MultiheadAttention,从零实现有助于理解每一步的张量形状和计算逻辑:
import torch import torch.nn as nn import torch.nn.functional as Fclass SimpleAttention(nn.Module): def init(self, dim): super().init() self.W_q = nn.Linear(dim, dim) self.W_k = nn.Linear(dim, dim) self.W_v = nn.Linear(dim, dim)
def forward(self, x): # x: [batch, seq_len, dim] Q = self.W_q(x) # [b, s, d] K = self.W_k(x) # [b, s, d] V = self.W_v(x) # [b, s, d] # 计算相似度(缩放点积) scores = torch.bmm(Q, K.transpose(1, 2)) / (K.size(-1) ** 0.5) # [b, s, s] attn_weights = F.softmax(scores, dim=-1) # 每行和为1 output = torch.bmm(attn_weights, V) # [b, s, d] return output, attn_weights
注意:实际训练中通常会加入 dropout、LayerNorm 和残差连接,构成一个完整的 Attention Block。
怎么可视化注意力权重,看出模型到底在“看”什么?
训练完模型后,提取某次前向传播中的 attention_weights(形状为 [batch, heads, seq_len, seq_len]),可做如下分析:
- 对单句输入,取第一个样本、第一个头,画热力图(heatmap):横轴是 Query 位置(当前词),纵轴是 Key 位置(被关注词),颜色越深表示权重越高;
- 观察代词(如“he”, “it”)是否高亮指向其先行词;
- 检查动词是否聚焦于主语/宾语,而非停用词(“the”, “a”);
- 使用库如
matplotlib.pyplot.imshow或seaborn.heatmap快速出图,配合xticks/yticks标注词元。
这不仅是调试工具,更是验证模型是否学到合理语言结构的直接证据。









