当前位置: 首页 > news >正文

NLP学习笔记09:注意力机制——从 Self-Attention 到 Transformer

NLP学习笔记09:注意力机制——从 Self-Attention 到 Transformer

作者:Ye Shun
日期:2026-04-18

一、前言

注意力机制(Attention Mechanism)是现代深度学习,尤其是自然语言处理中的核心技术之一。它的灵感来自人类的认知过程:当我们阅读一句话时,并不会平均地处理每一个词,而是会把更多注意力放在当前最相关的部分。

例如在阅读句子:

猫坐在垫子上,因为它很舒服。

理解“它”指代什么时,人不会机械地平均看待所有词,而会自动把注意力集中到与“它”最相关的候选对象上。注意力机制希望让模型也具备这种“动态聚焦”的能力。

它的核心思想可以概括为一句话:

根据输入中不同部分对当前任务的重要性,动态分配不同权重。

这套思想已经成为 Transformer、BERT、GPT、T5 等模型的基础。理解注意力机制,几乎就是理解现代 NLP 的关键起点。

这篇笔记将围绕以下几个问题展开:

  1. 注意力机制到底在解决什么问题
  2. Query、Key、Value 分别是什么意思
  3. 自注意力和多头注意力是怎么工作的
  4. 注意力机制为什么能推动 Transformer 崛起
  5. 实践中如何实现和可视化注意力

二、为什么需要注意力机制

在注意力机制出现之前,处理序列数据的主力模型主要是 RNN、LSTM 和 GRU。它们虽然能处理上下文,但存在一些明显局限。

1. 长距离依赖难题

在长序列中,前后信息相距很远时,RNN 系列模型往往难以稳定捕捉这种依赖。即便 LSTM 和 GRU 已经缓解了问题,也并没有彻底解决。

2. 顺序计算限制

RNN 在时间步之间存在强依赖,因此很难像普通矩阵运算那样充分并行。训练长序列时,效率容易受到影响。

3. 信息压缩瓶颈

在早期 Seq2Seq 模型中,编码器通常需要把整个源句压缩成一个固定长度向量,再交给解码器。这个单一向量很容易丢失细节,尤其是在长句子上。

4. 注意力给出的改进思路

注意力机制的关键改进是:

  • 不要求把所有信息压缩成一个固定向量
  • 在每一步都能动态查看输入中的不同位置
  • 根据当前任务重点重新分配权重

也就是说,模型在做决策时,不再只依赖“一个总摘要”,而是可以“回头查看原文中最相关的部分”。

三、注意力机制的基本概念

注意力机制最经典的数学形式是:

Attention(Q, K, V) = softmax(QK^T / √d_k) V

这是缩放点积注意力(Scaled Dot-Product Attention)的表达式。

1. Q、K、V 分别是什么

这三个量可以理解为:

  • Q(Query):当前要查询什么
  • K(Key):每个位置提供的“索引”或“匹配依据”
  • V(Value):每个位置真正携带的信息

可以把它类比成数据库检索:

  • Query 是检索请求
  • Key 是检索键
  • Value 是对应的数据内容

模型会先用Q和所有K做匹配,算出“当前应该关注谁”;再用这些权重对所有V加权求和,得到最终输出。

2. 为什么要除以√d_k

如果向量维度很大,QK^T的点积值容易变得很大,导致softmax之后分布过于尖锐,训练不稳定。

所以引入缩放项√d_k,让数值范围更平衡,梯度更稳定。

3. softmax 的作用

softmax会把匹配分数转换成一组和为 1 的权重,表示模型对不同位置的关注比例。

这就意味着:

  • 权重越大,说明模型越关注那个位置
  • 权重越小,说明那个位置对当前计算贡献较少

四、自注意力机制(Self-Attention)

自注意力(Self-Attention)是注意力机制中最关键的一种形式。它的特点是:

序列中的每个位置,都可以和序列中的所有其他位置建立联系。

也就是说,在自注意力中:

  • Query 来自输入序列本身
  • Key 来自输入序列本身
  • Value 也来自输入序列本身

1. 工作流程

对于一个输入序列中的某个位置,自注意力通常按以下步骤工作:

  1. 计算当前词和所有词之间的相关性分数
  2. 对分数做 softmax,得到注意力权重
  3. 用这些权重对所有 Value 做加权求和
  4. 得到当前词新的上下文表示

2. 一个简化示例

importtorchimporttorch.nn.functionalasFdefself_attention(query,key,value):scores=torch.matmul(query,key.transpose(-2,-1))/(query.size(-1)**0.5)weights=F.softmax(scores,dim=-1)returntorch.matmul(weights,value)

3. 自注意力的优势

全局上下文感知

每个位置都能直接访问整个序列中的所有位置,而不像 RNN 那样必须逐步传递信息。

更适合并行计算

自注意力可以把一个序列中所有位置的相关性计算写成矩阵乘法,因此更适合现代 GPU 并行计算。

需要特别说明的是:

  • 它“更容易并行”
  • 但不代表它在序列长度上的复杂度更低

标准自注意力在序列长度为n时,时间和内存开销通常是O(n^2)。这是它和 RNN 很不一样、也很重要的一个点。

更强的长距离建模能力

两个相距很远的词之间,也可以通过一次注意力计算直接建立联系,而不需要跨越很多时间步传递。

4. 自注意力的一个限制

自注意力本身并不天然编码位置信息。换句话说,如果不额外加入位置编码,它并不知道“哪个词在前,哪个词在后”。

所以在 Transformer 中,自注意力通常要配合位置编码(Positional Encoding)一起使用。

五、多头注意力(Multi-Head Attention)

单头注意力虽然已经很强,但模型在一次注意力计算中,可能只学到某一种关系模式。多头注意力(Multi-Head Attention)就是为了解决这个问题。

它的核心思想是:

把注意力机制并行做很多次,让不同的头去关注不同类型的关系。

1. 多头注意力的结构

多头注意力通常包括:

  • 多组独立的QKV线性变换
  • 多个并行注意力头
  • 拼接多个头的输出
  • 再通过一个线性层映射回原维度

2. 为什么多头更强

不同注意力头可能学习到不同模式,例如:

  • 一个头关注主谓关系
  • 一个头关注长距离依赖
  • 一个头关注局部词组搭配
  • 一个头关注指代消解

这会显著增强模型的表达能力。

3. 多头注意力示例

importtorchimporttorch.nnasnnimporttorch.nn.functionalasFclassMultiHeadAttention(nn.Module):def__init__(self,d_model,num_heads):super().__init__()self.d_model=d_model self.num_heads=num_heads self.d_k=d_model//num_heads self.W_q=nn.Linear(d_model,d_model)self.W_k=nn.Linear(d_model,d_model)self.W_v=nn.Linear(d_model,d_model)self.W_o=nn.Linear(d_model,d_model)defforward(self,query,key,value):batch_size=query.size(0)Q=self.W_q(query).view(batch_size,-1,self.num_heads,self.d_k).transpose(1,2)K=self.W_k(key).view(batch_size,-1,self.num_heads,self.d_k).transpose(1,2)V=self.W_v(value).view(batch_size,-1,self.num_heads,self.d_k).transpose(1,2)scores=torch.matmul(Q,K.transpose(-2,-1))/(self.d_k**0.5)weights=F.softmax(scores,dim=-1)output=torch.matmul(weights,V)output=output.transpose(1,2).contiguous().view(batch_size,-1,self.d_model)returnself.W_o(output)

六、注意力机制在 NLP 中的应用

注意力机制已经成为现代 NLP 系统的核心组件,尤其在 Transformer 架构中几乎无处不在。

1. 机器翻译

在经典的 Seq2Seq with Attention 中,解码器在生成每个目标词时,不再只依赖固定长度的编码向量,而是动态关注源句中最相关的部分。

这显著改善了长句翻译质量。

2. 文本摘要

摘要模型需要识别原文中的关键信息。注意力机制可以帮助模型聚焦核心句子或核心片段,提高摘要生成质量。

3. 问答系统

问答任务中,经常需要计算“问题”和“文档”之间的对应关系。交叉注意力(Cross-Attention)可以帮助模型找到最相关的证据片段。

4. 语言模型

GPT 系列模型使用掩码自注意力(Masked Self-Attention),保证每个位置只能看到它前面的内容,从而实现自回归生成。

5. 表示学习模型

BERT 使用双向自注意力,可以同时利用左右上下文,因此在文本理解任务中表现非常强。

七、BERT 中的注意力

BERT 是注意力机制应用得最典型的模型之一。它本质上是由多层 Transformer Encoder 堆叠而成。

1. BERT 的关键特点

  • 使用双向自注意力
  • 每层都有多头注意力
  • 通过多层堆叠不断增强上下文表示

2. 如何获取注意力权重

在 Hugging Face 中,如果想拿到 BERT 的注意力权重,一般要显式设置output_attentions=True

fromtransformersimportBertModel,BertTokenizer tokenizer=BertTokenizer.from_pretrained("bert-base-uncased")model=BertModel.from_pretrained("bert-base-uncased")inputs=tokenizer("Hello, my dog is cute",return_tensors="pt")outputs=model(**inputs,output_attentions=True)attention=outputs.attentions

这样outputs.attentions中才会包含各层、各头的注意力权重。

八、注意力机制的常见变体

随着序列越来越长、任务越来越复杂,研究者提出了很多注意力机制的变体。

1. 缩放点积注意力

这是 Transformer 中最经典的版本:

  • 使用点积计算相似度
  • √d_k缩放
  • 计算效率高

2. 加法注意力(Additive Attention)

这是更早期的一种注意力形式,常见于 Bahdanau Attention。它通过一个小型前馈网络来计算 Query 和 Key 的兼容性。

相比点积注意力:

  • 计算更灵活
  • 在低维场景下有时更稳定
  • 但效率通常不如点积注意力

3. 局部注意力(Local Attention)

局部注意力只关注输入的一部分,而不是整段序列。这样可以显著减少计算成本。

4. 稀疏注意力(Sparse Attention)

稀疏注意力不会让每个位置都和所有位置建立连接,而是只计算部分位置之间的注意力。例如 Longformer 中的滑动窗口注意力。

这类方法的目标都是一样的:

在尽量保留建模能力的同时,降低标准自注意力的二次复杂度开销。

九、实践练习建议

练习1:实现基础注意力机制

可以先写一个最简单的 attention 模块,输入一组隐藏状态,输出上下文向量和注意力权重:

importtorchimporttorch.nnasnnimporttorch.nn.functionalasFclassSimpleAttention(nn.Module):def__init__(self,hidden_size):super().__init__()self.attention=nn.Linear(hidden_size,1)defforward(self,encoder_outputs):attention_scores=self.attention(encoder_outputs).squeeze(2)attention_weights=F.softmax(attention_scores,dim=1)context_vector=torch.bmm(attention_weights.unsqueeze(1),encoder_outputs)returncontext_vector.squeeze(1),attention_weights

这个练习很适合帮助理解:

  • 注意力分数是怎么来的
  • 权重是如何归一化的
  • 上下文向量是如何加权求和得到的

练习2:可视化注意力权重

如果把注意力权重画成热力图,会更直观地看到模型到底在关注什么。

importmatplotlib.pyplotaspltimportseabornassnsdefplot_attention(attention_weights,source_tokens,target_tokens):plt.figure(figsize=(10,8))sns.heatmap(attention_weights,xticklabels=source_tokens,yticklabels=target_tokens,cmap="YlGnBu")plt.xlabel("Source Tokens")plt.ylabel("Target Tokens")plt.title("Attention Weights Visualization")plt.show()

这个练习对理解机器翻译和 Transformer 非常有帮助。

十、学习建议

如果你想真正把注意力机制学透,我建议按下面的顺序来:

  1. 先理解最基本的加权求和思想
  2. 再理解 Query、Key、Value 的角色分工
  3. 然后理解自注意力和多头注意力
  4. 接着理解注意力如何进入 Transformer
  5. 最后再去看 BERT、GPT、T5 等大模型

这样更容易把“公式、结构和应用”串起来。

十一、总结

注意力机制的本质,是让模型在处理输入时,不必平均看待所有信息,而是能够根据当前任务动态聚焦最相关的部分。

从方法角度看:

  • 注意力机制解决了固定向量瓶颈问题
  • 自注意力让序列中任意位置都能直接交互
  • 多头注意力让模型可以并行学习多种关系模式

从应用角度看:

  • 它推动了机器翻译、问答、摘要、语言模型等任务的发展
  • 它也是 Transformer、BERT、GPT 等现代模型的核心基础

理解注意力机制之后,再去看 Transformer,就会更容易明白为什么现代 NLP 会从 RNN 时代走向自注意力时代。

http://www.jsqmd.com/news/663878/

相关文章:

  • JavaScript中的void操作符详解
  • 终极解决方案:PS3游戏更新下载器让怀旧游戏重获新生 [特殊字符]
  • NLP学习笔记10:Transformer 架构——从编码器、解码器到自注意力
  • 别再手动调参了!用OpenBayes一键部署Depth-Anything-3,5分钟搞定你的3D视觉项目
  • AI智能体开发核心概念全解析
  • AGI研发已无“安全窗口期”:从GPT-5延迟到中国“伏羲计划”提速,90天内5国密集调整国家级AGI战略(附原始政策文本对照表)
  • 从零到精通:使用stress-ng对Linux系统进行全方位压力测试
  • 从按下电源到看到Logo:一文拆解Android手机开机背后的BootLoader与Linux内核启动全流程
  • 揭秘AI编程时代代码资源失控真相:如何用动态血缘追踪+智能配额引擎实现零泄漏管理?
  • 秒杀系统整体架构怎么设计?一次讲清限流、削峰、库存、幂等与高并发链路
  • 星空图床系统1.1.0源码 在线图床 图床外链
  • UnrealPakViewer完全指南:3步掌握UE4 Pak文件分析的终极技巧
  • 2026年靠谱的庭院景观灯/新中式景观灯厂家对比推荐 - 品牌宣传支持者
  • 超越官方SDK:用Python直接读取Myo蓝牙数据,实现双臂环同步采集
  • Unity 2019+打包APK卡在Building Gradle?试试这招替换阿里云镜像,5分钟搞定
  • Python3 字符串
  • 【限时开源】我们刚发布的DepGuard v2.0:首个支持TypeScript/Python/Rust三语种的AI生成代码依赖审计工具(仅开放前500个企业License)
  • 提示工程(Prompt Engineering)完整指南:从原子结构到工业级实践——AI智能体开发实战
  • 新版精美UI界面FileCodeBox快递柜源码 附带搭建教程
  • 嵌入式系统调试接口安全防护与最佳实践
  • c++怎么快速生成一个包含随机数据的1GB大型测试文件【实战】
  • 智能代码生成与代码自愈结合(工业级自修复系统设计白皮书)
  • OpenMemories-Tweak:索尼相机隐藏功能深度解锁终极指南
  • 黎阳之光:全域实景立体管控,重构智慧电厂与变电站数字孪生新范式
  • Intel Realsense D435图像采集实战:用C接口和OpenCV imshow的正确姿势(解决颜色反色问题)
  • 鸿蒙游戏,会不会重演微信小游戏的爆发?
  • 你还在用Copilot式单点辅助?SITS2026已实现“全栈感知生成”:从Service Mesh配置→CRD定义→Argo CD Manifest全自动推演(附生成可信度量化评估矩阵V1.3)
  • Windows风扇智能控制终极指南:5分钟打造个性化散热方案
  • jEasyUI 合并单元格详解
  • 别再乱点‘是’了!Windows UAC这10个组策略设置,你真的都懂吗?