位置编码

28
0
0
2023-03-03

位置编码

位置编码(Positional Encoding)是Transformer模型中用来引入序列中词语位置信息的一种技术。由于Transformer模型本身不包含循环神经网络的递归结构或卷积神经网络的层次结构,因此它本身无法捕捉到序列数据中的顺序信息。位置编码就是为了解决这个问题而设计的。

位置编码的方法

位置编码通常是通过以下方式实现的:

  1. 正弦和余弦函数: 位置编码通常是通过使用正弦和余弦函数来计算的,这些函数能够以固定频率变化,从而编码位置信息。具体的计算公式如下:

    对于位置 pos 和维度 ii 从 0 到 d_model/2):

    PE(pos, 2i) = sin(pos / 10000^(2i/d_model))
    PE(pos, 2i+1) = cos(pos / 10000^(2i/d_model))
    

    其中,d_model 是嵌入向量的维度。这种方法使得模型能够捕捉到相对位置信息,因为对于任意固定偏移 kPE(pos+k) 可以被表示为 PE(pos) 的线性函数。

  2. 学习到的位置编码: 位置编码也可以作为模型参数在训练过程中学习得到,而不是预先计算。这种方法允许模型根据具体任务的需要自适应地调整位置编码。

位置编码的应用

位置编码在Transformer模型中的应用如下:

  1. 与词嵌入结合: 在Transformer模型中,位置编码向量通常与词嵌入向量相加,得到最终的输入表示。这样,每个词语的表示既包含了词汇信息,也包含了位置信息。

  2. 多头注意力机制: 在Transformer的多头注意力机制中,位置编码使得模型能够在计算注意力权重时考虑到词语的相对位置。

  3. 序列处理: 在处理序列任务(如机器翻译、文本摘要等)时,位置编码帮助模型理解词语的顺序,这对于理解句子的语义至关重要。

正弦和余弦位置编码的简单解释

  1. 想象一个长长的数字列表:假设我们有一个句子,每个词都有一个对应的数字列表(词向量),这些列表的长度是固定的,比如512。

  2. 给每个数字列表添加位置信息:为了让模型知道每个词在句子中的位置,我们需要在原来的数字列表上添加一些额外的信息。这些信息就是位置编码。

  3. 使用正弦和余弦函数:我们使用正弦和余弦函数来生成位置信息。这些函数可以根据词在句子中的位置(比如第一个词、第二个词等)来生成不同的数字。

  4. 如何生成这些数字:对于每个位置,我们使用以下公式来生成位置编码的数字:

    • 对于列表中的偶数位置(第0、2、4…个数字),我们使用正弦函数:sin(位置 / 频率)

    • 对于列表中的奇数位置(第1、3、5…个数字),我们使用余弦函数:cos(位置 / 频率)

    这里的“频率”是一个随着列表位置增加而增加的数字,这样每个位置都有不同的正弦和余弦值。

  5. 将位置编码添加到词向量上:最后,我们将生成的正弦和余弦数字添加到原来的词向量上。这样,每个词的数字列表不仅包含了词本身的信息,还包含了它在句子中的位置信息。

为什么这样有效?

  • 不同的频率:使用不同的频率可以让模型捕捉到词与词之间的相对位置关系。例如,如果两个词相隔很远,它们的位置编码在某个频率上会有很大的差异。

  • 正弦和余弦的组合:正弦和余弦函数可以组合出很多种模式,这些模式可以帮助模型理解更复杂的序列结构。

小知识

Position Embedding 本身是一个绝对位置的信息,但在语言模型中,相对位置也很重要。那么为什么位置嵌入机制有用呢?

我们不要去关心三角函数公式,可以看看下图公式(3)中的第一行,我们做如下的解释,对于 “我爱吃苹果” 这一句话,有 5 个单词,假设序号分别为 1、2、3、4、5。

假设 pos=1=我、k=2=爱、pos+k=3=吃pos=1=我、k=2=爱、pos+k=3=吃,也就是说 pos+k=3pos+k=3 位置的位置向量的某一维可以通过 pos=1pos=1 位置的位置向量的某一维线性组合加以线性表示,通过该线性表示可以得出 “吃” 的位置编码信息蕴含了相对于前两个字 “我” 的位置编码信息。

总而言之就是,某个单词的位置信息是其他单词位置信息的线性组合,这种线性组合就意味着位置向量中蕴含了相对位置信息。