自注意力机制(Self-attention)
对于输入维度固定的问题,如输入是单个固定长度向量,传统模型(如CNN)可直接处理。

对于输入是多个向量组成的序列,总长度不固定(如自然语言句子、时间序列、点云、机器人传感器数据等),如输入是长度可变的一组向量(序列),传统模型(如CNN)需要强制固定输入尺寸,RNN/LSTM虽然可以处理,但是逐时间步处理,无法并行,长序列梯度消失、长距离依赖难捕捉。

自注意力机制可以解决的核心问题:
- “可变长度输入” 问题:自注意力天然适配长度可变的序列输入,无需强制固定输入长度,灵活适配不同任务。
- “长距离依赖难以捕捉” 问题:自注意力直接计算序列中任意两个位置的相似度(注意力权重),一步到位捕捉全局、长距离的依赖关系,不受序列长度限制。
- “序列计算无法并行” 问题:RNN/LSTM 是时序依赖的,必须按顺序计算每个时间步(必须等前一步完成才能处理下一步),无法利用 GPU 并行加速,训练效率极低。
自注意力可以同时计算所有位置的注意力权重,完全并行化计算,大幅提升训练速度,适配大规模数据训练。
可变长度输入的三种场景:
场景一:自然语言(文本)
对于句子 “
this is a cat”,每个单词对应一个向量,4 个单词组成长度为 4 的向量集合(句子长度可变,因此输入向量集合的长度不固定)。
将单词编码成向量的方法,在文章循环神经网络(RNN)-CSDN博客中我们介绍了One-Hot Encoding和Word Hashing,这里再简单介绍一种深度学习最优的Word Embedding(词嵌入):
- Word Embedding(词嵌入):与Word Hashing人为定义不同,Word Embedding把离散单词映射成 “低维、稠密、可训练、含语义” 的实数向量,靠神经网络反向传播自动学出来,可以让让语义相近的词向量空间距离更近,是 BERT、Transformer 大模型底层输入。其具体过程如下(以 “
This is a cat”为例):
- 原始文本预处理:对原始文本进行去标点、去乱码、分词后得到[This, is, a, cat]
- 建立全局词汇表 Vocabulary:统计所有单词,给每个唯一单词分配一个唯一整数编号(Token ID),假设总词表大小
:
This → 0,is → 1,a → 2,cat → 3,dog → 4- 初始化 Embedding 查找表:人为设定嵌入维度
(超参,常用:64/128/256/768)
新建一个可训练参数矩阵(行数 = 总单词数
,列数 = 词嵌入维度
,初始值则随机高斯 / 均匀分布初始化),例如
:
查表映射过程就是输入单词,然后查找ID,最后取出矩阵对应整行向量。
例如cat ID=3 → 取出第四行[0.055, 0.000, 0.000],这就是该单词初始随机词嵌入- 自监督预训练(让向量学会语义):初始向量是随机乱数,靠训练更新矩阵
,产生语义距离。大模型主流的方式是用 MLM 掩码语言模型,随机盖住句子里部分单词,让模型预测遮盖词,然后反向传播梯度来更新 Embedding 矩阵所有参数
- 训练收敛,得到成熟词向量:训练多轮 epoch 后,语义相近单词向量空间距离变近(
),语义无关单词向量距离很远。此时矩阵
固化,形成静态 Word Embedding。
场景二:语音 / 音频
将连续语音波形转换为 “帧特征向量的集合” :每帧取 25ms 的语音窗口,帧移 10ms(窗口重叠,保证语音连续性)。1 秒语音对应
1s / 10ms = 100帧,不同时长的语音对应不同数量的帧(输入长度可变)。最后使用MFCC等方法对每帧语音提取声学特征。所以一段语音就是 “长度可变的帧特征向量集合”。
场景三:图结构
图(Graph)本质也是向量集合,将图的每个节点(Node)视为一个向量,整个图就是节点向量的集合。例如社交网络中,每个用户是一个节点,用户的画像(年龄、性别、兴趣、行为等特征)就是一个向量;用户之间的社交关系是图的边。
向量集合(Vector Set)的本质定义:由多个向量组成、长度可变的输入数据,广泛存在于 NLP、语音、图结构等领域,核心特点是输入长度不固定。
可变长度输入任务的三类输出形式:
- 形式1(序列标注(Sequence Labeling)):每个向量对应一个标签(Each vector has a label)。典型应用如
- POS tagging(词性标注):输入句子
I saw a saw(4 个词向量),输出 4 个词性标签N/V/DET/N,解决一词多义(saw可作动词 / 名词);- 语音帧分类:输入语音帧向量集合,输出每个帧的标签(如音素分类、语音活动检测)
- 社交网络节点分类:输入用户节点向量集合,输出每个用户的标签(如是否购买、是否为异常用户)。
- 形式2(序列分类(Sequence Classification)):整个序列 / 集合对应一个标签(The whole sequence has a label)。典型应用如
- Sentiment analysis(情感分析):输入句子
this is good(4 个词向量),输出 1 个标签positive(正面情感);- 说话人识别:输入一段语音的帧向量集合,输出 1 个说话人身份标签;
- 形式3(序列到序列(Seq2Seq)):模型自主决定输出标签数量(Model decides the number of labels itself)。典型应用如
- 机器翻译:输入英文
N个词,输出法文N'个词;- 语音识别:输入语音
N帧,输出文本N'个词;- 文本摘要:输入长文本
N个词,输出摘要N'个词。
Self-attention
下面我们以 序列标注(Sequence Labeling) 为例,通过最简单的全连接层来引入Self-attention,并介绍Self-attention工作原理及过程:
如果只使用全连接层来实现序列标注(Sequence Labeling),如下所示(FC表示全连接层,Fully-connected),每个输入向量单独经过一个全连接层(FC),直接输出对应标签。但是这样完全不考虑上下文,每个词的预测只依赖自身,无法利用前后文信息。

为了让模型考虑上下文,用 滑动窗口 把前后几个词拼起来均作为输入输入到全连接层,让模型看到局部邻居。但是窗口大小有限,只能看局部,无法捕捉全局 / 长距离依赖,而且窗口大小固定,不同长度的句子需要截断 / 填充,同时,窗口越大会导致输入维度越高,全连接层参数呈指数增长,训练困难。

针对以上问题,自注意力机制设计目标就是给序列中每个向量,生成融合整个序列全局上下文的新特征,可以灵活捕捉任意两个位置的依赖。如下所示,输入向量先经过Self-attention 层,输出 4 个带上下文的新向量每个新向量都融合了整个序列所有向量的信息,再分别输入 FC 层做序列标注。

可以像CNN一样堆叠多层自注意力 + FC,提取更抽象的高层特征:

下图直观展示了自注意力的连接本质(虚线表示有关系,不是全连接),每个输出都与所有输入
有关(即带全局上下文信息),且 Self-attention层 可灵活用于输入层或中间隐藏层,用
统一表示 Self-attention层 的输入。

以第一个输入对应第一个输出
为例。自注意力机制的本质上是求
与其他输入
的关联性(用
表示关联性,称为相关性分数),相关性越高
越大,表示该向量对
贡献越大。

相关性分数的计算方式及过程如下。计算相关性的经典方法有两种:
- Dot-product(点积,Transformer 默认使用):以计算
与
的相关性为例。将输入向量
乘以权重矩阵
得到向量
,
乘以线性矩阵
得到向量
,最后得到相关性
- Additive(加性,早期注意力):
注意:Transformer 中统一使用点积,因为计算速度快,完美适配 GPU 并行。

以计算 为例,用
的 Query
(
),与所有位置的 Key
做点积(
),得到原始相关性分数(输入向量
,查询向量
,键向量
,最终通过点积公式得到的相关性分数是一个标量):
。
分数越高,代表两个位置的相关性越强。将原始分数 输入Softmax 函数,归一化到
[0,1]区间,且总和为 1,得到最终的注意力权重:

用归一化后的注意力权重,对所有位置的 Value
(
)做加权求和,得到最终输出:

所以,自注意力机制对于每个输入向量,用 3 个可学习的权重矩阵
做线性变换,得到 3 个功能不同的向量:

- Q(查询):相当于用户输入的「检索关键词」,代表当前待表征的特征自身的需求,用于去匹配其他特征中有用的信息。
- K(键):相当于数据库的「索引标签」,代表被查询特征的身份标识,用于和Q计算相似度,判断哪些信息值得关注。
- V(值):相当于数据库中「索引对应的实际内容」,代表被查询特征的具体信息,最终会根据相似度权重被加权求和,输出融合后的特征。
是并行计算的,它们的计算方式与
相同:

下面从矩阵角度理解自注意力机制的计算过程:
1.输入定义
假设输入序列长度为
,每个输入向量
是3 维列向量:
将所有输入向量按列拼接,得到输入矩阵
(维度:3×4):
2.权重矩阵定义
自注意力的 3 个核心可学习权重矩阵(维度由模型隐藏维度
决定,这里假设
做示例,可任意扩展):
:Query 权重矩阵
:Key 权重矩阵
:Value 权重矩阵(
为 Value 维度,通常与
相等)
3.Q/K/V 矩阵的矩阵运算
对每个输入向量
,线性变换生成
:
将所有
按列拼接,得到Q/K/V 矩阵:
4.注意力分数矩阵
的计算
原始注意力分数
是
与
的点积:
将所有
组合成原始注意力矩阵
(维度:4×4,行对应 Query,列对应 Key),其矩阵运算为:
5.Softmax 归一化
对矩阵
的每一行做 Softmax 归一化,得到注意力权重矩阵
(维度仍为 4×4,每行和为 1):
6.输出矩阵
的计算
每个输出向量
是所有
按注意力权重
的加权求和:
将所有
按列拼接,得到输出矩阵
(维度:
×4),其矩阵运算为:
完整矩阵公式
Multi-head Self-attention
单头自注意力在同一个向量空间中计算所有位置的相关性,只能建模一种类型的依赖关系。但是对于实际任务(如 NLP、机器人时序数据、多传感器融合)中,序列的依赖是多维度的,例如自然语言中一个词需要同时关注 “语法搭配(主谓 / 冠词 + 名词)” “语义关联(同义词 / 指代)” “长距离上下文” 等多种依赖关系。
多头自注意力的核心设计目标就是将 投影到多个独立的子空间,每个头在自己的子空间中学习不同类型的相关性;最终融合所有子空间的特征,让模型同时捕捉多维度、复杂的序列依赖,大幅提升表达能力。
下图以两个头为例说明其工作过程:

第一步:生成单头 (与单头自注意力一致)
- 对每个输入向量
(以 3 维输入、序列长度 4 为例),用全局权重矩阵
生成单头的
:

第二步:分头,生成每个头的子
- 对单头的
,用每个头专属的权重矩阵做线性变换,得到每个头的子空间
:

头1:
头2:
每个头的子空间完全独立,互不干扰,为学习不同类型的依赖提供基础。
第三步:头 1 和头 2 的独立自注意力计算
- 头 1 在自己的子空间中,执行完整的单头自注意力流程:
计算注意力分数:
Softmax 归一化:
加权求和:

- 头 2 在自己的子空间中,执行完整的单头自注意力流程:
计算注意力分数:
Softmax 归一化:
加权求和:

第四步:多头输出融合,得到最终输出
- 将所有头的输出
按行拼接(Concatenate),再用全局输出权重矩阵
做线性变换,得到最终的多头自注意力输出
:
将拼接后的高维向量投影回与单头一致的维度(如 4 维),融合多个子空间的特征,得到最终带全局上下文的输出
。
Positional Encoding
对于上述介绍的自注意力机制,它有一个明显的缺陷,即自注意力本身不包含任何位置信息,它的核心逻辑是计算序列中所有向量的全局相关性,它只关注向量的内容,完全不关心向量的顺序。这意味着对于输入序列和
自注意力计算出的
、注意力权重、输出特征完全一致。
针对自注意力的位置缺失问题,位置编码(Positional Encoding)的设计目标非常明确:为序列中每个位置 ,分配一个唯一的位置向量
,让不同位置可区分,具体实现过程如下:

- 为每个位置生成唯一的位置向量
:对于长度为
的序列,为每个位置
(
)生成一个维度与输入特征
完全相同的位置向量
。
- 位置向量与输入特征相加:将位置向量
与输入特征
逐元素相加,得到带位置信息的新输入
:
- 用融合后的
代替原始
,计算 Q/K/V,执行自注意力计算:

对于该如何生成,有以下两种常用的方式:
- Hand-crafted:手工设计的正弦 - 余弦位置编码(Transformer 原始方案)。该方案完全由手工设计,无需训练。公式定义,对于序列中第
个位置(从 0 开始计数),位置向量
的第
和
维为(
是输入特征
的维度(与
维度一致)):

- Learned from data:可学习的位置编码。将位置编码视为一个可学习的嵌入层(Embedding Layer),让模型在训练中自动学习每个位置的
:
初始化一个位置编码矩阵,其中max len是模型支持的最大序列长度(如 512、1024);训练时,通过反向传播更新矩阵
中的每个位置向量;推理时,取对应位置的
,与
相加。
Self-attention for Speech
语音是典型的超长时序向量序列,通常以 10ms 为一帧提取声学特征(如 MFCC、Filter Bank),1 秒语音对应 100 帧,长对话 / 语音指令可达数千帧,序列长度 极大;而标准自注意力的时间 / 空间复杂度为
,注意力矩阵
是
的方阵,当
时矩阵大小达 100 万,
时直接破亿,计算量和显存完全无法承受。为此,在使用自注意力机制解决语音问题时常采用截断自注意力(Truncated Self-attention):
限制每个位置的注意力计算范围,仅在局部时间窗口(附近几个输入向量)内计算注意力(下图用红色叉号表示屏蔽长距离的全局连接)。以输入(第 3 帧语音)为例,仅在固定窗口(如前后 3-5 帧)内计算与其他帧的相关性,不计算与整个序列所有帧的关联。既大幅降低计算量,又保留语音所需的局部时序依赖(语音的音素、语义仅与前后几帧强相关,长距离依赖可通过多层堆叠捕捉)。

完整处理流程如下:
- 特征提取:将连续语音波形分帧,提取每帧的声学特征(如 39 维 MFCC),得到长度为
的向量序列。
- 窗口化自注意力计算:对每帧特征,仅在局部窗口内计算
、注意力分数、加权求和,生成带上下文的帧特征。
- 多层堆叠:多层截断自注意力堆叠,逐步扩大感受野,捕捉长距离时序依赖。
- 任务头输出:接全连接层 / CTC/Transformer 解码器,完成语音识别、说话人识别等任务。
Self-attention for Image
图像是 2D 网格结构,自注意力的核心是将图像转换为向量集合(序列),建模全局空间依赖,弥补 CNN 仅能局部建模的缺陷。图像的向量化方法:
对于 的图像(如5×10×3的 RGB 图),对于图像里的每一个像素(每个网格小格子)把它在 R、G、B 三个通道的数值,按顺序拼起来,就得到一个3 维向量。图像共有50个像素,我们把这 50 个向量按 从左到右、从上到下 的顺序排成一列,就得到了一个长度为 50 的向量序列。原本的图像是三维张量
[H=5, W=10, C=3],转成向量序列后,变成二维矩阵[N=50, D=3]表示序列长度(像素总数),
N=50D=3表示每个向量的维度(通道数)

但是上述这种一个像素作为一个向量,如果是一张 224×224 的彩色图,H×W=50176 个像素,序列长度 5 万,计算量巨大。所以实际工程中通常使用Patch 级向量化:
- 把图像切成一个个 Patch(图像块):比如把 224×224 的图像,切成16×16 大小的 Patch。每个 Patch 的大小为
16×16×3(16 行、16 列、3 个通道),总 Patch 数(224/16) × (224/16) = 14×14 = 196个(序列长度从 5 万→196,计算量直接降了几百倍) - 把每个 Patch,打包成一个向量:把每个 16×16×3 的 Patch 展平,得到一个768 维的向量(16×16×3=768)
- 把所有 Patch 的向量,排成 向量序列:把 196 个 Patch 的向量,按 从左到右、从上到下 的顺序排成一列,得到长度为 196 的向量序列,每个向量 768 维,完美适配自注意力的输入。
- 补充位置编码:自注意力本身没有位置信息,所以我们给每个 Patch 加一个2D 位置编码向量(维度和 Patch 向量一致,768 维),和 Patch 向量相加,让模型感知 这个 Patch 在图像中的上下左右空间位置 。
Self-attention for Graph
图(Graph)是不规则的拓扑结构,节点数量可变、节点之间的连接任意(无固定顺序 / 网格)。
图注意力网络 GAT的核心逻辑是将图的每个节点视为一个向量(节点特征,如社交网络的用户特征),整个图是节点向量的集合;仅对有边连接的邻居节点计算注意力,无连接的节点对注意力分数置 0(图中注意力矩阵仅相连节点有值,其他为 0),每个节点的输出,是其所有邻居节点的加权求和,权重为动态学习的注意力分数,自动区分不同邻居的重要性。

Self-attention VS CNN

- CNN模型弹性小,在数据量较少时,泛化能力更强、训练更稳定。
- Self-attention模型容量大,表达能力强。在海量数据预训练下,性能显著超越 CNN,能捕捉更复杂的全局特征。
Self-attention VS RNN
- RNN:
- 串行计算(Non-parallel):必须按时间步(
)依次处理,前一步的输出依赖于后一步的输入,无法同时计算所有位置,只能逐步传递隐藏状态(memory)。
- 长距离依赖困难:信息需沿时间步传递,长序列中梯度易消失,导致早期信息难以被捕捉。
- 串行计算(Non-parallel):必须按时间步(
- Self-attention:
- 并行计算(Parallel):所有位置的特征计算同时进行,无先后依赖关系。所有向量可一次性处理,极大提升了训练速度。
- 长距离依赖轻松:通过注意力分数直接建立任意两个位置的联系,无需逐层传递,长序列建模更轻松。

更多推荐
















所有评论(0)