跳转至

Transfomer面

为什么 Transformer 需要显式引入位置信息?自注意力本身为什么不具备位置感知?

自注意力的置换等变性

自注意力机制的核心运算可以概括为:

image.png

置换等变性对于某些任务(例如聚合全局信息)是友好的,但对于序列建模来说是不够的。语言是时序的,后续的 token 往往依赖于前面的 token,而位置信息正是建立这种依赖关系的基础。比如在翻译任务中,“I am” 和 “am I” 的区别必须被模型捕捉到。

为什么需要显式引入

正因为自注意力自身对位置“无感”,我们必须通过额外的方式把位置信息告诉模型。目前主流的方法有三种:

  1. 绝对位置编码(Absolute Positional Encoding):在输入嵌入中直接加入一个表示位置的向量,比如原始 Transformer 使用的正弦/余弦位置编码,或者可学习的位置嵌入(learned positional embedding)。

  2. 相对位置编码(Relative Positional Encoding):在计算注意力分数时,直接考虑两个 token 之间的相对距离,例如 Transformer-XL、T5、ALiBi 等采用的方式。

  3. 旋转位置编码(RoPE):通过对查询和键向量施加旋转矩阵,将相对位置信息融入注意力计算中,目前大模型(如 LLaMA、GPT-NeoX)广泛采用。

无论哪种方法,本质都是在原本不包含位置信息的计算图中,注入一个与位置相关的项,从而使模型能够区分不同位置的相同词,并利用词序进行推理。


原始 Transformer 使用的正弦/余弦位置编码公式是怎样的?每个维度上的频率如何计算?

image.png

频率的计算方式

公式中的分母部分决定了每个维度的波长(即周期)。具体来看,对于第 ii 维(或者更准确地说,第 ii 组,因为每两个维度共享同一个频率),其角频率为:

image.png

为什么选择正弦/余弦而非可学习的位置嵌入?

论文作者指出,正弦/余弦编码能够外推到比训练时更长的序列(因为函数定义在所有位置上都有效),而可学习的位置嵌入只能处理预设的最大长度。此外,正弦/余弦编码不需要额外的训练参数,实现简单。不过,后来的实践表明,可学习的位置嵌入在性能上往往更优,而 RoPE 等新方法结合了两者的优点。

工程实现示例(PyTorch 风格)

import torch
import math

def sinusoidal_position_encoding(max_len, d_model):
    pe = torch.zeros(max_len, d_model)
    position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
    div_term = torch.exp(torch.arange(0, d_model, 2).float() *
                         (-math.log(10000.0) / d_model))
    pe[:, 0::2] = torch.sin(position * div_term)   # 偶数维
    pe[:, 1::2] = torch.cos(position * div_term)   # 奇数维
    return pe

这段代码直接实现了上述公式。div_term 计算了所有频率的倒数,然后与位置 position 相乘后分别取 sin 和 cos。得到的 pe 可以直接加到词嵌入上作为输入。

正弦位置编码为什么能表达相对位置关系?请从三角函数角度解释。

正弦和余弦函数具有线性相加的性质,这使得位置编码能够自然地表达相对位置关系。对于固定的偏移量 k,位置 pos + k 的编码向量可以由位置 pos 的编码向量经过一个线性变换得到。这是由三角恒等式保证的:

image.png

因此,对于任意维度 i,位置 pos+k 的编码(正弦和余弦分量)可以表示为位置 pos 编码的线性组合,其中组合系数只依赖于偏移 k,与绝对位置 pos 无关。由于 Transformer 的注意力计算和 FFN 中包含线性变换,模型理论上可以学习利用这种线性关系来捕捉相对位置,而不需要显式地计算相对距离。

这种性质使得正弦位置编码具有一定的外推能力:即使模型在训练时没有见过某些绝对位置,只要见过某个相对偏移,也可能通过这种线性关系泛化。这一特性是固定正弦编码相比可学习绝对位置编码的重要优势。

可学习位置编码与固定位置编码各有什么优缺点?在什么场景下选择哪种?

可学习位置编码(Learned Positional Embedding):

  • 优点:灵活,允许模型为每个位置学习最适合任务的位置表示。它不依赖人工设计的函数,能够通过训练自动适应数据中的位置模式。对于大多数任务,它通常能带来微小的性能提升,因为它可以编码任意位置相关的先验。

  • 缺点:位置数量固定(最大序列长度),无法外推到更长的序列。如果测试序列超出训练时的最大长度,就会遇到未见过位置嵌入,导致性能下降或需要特殊处理。另外,可学习位置嵌入容易过拟合,尤其当训练数据有限时,低频位置嵌入可能训练不充分。

  • 适用场景:当序列长度相对固定或可以截断/填充到固定长度时,可学习位置嵌入简单有效。BERT 及许多早期模型使用它。

固定位置编码(Sinusoidal Positional Encoding):

  • 优点:无需训练参数,可以处理任意长度序列(因为函数可以无限外推,尽管外推效果会衰减)。由于它是确定性函数,不会引入额外的过拟合风险。它蕴含相对位置信息,有助于模型捕捉相对位置。

  • 缺点:因为是固定的,无法根据任务进行调整。对于某些需要不同位置权重的任务,固定编码可能不是最优。而且,在实际超长序列外推时,由于训练中模型只见过一定长度内的正弦模式,外推后的性能仍然会下降。

  • 适用场景:需要处理可变长度或较长序列的任务,尤其是期望模型具有一定长度外推能力时。原始 Transformer 和许多现代大模型(如 LLaMA 使用 RoPE,一种相对编码变体,但固定编码也被某些模型使用)倾向于固定编码或基于它的变体。

选择哪种通常取决于任务特性、数据和工程便利性。当前趋势是使用相对位置编码(如 RoPE),它结合了两者的一些优点。

可学习位置编码的最大序列长度是固定的,如果要处理超过该长度的文本,有哪些简单处理方式?

  1. 插值(Interpolation):将超出最大长度的位置线性或非线性缩放到训练过的位置范围内。例如,对于位置 p > L,使用 p * (L / max_len) 的位置编码。更常用的是在每一层的位置编码上做插值。这种方法简单,但可能导致高频信息丢失,影响局部感知。

  2. 外推(Extrapolation):直接使用位置 p,但位置嵌入是随机初始化的。由于这些位置未参与训练,模型可能难以利用。可以配合微调,用少量长序列数据微调新位置嵌入。

  3. 分块处理(Chunking):将长序列切分为多个重叠或不重叠的片段,每个片段独立编码后,在片段之间引入特殊的片段位置嵌入(如相对位置)或通过循环机制连接。例如 Transformer-XL 使用片段级别的循环,将前一个片段的隐藏状态缓存并用于当前片段,配合相对位置编码。

  4. 相对位置编码代替绝对位置:使用相对位置编码(如 Shaw et al., 2018; T5; RoPE)可以从根本上解决长度限制问题,因为相对位置只关心距离,不依赖于绝对位置索引,理论上可以处理任意长度。这是当前主流方法。

  5. 层次化位置编码:为文档结构设计位置(如句子级位置+词级位置),以降低绝对位置索引的增长。

  6. 连续位置编码(Continuous Positional Encoding):使用可学习的连续函数(如 MLP)将位置映射为嵌入,理论上可以输入任意实数值位置。推理时泛化到新位置,但需要训练时模拟长度变化。

绝对位置编码加到输入的方式是“相加”还是“拼接”?为什么相加通常效果更好?

原始 Transformer 采用的是相加:input = token_embedding + position_embedding。相加效果好的原因:

  • 维度匹配与信息融合:相加要求位置编码和词嵌入维度相同,二者可以直接融合,不增加额外维度。信息在相同的向量空间中混合,后续的注意力层和 FFN 可以通过学习自动从中解耦位置和语义信息。拼接虽然保留了独立性,但使输入维度加倍,需要额外的线性变换降维,增加了参数和计算量,并且可能引入过多的自由度导致模型难以学习到位置和语义的有效交互。

  • 参数效率:相加不引入额外参数,模型更紧凑。

  • 经验效果:大量实验证明相加的效果优于或相当于拼接,同时更简洁。

如果采用拼接,则输入变为 [token_emb; pos_emb],然后需要一个全连接层将维度映射回 d_model。这种方式在一些工作(如使用复杂位置信息)中有应用,但总体不如相加普遍。

正弦位置编码是逐元素加到词向量上的,这是否会造成语义信息被“污染”?

理论上,位置编码的加入确实会在一定程度上“干扰”原始的语义表示,但这种污染是可以接受且必要的,因为:

  • 模型可以学会分离:Transformer 的后续层具有足够的容量来处理混合信号。通过注意力机制和非线性变换,模型能够从混合向量中重新提取出语义成分和位置成分。实验表明,模型确实会形成专门的注意力头分别关注内容和位置。

  • 位置信息本身就是上下文的一部分:在自然语言中,词义和位置是耦合的(例如“我”和“你”的相对位置决定指代)。将位置与语义直接混合,实际上符合语言处理的本质需求。

  • 向量空间的富余维度:高维向量空间(如 512 维)中,不同的信息可以占据大致正交的子空间。位置编码和词嵌入可以近似在不重叠的方向上,从而减少干扰。

虽然有轻微污染,但整体带来的位置感知好处远大于负面作用。一些工作曾尝试将位置编码加在注意力分数或值上,而不是与输入相加,但相加已成为标准且有效的设计。

绝对位置编码能否区分方向(前后)?如果不能,这对语言理解有影响吗?

绝对位置编码(无论是正弦还是可学习)本质上只告诉模型“绝对位置”,不直接告诉“相对方向”(前或后)。然而,通过结合自注意力,模型能够学到方向信息。因为自注意力计算时,每个 token 可以看到所有其他 token,通过比较它们的绝对位置编码,模型可以推断出相对次序。例如,在可学习的绝对位置嵌入中,位置 pospos+1 的嵌入在训练中会形成特定的关系,注意力头可以学会将“前面的 token”与“后面的 token”区分开来。

对于语言理解,方向性至关重要(例如理解“A 在 B 之前”)。如果模型无法区分方向,很多语言任务(如词序敏感的任务)将无法完成。实验表明,使用绝对位置编码的 Transformer 确实能够捕捉方向,因为它可以通过学习位置嵌入之间的差值来隐式编码相对位置。但是,这种隐式能力依赖于足够的训练数据,且在一些细粒度的顺序任务中可能不如显式的相对位置编码稳健。

在 BERT 中,位置编码是可学习的,最大支持 512,如果想微调支持 1024 长度,怎么初始化新增的位置嵌入?

对于 BERT 扩展至 1024 位置,通常采用以下初始化策略:

  • 复制已有位置的嵌入模式:将位置 0~511 的嵌入复制或通过某种变换得到位置 512~1023 的嵌入。一种简单的方法是使用插值:将原本 512 个位置的嵌入进行线性扩展,比如对于新位置 p,取 p' = p * (512 / 1024) 处的嵌入(可能需要最近邻或线性插值)。然后在微调中一起更新。

  • 随机初始化并微调:为新增的位置嵌入随机初始化(如小正态分布),然后在微调时只训练这些新嵌入,或全部位置嵌入一起微调。为了保持模型稳定性,可以使用较小的学习率训练新增部分。

  • 基于正弦编码的初始化:用正弦位置编码公式为所有 1024 个位置生成嵌入,然后作为初始值,微调时可全部微调或仅微调高频部分。

实践中,微调时通常使用长文本数据(如截断或生成的长文档),并联合训练所有位置嵌入。为了避免破坏预训练学到的表示,早期阶段可以冻结前 512 个位置嵌入,只微调新增的 512 个,随后再一起微调。

分析正弦位置编码的波长范围:小维度对应高频还是低频?这有利于捕捉什么范围的位置?

在正弦位置编码中,维度索引 i 越小,对应的频率越高(波长越短)。具体地,第 0 对维度(i=0)频率最高,波长最短(2π2π);随着 i 增大,频率逐渐降低,波长变长。

  • 高频(小维度):变化快,对位置变化敏感,适合捕捉局部位置信息(如相邻词的关系、短语结构)。短波长让相邻位置的编码有显著差异,有助于模型区分近距离 token。

  • 低频(大维度):变化慢,对位置变化不敏感,适合捕捉全局位置信息(如段落起始、长距离相对位置)。低频分量在较大范围内值相近,让模型感知远距离的粗略位置。

这种多尺度设计使模型能同时关注局部和长程依赖。

为什么位置编码向量的 L2 范数随着维度增加而增大?这会导致什么问题?

正弦位置编码向量在第 i 维的幅度基本恒定(正弦/余弦值域 [-1,1]),但向量的元素数量为 d_model。随着维度增加,L2 范数自然增大,因为它是所有元素的平方和的平方根。对于正弦编码,范数大致为 dmodel/2dmodel/2。

这可能导致的问题是:位置编码的范数远大于词嵌入的范数(后者通常初始化为较小的随机值,如 Xavier 初始化后范数约 1)。当二者相加时,位置编码可能主导输入表示,削弱语义信息。为缓解这个问题,实践中可以:

  • 缩放位置编码(例如乘以一个小于 1 的因子)。

  • 对词嵌入和位置编码分别进行适当的缩放(如在 Pre-LN Transformer 中,嵌入后通常立即接 LayerNorm,可以平衡二者)。

  • 使用层归一化来混合。

现代 Transformer 的 Pre-Norm 结构会在第一层自注意力之前进行 LayerNorm,可以有效减轻这种幅度差异。

绝对位置编码能否用于层次化结构(如句子级位置)?如果可以,怎么设计?

可以。层次化位置编码可以为每个 token 提供多级位置信息,例如:词在句子中的位置 + 句子在段落中的位置 + 段落在文档中的位置。一种设计方案是组合编码:将不同层次的位置编码分别生成后相加或拼接。例如,对于一个 token,可以使用三个不同的位置编码:pos_word(词级位置)、pos_sent(句子级位置)、pos_para(段落级位置)。这些编码可以通过可学习嵌入表或正弦函数生成。然后,将这些编码加在一起,或者采用不同频率的编码以关注不同层次。

另一种方法是使用层次化可学习嵌入:为每个层次维护一个嵌入矩阵,每个层次的嵌入维度之和等于 d_model。然后将不同层次的嵌入拼接或相加。

文献中,BERT 本身使用了句子级位置(Segment Embedding),但那是用于区分两个句子,不是精确的位置。层次化位置编码在长文档建模、对话系统中的话语级和词级位置感知中很有用。

在 Transformer 中,位置编码的数值范围通常多大?与词嵌入的数值范围是否匹配?不匹配会有什么影响?

正弦位置编码的输出值范围是 [-1, 1]。词嵌入通常是随机初始化(如正态分布 N(0, 0.02)),数值范围也大致在 -0.1 到 0.1 之间。这样,位置编码的幅度可能显著大于词嵌入,导致输入中位置信息压倒语义信息。不过,标准 Transformer 会在嵌入之后通过 LayerNorm(在 Pre-Norm 架构中,输入会先经过 LayerNorm,实际上嵌入和位置编码相加后,会通过残差连接前的归一化吗?在 Pre-Norm 中,第一层自注意力的输入是先 LayerNorm 再进入注意力,所以相加后的混合向量会先被归一化,从而平衡尺度。在原始 Post-Norm 中,嵌入相加后直接进入注意力层,但权重初始化已将嵌入缩小,并通过后归一化调整。

现代做法:在使用 Pre-Norm 时,嵌入和位置编码相加后立即进入 LayerNorm,因此幅度差异被归一化缓解。但如果没有归一化或初始化不当,幅度不匹配可能导致训练初期不稳定,模型需要更多时间调整词嵌入的尺度来匹配位置编码。实验中常将位置编码乘以一个小的常数(如 0.01)来匹配嵌入。

为什么原始的绝对位置编码在超长序列下效果不好?仅仅因为没训练过吗?

不止是没训练过。根本原因有两个:

  • 泛化能力有限:对于可学习的绝对位置编码,超出训练长度的位置编码从未被训练,其嵌入是随机初始化的,模型不知道如何使用这些新位置,性能自然下降。对于正弦位置编码,尽管函数可以外推,但模型仅在有限长度(如 512)上训练,学到的注意力模式和权重并未适应更长序列的正弦波模式,导致注意力分布异常。

  • 位置区分度下降:随着序列变长,绝对位置编码中低频分量对距离的区分度越来越弱。例如,位置 1000 和 1001 在高频上区分明显,但低频分量差异极小。模型在训练时已经适应了特定长度范围内的位置变化模式,对于更长序列,注意力层难以有效利用这种变缓的变化来区分 token 的顺序。

  • 注意力分布的平滑化:在长序列中,由于 softmax 归一化,注意力权重趋于均匀分布,导致信息检索困难。这不仅仅是位置编码的问题,但绝对位置编码无法缓解这种现象。

因此,超长序列需要特殊的编码策略(如相对位置编码、RoPE、ALiBi)来重新引入距离感知。

可学习位置编码是否能隐式学到相对位置信息?有什么证据?

是的,可学习位置编码在训练后能够隐式地编码相对位置。证据包括:

  • 训练好的位置嵌入之间的点积或差值表现出一定的周期性或平滑性。可视化显示相邻位置的嵌入相似度较高,距离越远相似度越低,体现出相对距离信息。

  • 可以训练一个线性变换,以位置 p 的嵌入为输入,预测位置 p+k 的嵌入,说明相对位置信息蕴含在绝对位置嵌入中。

  • 在注意力模式中,许多注意力头会形成类似“关注前一个 token”的偏置,这需要模型从绝对位置嵌入中提取出相对位置信号。

因此,绝对位置编码确实学到了一定程度的相对位置。然而,这种能力是隐式且有限的,尤其在需要泛化到新长度时表现不佳。

绝对位置编码的维度如果小于词嵌入维度,多余维度填零,这会损害性能吗?

会损害性能。因为位置信息只存在于部分维度,其余维度语义信息独占。这会造成:

  • 维度使用不均衡,注意力计算时不同维度的重要性不匹配,可能限制了模型容量。

  • 填零的维度浪费了表示空间,且零值会与词嵌入中的非零信号混杂,可能干扰注意力权重的计算。

  • 实验证明,这种做法会导致性能下降。通常应该使位置编码维度等于词嵌入维度,或者通过线性变换将低维位置编码投影到高维。

有没有尝试使用随机初始化但不可训练的位置编码?它的效果如何?

有。一种做法是使用随机生成的正弦位置编码(如随机频率和相位),但不训练。或者使用完全随机初始化的可学习位置编码但固定不更新。实验表明,使用随机但固定的位置编码,只要编码具有足够的多样性且能提供唯一的位置标识,模型仍然可以工作,但性能通常不如经过精心设计或学习的位置编码。随机固定编码可能无法为相对位置提供平滑的度量,导致注意力模式混乱。一些工作(如用随机傅里叶特征)表明,适当配置的随机编码可以达到与正弦编码接近的效果,但没有决定性优势。

正弦位置编码的“波长”从 2π2π 到 10000⋅2π10000⋅2π,这个上限 10000 是如何选定的?改变它会怎样?

10000 这个值是经验选定的。它决定了最低频率,使得在训练长度(如 512)内,最低频率的正弦波也只经历了不到一个完整周期的一部分。这样,不同位置在该维度上几乎呈单调变化,提供了唯一的绝对位置信号。如果上限减小(如 100),低频波长变短,在长序列上会发生周期性重复,不同绝对位置可能有相似的编码,削弱绝对位置区分能力。如果上限增大,则低频过于平缓,位置变化近乎不变,浪费维度。因此,10000 是个折中值,针对当时的典型序列长度(512)优化。

改变该值会影响位置编码的尺度,进而影响模型对绝对位置和相对位置的权衡。在更长序列上(如 2048),通常需要增大上限或调整频率分布。

在处理音频或时间序列时,是否可以直接复用 NLP 中的位置编码?有什么特殊考虑?

可以复用,但需要特殊考虑:

  • 采样率差异:音频时间序列的“位置”对应时间步,其密度远高于文本。位置编码需要适应非常长的序列(如几万点)。NLP 中的绝对位置编码在长度极长时失效,需要外推能力强的编码(如 RoPE、ALiBi)。

  • 周期性特征:音频信号具有固有的周期性,位置编码可能干扰这种周期。可以使用可学习的位置编码来适应周期,或使用基于时间戳的编码。

  • 多层次位置:音频可能有多尺度位置(帧级、样本级)。可以设计多尺度位置编码。

  • 连续值位置:不像文本是离散位置,音频时间可以视为连续值。可以用连续函数(如通过 MLP 对时间 t 输出嵌入)来代替离散位置嵌入。

如果输入是一棵树或图,如何设计绝对位置编码来表示拓扑结构?

对于图/树结构,位置编码需要反映节点在结构中的位置,而非线性序列顺序。常见方法:

  • 基于图核或随机游走:使用图上的拉普拉斯矩阵的特征向量作为位置编码(Laplacian Positional Encoding)。每个节点用最小的 k 个非平凡特征向量的对应分量作为位置嵌入。这能编码全局的图结构位置。

  • 可学习的图位置嵌入:如果图结构在数据间一致(如分子图的原子位置),可以使用可学习嵌入,但不够通用。

  • 基于距离或最短路径:将节点到某些锚点的最短路径长度编码为位置,或使用 Weisfeiler-Lehman (WL) 结构特征。

  • 层次化编码:对于树,可以用从根到节点的路径序列的编码(如将路径上的边类型嵌入求和)作为绝对位置。

这些编码与 Transformer 的自注意力结合时,通常加在输入嵌入上,使模型

能够区分同构子图中的不同节点,从而具备结构感知能力。