详解Transformer中的Positional Encoding

参考:

  1. https://arxiv.org/abs/1706.03762
  2. https://www.zhihu.com/question/347678607
  3. https://kazemnejad.com/blog/transformer_architecture_positional_encoding/#what-is-positional-encoding-and-why-do-we-need-it-in-the-first-place
  4. https://blog.csdn.net/Datawhale/article/details/119582757?utm_medium=distribute.pc_aggpa

证明部分:

  1. https://kazemnejad.com/blog/transformer_architecture_positional_encoding/#what-is-positional-encoding-and-why-do-we-need-it-in-the-first-place
  2. https://timodenk.com/blog/linear-relationships-in-the-transformers-positional-encoding/

一、为什么要有Positional Encoding?

像论文中介绍的,由于Transformer中没有循环以及卷积结构,为了使模型能够利用序列的顺序,作者们需要插入一些关于tokens在序列中相对或绝对位置的信息。因此,作者们提出了“Positional Encoding位置编码”的概念。
Transformer结构
Positional Encoding和token embedding具有同样的维度,Positional Encoding和token embedding可以直接相加,结果作为Encoder和Decoder的底部输入。

二、怎么定义Positional Encoding?

现在知道我们需要Positional Encoding,那怎么定义它呢?

我们可以从头构思一下,直接编号行不?

直接编号

假设给定一个长度为 T T T 的序列,token在序列中的位置记作 p o s pos pos,那么token的位置编码
P E = p o s = 0 , 1 , 2 , . . . , T − 1 PE=pos=0,1,2,...,T-1 PE=pos=0,1,2,...,T1
但是这就有个问题,如果有一段很长的序列(假如为1000),那么最后一个token的位置编码非常大,这是很不合适的:

  1. 它比第一个token的编码大太多,和token embedding合并以后难免会出现特征在数值上的倾斜;
  2. 它比一般的token embedding的数值要大,模型可能会把它当作主要信息,对模型可能有一定的干扰。

那么,位置编码最好具有一定的值域范围

对每个位置 p o s pos pos作归一化

我们可以使用序列长度 T T T 对每个位置 p o s pos pos 作归一化,也就是 P E = p o s T − 1 P E=\frac{pos}{T-1} PE=T1pos

上面两种方法都是建立一个长度为 T T T 的词表,按词表的长度来分配position encoding,这两个方法都属于表格型

这样固然使得所有位置编码都落入区间 [ 0 , 1 ] [0,1] [0,1],但是问题也是显著的:
不同长度序列的位置编码的步长是不同的,在较短序列中相邻的两个token的位置编码的差异,会比长序列中相邻的两个token的位置编码差异更小。如果使用这种方法,那么在长文本中相对次序关系会被“稀释”。

我们关注的位置信息,最核心的就是相对次序关系,尤其是上下文中的次序关系。也就是关注一个token与另一个token距离的相对位置(距离差几个token)。应该让位置1和位置2的距离比位置3和位置10的距离更近,位置1和位置2与位置3和位置4都只相差1。

总结一下,position encoding的定义要满足下列需求:

  1. 每个位置有一个唯一的positional encoding;
  2. 最好具有一定的值域范围,否则它比一般的字嵌入的数值要大,难免会抢了字嵌入的「风头」,对模型可能有一定的干扰;
  3. 需要体现一定的相对次序关系,并且在一定范围内的编码差异不应该依赖于文本长度,具有一定translation invariant平移不变性。

函数型

一种思路是使用有界的周期性函数。在前面的两种方法中,我们为了体现某个字在句子中的绝对位置,使用了一个单调的函数,使得任意后续的字符的位置编码都大于前面的字,如果我们放弃对绝对位置的追求,转而要求位置编码仅仅关注一定范围内的相对次序关系,那么使用一个sin/cos函数就是很好的选择,因为sin/cos函数的周期变化规律非常稳定,所以编码具有一定的平移不变性。如下:
P E ( p o s ) = sin ⁡ ( ω ⋅ p o s ) P E(p o s)=\sin \left({\omega \cdot p o s}\right) PE(pos)=sin(ωpos)

其中, ω {\omega } ω 越小,波长越长,即相邻的token的位置编码之间的差异越小。

但这样也存在一些问题:

  1. 如果 ω {\omega } ω 比较大,相邻token之间的位置差异不明显;
  2. 如果 ω {\omega } ω 比较小,在长序列中可能会有一些不同位置的token的位置编码一样,这是因为PE的值域 [ − 1 , 1 ] [-1,1] [1,1] 的表现范围有限。

既然token embedding的维度是 d model  d_{\text {model }} dmodel (论文中 d model  = 512 d_{\text {model }}=512 dmodel =512),那么也可以使用一个 d model  d_{\text {model }} dmodel 维向量来表示位置编码,这样的话,表示范围要远大于 [ − 1 , 1 ] [-1,1] [1,1] ,也方便后面和token embedding直接相加。

三、论文中的公式

论文中给出:positional encoding是一个向量,且 P E → p o s ∈ R d model  \overrightarrow{PE}_{pos} \in \mathbb{R}^{d_{\text {model }}} PE posRdmodel  f : N → R d model  f: \mathbb{N} \rightarrow \mathbb{R}^{d_{\text {model }}} f:NRdmodel  P E → p o s \overrightarrow{PE}_{pos} PE pos 定义为
P E ( p o s , 2 i ) = sin ⁡ ( p o s / 1000 0 2 i / d model  ) P E ( p o s , 2 i + 1 ) = cos ⁡ ( p o s / 1000 0 2 i / d model  ) \begin{aligned} P E_{(p o s, 2 i)} &=\sin \left(p o s / 10000^{2 i / d_{\text {model }}}\right) \\ P E_{(p o s, 2 i+1)} &=\cos \left(p o s / 10000^{2 i / d_{\text {model }}}\right) \end{aligned} PE(pos,2i)PE(pos,2i+1)=sin(pos/100002i/dmodel )=cos(pos/100002i/dmodel )

也可以写作:
P E → p o s ( i ) = f ( p o s ) ( i ) : = { sin ⁡ ( ω k ⋅ p o s ) ,  if  i = 2 k cos ⁡ ( ω k ⋅ p o s ) ,  if  i = 2 k + 1 \overrightarrow{PE}_{pos}^{(i)}=f(pos)^{(i)}:=\left\{\begin{array}{ll} \sin \left(\omega_{k} \cdot pos\right), & \text { if } i=2 k \\ \cos \left(\omega_{k} \cdot pos\right), & \text { if } i=2 k+1 \end{array}\right. PE pos(i)=f(pos)(i):={sin(ωkpos),cos(ωkpos), if i=2k if i=2k+1

其中, ω k = 1 1000 0 2 k / d model  \omega_{k}=\frac{1}{10000^{2 k / d_{\text {model }}}} ωk=100002k/dmodel 1

i i i 表示 P E → p o s \overrightarrow{PE}_{pos} PE pos 的维度, i i i 的取值范围是 [ 0 , … , d model  / 2 ) \left[0, \ldots, d_{\text {model }} / 2\right) [0,,dmodel /2)

具体描述

我们可以想象出这是一个由每一个频率产生的 sin ⁡ / cos ⁡ {\sin}/{\cos} sin/cos对组成的向量(注意这里 d model  d_{\text {model }} dmodel  要除以 2 2 2 ):
P E → p o s = [ sin ⁡ ( ω 0 ⋅ p o s ) cos ⁡ ( ω 0 ⋅ p o s ) sin ⁡ ( ω 1 ⋅ p o s ) cos ⁡ ( ω 1 ⋅ p o s ) ⋮ sin ⁡ ( ω d model  / 2 − 1 ⋅ p o s ) cos ⁡ ( ω d model  / 2 − 1 ⋅ p o s ) ] d model  × 1 \overrightarrow{PE}_{pos}=\left[\begin{array}{c} \sin \left(\omega_{0} \cdot pos\right) \\ \cos \left(\omega_{0} \cdot pos\right) \\ \sin \left(\omega_{1} \cdot pos\right) \\ \cos \left(\omega_{1} \cdot pos\right) \\ \vdots \\ \sin \left(\omega_{d_{\text {model }} / 2-1} \cdot pos\right) \\ \cos \left(\omega_{d_{\text {model }} / 2-1} \cdot pos\right) \end{array}\right]_{d_{\text {model }} \times 1} PE pos=sin(ω0pos)cos(ω0pos)sin(ω1pos)cos(ω1pos)sin(ωdmodel /21pos)cos(ωdmodel /21pos)dmodel ×1
论文说,频率沿着向量维度递减,波长 1000 0 2 k / d model  10000^{2 k / d_{\text {model }}} 100002k/dmodel  呈几何级数增长,从从 2 π 2 \pi 2π 增长到 10000 ⋅ 2 π 10000 \cdot 2 \pi 100002π(不过我算着是到约 9646.61612 ⋅ 2 π 9646.61612\cdot 2 \pi 9646.616122π) 。
P E → p o s = [ sin ⁡ ( p o s / 1000 0 2 × 0 512 ) cos ⁡ ( p o s / 1000 0 2 × 0 512 ) ⋮ sin ⁡ ( p o s / 1000 0 2 × 255 512 ) cos ⁡ ( p o s / 1000 0 2 × 255 512 ) ] d model  × 1 ≈ [ sin ⁡ ( p o s ) cos ⁡ ( p o s ) ⋮ sin ⁡ ( 9646.61612 ⋅ p o s ) cos ⁡ ( 9646.61612 ⋅ p o s ) ] d model  × 1 \overrightarrow{PE}_{pos}=\left[\begin{array}{c} \sin \left(pos / 10000^{2 \times \frac{0}{512}}\right) \\ \cos \left(pos / 10000^{2 \times \frac{0}{512}}\right) \\ \vdots \\ \sin \left(pos / 10000^{2 \times \frac{255}{512}}\right)\\ \cos \left(pos / 10000^{2 \times \frac{255}{512}}\right) \end{array}\right]_{d_{\text {model }} \times 1} \approx \left[\begin{array}{c} \sin \left(pos\right) \\ \cos \left(pos\right) \\ \vdots \\ \sin \left(9646.61612 \cdot pos \right)\\ \cos \left(9646.61612 \cdot pos\right) \end{array}\right]_{d_{\text {model }} \times 1} PE pos=sin(pos/100002×5120)cos(pos/100002×5120)sin(pos/100002×512255)cos(pos/100002×512255)dmodel ×1sin(pos)cos(pos)sin(9646.61612pos)cos(9646.61612pos)dmodel ×1

不过这样定义positional encoding,仍会陷入循环, 这里人为地将最大不重复序列长度限制为 512。例如,在 BERT 中就是这样做的(尽管值得一提的是他们使用了学习位置嵌入,但那是另一回事了)。 如果不这样做,模型确实无法区分序列中的第一个token和第513个token的位置编码。

四、为什么公式可以体现出相对次序关系?

1.相对次序关系怎么表示?

论文原文:

We chose this function because we hypothesized it would allow the model to easily learn to attend by relative positions, since for any fixed offset k, PEpos+k can be represented as a linear function of PEpos.

如果说Positional Encoding向量可以表示相对次序关系,那么 P E → p o s \overrightarrow{PE}_{pos} PE pos 应该满足 P E → p o s + k \overrightarrow{PE}_{pos+k} PE pos+k P E → p o s \overrightarrow{PE}_{pos} PE pos 的线性变换,即:

对于任意固定的偏移量 k k k,存在线性变换 T ( k ) ∈ R d model  × d model  \boldsymbol{T}^{(k)} \in \mathbb{R}^{d_{\text {model }} \times d_{\text {model }}} T(k)Rdmodel ×dmodel ,使得
T ( k ) ⋅ P E → p o s = P E → p o s + k \boldsymbol{T}^{(k)} \cdot\overrightarrow{PE}_{pos} = \overrightarrow{PE}_{pos+k} T(k)PE pos=PE pos+k
这一等式对于序列中任何有效位置 t ∈ { 0 , 1 , … , n − k − 1 } t\in\left\{0,1,\dots,n-k-1\right\} t{0,1,,nk1} 的任何位置偏移 k ∈ { 1 , … , n } k\in\left\{1,\dots,n\right\} k{1,,n} 成立。

为什么满足这个公式,Positional Encoding向量就可以表示相对次序?

这里就谈到了对线性变换的理解,矩阵对向量的线性变换,其实是施加在其基底上的变换,而新的向量是关于新的基底的线性组合,与原来的向量关于原来的基底的线性组合,是一样的。是不是就可以对应上:新的向量 P E → p o s + k \overrightarrow{PE}_{pos+k} PE pos+k 是关于新的基底的线性组合,与原来的向量 P E → p o s \overrightarrow{PE}_{pos} PE pos 关于原来的基底的线性组合,是一样的。也就是说,他们之间的线性变换不受这个位置为 p o s pos pos 的token在序列中的绝对位置的影响,这个线性变换矩阵 T ( k ) \boldsymbol{T}^{(k)} T(k) 可以表示出了不同距离的token的相对关系。

更多关于线性变换的直观理解:https://blog.csdn.net/xiaoyink/article/details/90705106

2.那论文公式满足这个相对次序关系的表示吗?

要使 T ( k ) ⋅ P E → p o s = P E → p o s + k \boldsymbol{T}^{(k)} \cdot\overrightarrow{PE}_{pos} = \overrightarrow{PE}_{pos+k} T(k)PE pos=PE pos+k,需要使 T ( k ) \boldsymbol{T}^{(k)} T(k)不依赖于 p o s pos pos

证明:

T ( k ) \boldsymbol{T}^{(k)} T(k) 是一个 2 × 2 2 \times 2 2×2矩阵, T ( k ) = [ u 1 v 1 u 2 v 2 ] \boldsymbol{T}^{(k)} = \begin{bmatrix} u_1 & v_1 \\ u_2 & v_2 \end{bmatrix} T(k)=[u1u2v1v2]

T ( k ) ⋅ P E → p o s = P E → p o s + k \boldsymbol{T}^{(k)} \cdot\overrightarrow{PE}_{pos} = \overrightarrow{PE}_{pos+k} T(k)PE pos=PE pos+k可写作:
[ u 1 v 1 u 2 v 2 ] . [ sin ⁡ ( ω k ⋅ p o s ) cos ⁡ ( ω k ⋅ p o s ) ] = [ sin ⁡ ( ω k ⋅ ( p o s + ϕ ) ) cos ⁡ ( ω k ⋅ ( p o s + ϕ ) ) ] % <![CDATA[ \begin{bmatrix} u_1 & v_1 \\ u_2 & v_2 \end{bmatrix} .\begin{bmatrix} \sin(\omega_k \cdot pos) \\ \cos(\omega_k \cdot pos) \end{bmatrix} = \begin{bmatrix} \sin(\omega_k \cdot (pos + \phi)) \\ \cos(\omega_k \cdot (pos + \phi)) \end{bmatrix} %]]> [u1u2v1v2].[sin(ωkpos)cos(ωkpos)]=[sin(ωk(pos+ϕ))cos(ωk(pos+ϕ))]
等式右边使用三角函数正余弦公式,可化为:
[ u 1 v 1 u 2 v 2 ] . [ sin ⁡ ( ω k ⋅ p o s ) cos ⁡ ( ω k ⋅ p o s ) ] = [ sin ⁡ ( ω k ⋅ p o s ) cos ⁡ ( ω k ⋅ ϕ ) + cos ⁡ ( ω k ⋅ p o s ) sin ⁡ ( ω k ⋅ ϕ ) cos ⁡ ( ω k ⋅ p o s ) cos ⁡ ( ω k ⋅ ϕ ) − sin ⁡ ( ω k ⋅ p o s ) sin ⁡ ( ω k ⋅ ϕ ) ] % <![CDATA[ \begin{bmatrix} u_1 & v_1 \\ u_2 & v_2 \end{bmatrix} .\begin{bmatrix} \sin(\omega_k \cdot pos) \\ \cos(\omega_k \cdot pos) \end{bmatrix} = \begin{bmatrix} \sin(\omega_k \cdot pos)\cos(\omega_k \cdot\phi) + \cos(\omega_k \cdot pos)\sin(\omega_k \cdot\phi) \\ \cos(\omega_k \cdot pos)\cos(\omega_k \cdot\phi) - \sin(\omega_k \cdot pos)\sin(\omega_k \cdot \phi) \end{bmatrix} %]]> [u1u2v1v2].[sin(ωkpos)cos(ωkpos)]=[sin(ωkpos)cos(ωkϕ)+cos(ωkpos)sin(ωkϕ)cos(ωkpos)cos(ωkϕ)sin(ωkpos)sin(ωkϕ)]

可以得到以下两个等式:
u 1 sin ⁡ ( ω k ⋅ p o s ) + v 1 cos ⁡ ( ω k ⋅ p o s ) =      cos ⁡ ( ω k ⋅ ϕ ) sin ⁡ ( ω k ⋅ p o s ) + sin ⁡ ( ω k ⋅ ϕ ) cos ⁡ ( ω k ⋅ p o s ) u 2 sin ⁡ ( ω k ⋅ p o s ) + v 2 cos ⁡ ( ω k ⋅ p o s ) = − sin ⁡ ( ω k ⋅ ϕ ) sin ⁡ ( ω k ⋅ p o s ) + cos ⁡ ( ω k ⋅ ϕ ) cos ⁡ ( ω k ⋅ p o s ) u_1 \sin(\omega_k \cdot pos) + v_1 \cos(\omega_k \cdot pos) = \ \ \ \ \cos(\omega_k \cdot\phi)\sin(\omega_k \cdot pos) + \sin(\omega_k \cdot\phi)\cos(\omega_k \cdot pos) \\ u_2 \sin(\omega_k \cdot pos) + v_2 \cos(\omega_k \cdot pos) = - \sin(\omega_k \cdot\phi)\sin(\omega_k \cdot pos) + \cos(\omega_k \cdot\phi)\cos(\omega_k \cdot pos) u1sin(ωkpos)+v1cos(ωkpos)=    cos(ωkϕ)sin(ωkpos)+sin(ωkϕ)cos(ωkpos)u2sin(ωkpos)+v2cos(ωkpos)=sin(ωkϕ)sin(ωkpos)+cos(ωkϕ)cos(ωkpos)

求解上述方程,得到:

T ϕ , k = [      cos ⁡ ( ω k . ϕ ) sin ⁡ ( ω k . ϕ ) − sin ⁡ ( ω k . ϕ ) cos ⁡ ( ω k . ϕ ) ] T_{\phi,k} = \begin{bmatrix} \ \ \ \ \cos(\omega_k .\phi) & \sin(\omega_k .\phi) \\ - \sin(\omega_k . \phi) & \cos(\omega_k .\phi) \end{bmatrix} Tϕ,k=[    cos(ωk.ϕ)sin(ωk.ϕ)sin(ωk.ϕ)cos(ωk.ϕ)]
T ( k ) \boldsymbol{T}^{(k)} T(k) 不依赖于 p o s pos pos
而且可以发现, T ( k ) \boldsymbol{T}^{(k)} T(k) 跟旋转矩阵很相似。

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Transformer是一种用于处理序列数据的模型架构,它在自然语言处理领域广泛应用于任务如机器翻译、文本生成和情感分析等。它的核心思想是利用自注意力机制来捕捉输入序列不同位置的依赖关系。 Transformer由多个相同层级的编码器和解码器组成。下面我将详细介绍Transformer的结构: 1. 编码器(Encoder):编码器由N个相同的层级堆叠而成,每个层级都包含两个子层级,分别是多头自注意力机制(Multi-Head Self-Attention)和全连接前馈网络(Feed-Forward Neural Network)。 - 多头自注意力机制:自注意力机制能够计算序列每个位置与其他位置的相关度,通过对输入序列进行注意力加权求和来获取每个位置的表示。多头表示模块则是并行地进行多次自注意力计算,以捕捉不同的语义信息。 - 全连接前馈网络:在每个位置的表示上应用两个全连接层,这个前馈神经网络可以帮助模型学习更复杂的非线性变换。 2. 解码器(Decoder):解码器也由N个相同的层级堆叠而成,它除了包括编码器的两个子层级外,还有一个额外的子层级,即编码器-解码器注意力机制(Encoder-Decoder Attention)。解码器通过编码器-解码器注意力机制来获取输入序列的信息,以便更好地生成输出序列。 - 编码器-解码器注意力机制:通过计算输入序列和输出序列之间的相关度,为解码器提供输入序列的上下文信息,以便更好地进行生成。 除了以上主要的结构外,Transformer还引入了一些重要的概念和技术,包括残差连接(Residual Connections)、Layer Normalization(层归一化)和位置编码(Positional Encoding)等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值