Navigation

    Gpushare.com

    • Register
    • Login
    • Search
    • Popular
    • Categories
    • Recent
    • Tags

    Transformer中的Positional Encoding

    语音识别与语义处理领域
    1
    1
    33
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • 155****7220
      155****7220 last edited by

      最近我在学习Transformer结构的时候,发现其中的positional encoding很不好理解,尤其是其中的公式,为什么要这样设计,后来上网收集各种资料,方才理解,遂于此写一篇文章进行记录

      首先你需要知道,Transformer是以字作为输入,将字进行字嵌入之后,再与位置嵌入进行相加(不是拼接,就是单纯的对应位置上的数值进行加和)

      需要使用位置嵌入的原因也很简单,因为Transformer摈弃了RNN的结构,因此需要一个东西来标记各个字之间的时序or位置关系,而这个东西,就是位置嵌入

      One possible solution to give the model some sense of order is to add a piece of information to each word about its position in the sentence. We call this “piece of information”, the positional encoding.

      如果让我们从0开始设计一个Positional Encoding,比较容易想到的第一个方法是取[0,1]之间的数分配给每个字,其中0给第一个字,1给最后一个字,具体公式就是PE=posT−1PE=\frac{pos}{T-1}PE=T−1pos​。这样做的问题在于,假设在较短文本中任意两个字位置编码的差为0.0333,同时在某一个较长文本中也有两个字的位置编码的差是0.0333。假设较短文本总共30个字,那么较短文本中的这两个字其实是相邻的;假设较长文本总共90个字,那么较长文本中这两个字中间实际上隔了两个字。这显然是不合适的,因为相同的差值,在不同的句子中却不是同一个含义

      另一个想法是线性的给每个时间步分配一个数字,也就是说,第一个单词被赋予1,第二个单词被赋予2,依此类推。这种方式也有很大的问题:1. 它比一般的字嵌入的数值要大,难免会抢了字嵌入的「风头」,对模型可能有一定的干扰;2. 最后一个字比第一个字大太多,和字嵌入合并后难免会出现特征在数值上的倾斜

      理想的设计

      理想情况下,位置嵌入的设计应该满足以下条件:

      • 它应该为每个字输出唯一的编码
      • 不同长度的句子之间,任何两个字之间的差值应该保持一致
      • 它的值应该是有界的

      作者设计的位置嵌入满足以上的要求。首先,它不是一个数字,而是一个包含句子中特定位置信息的ddd维向量。其次,这种嵌入方式没有集成到模型中,相反,这个向量是用来给句子中的每个字提供位置信息的,换句话说,我们通过注入每个字位置信息的方式,增强了模型的输入(其实说白了就是将位置嵌入和字嵌入相加,然后作为输入)

      设ttt为一句话中的某个字的位置,pt⃗∈Rd\vec{p_t} \in \mathbb{R}^dpt​​∈Rd表示位置ttt时刻这个词位置嵌入的向量,pt⃗\vec{p_t}pt​​的定义如下
      $$
      \begin{align}
      \vec{p_t}^{(i)} = f(t)^{(i)} & :=
      \begin{cases}
      \sin({\omega_k} . t), & \text{if}\ i = 2k \
      \cos({\omega_k} . t), & \text{if}\ i = 2k + 1
      \end{cases}
      \end{align}
      $$
      其中
      $$
      \omega_k = \frac{1}{10000^{2k / d}}
      $$
      kkk​指的是位置嵌入中维度的下标,为了使得位置嵌入和字嵌入能够相加,因此位置嵌入维度和字嵌入的维度必须相同,所以i∈[0,d)i\in [0, d)i∈[0,d),所以就有k∈[0,d−12)k\in [0, \frac{d-1}{2})k∈[0,2d−1​)

      对于三角函数y=Asin(Bx+C)+Dy=Asin(Bx+C)+Dy=Asin(Bx+C)+D来说,周期是2πB\frac{2\pi}{B}B2π​,频率为B2π\frac{B}{2\pi}2πB​,因此B越大,频率值越大,一个周期内函数图像重复次数越多,波长越短(如果这里的数学知识忘了,可以看这篇文章)

      回到pt⃗\vec{p_t}pt​​的定义中,kkk是越来越大的,因此wkw_kwk​越来越小,所以wk2π\frac{w_k}{2\pi}2πwk​​也越来越小,于是频率随着向量维度下标的递增而递减,频率递减=周期变长。我们计算一下周期最小是2π2\pi2π(k=0k=0k=0时),周期最大是10000⋅2π10000·2\pi10000⋅2π(假设k=d2k=\frac{d}{2}k=2d​时)

      你可以想象下ttt时刻字的位置编码pt⃗\vec{p_t}pt​​是一个包含sin和cos函数的向量(假设ddd可以被2整除)
      $$
      \vec{p_t} = \begin{bmatrix}
      \sin({\omega_0}.t)\
      \cos({\omega_0}.t)\
      \
      \sin({\omega_1}.t)\
      \cos({\omega_1}.t)\
      \
      \vdots\
      \
      \sin({\omega_{\frac{d}{2}-1}}.t)\
      \cos({\omega_{\frac{d}{2}-1}}.t)
      \end{bmatrix}_{d \times 1}
      $$

      直观展示

      你可能想知道sin和cos的组合是如何表示位置信息的?这其实很简单,假设你想用二进制表示一个数字,你会怎么做?
      $$
      \begin{align}
      0: \ \ \ \ \color{orange}{\texttt{0}} \ \ \color{green}{\texttt{0}} \ \ \color{blue}{\texttt{0}} \ \ \color{red}{\texttt{0}} & &
      8: \ \ \ \ \color{orange}{\texttt{1}} \ \ \color{green}{\texttt{0}} \ \ \color{blue}{\texttt{0}} \ \ \color{red}{\texttt{0}} \
      1: \ \ \ \ \color{orange}{\texttt{0}} \ \ \color{green}{\texttt{0}} \ \ \color{blue}{\texttt{0}} \ \ \color{red}{\texttt{1}} & &
      9: \ \ \ \ \color{orange}{\texttt{1}} \ \ \color{green}{\texttt{0}} \ \ \color{blue}{\texttt{0}} \ \ \color{red}{\texttt{1}} \
      2: \ \ \ \ \color{orange}{\texttt{0}} \ \ \color{green}{\texttt{0}} \ \ \color{blue}{\texttt{1}} \ \ \color{red}{\texttt{0}} & &
      2: \ \ \ \ \color{orange}{\texttt{1}} \ \ \color{green}{\texttt{0}} \ \ \color{blue}{\texttt{1}} \ \ \color{red}{\texttt{0}} \
      3: \ \ \ \ \color{orange}{\texttt{0}} \ \ \color{green}{\texttt{0}} \ \ \color{blue}{\texttt{1}} \ \ \color{red}{\texttt{1}} & &
      11: \ \ \ \ \color{orange}{\texttt{1}} \ \ \color{green}{\texttt{0}} \ \ \color{blue}{\texttt{1}} \ \ \color{red}{\texttt{1}} \
      4: \ \ \ \ \color{orange}{\texttt{0}} \ \ \color{green}{\texttt{1}} \ \ \color{blue}{\texttt{0}} \ \ \color{red}{\texttt{0}} & &
      12: \ \ \ \ \color{orange}{\texttt{1}} \ \ \color{green}{\texttt{1}} \ \ \color{blue}{\texttt{0}} \ \ \color{red}{\texttt{0}} \
      5: \ \ \ \ \color{orange}{\texttt{0}} \ \ \color{green}{\texttt{1}} \ \ \color{blue}{\texttt{0}} \ \ \color{red}{\texttt{1}} & &
      13: \ \ \ \ \color{orange}{\texttt{1}} \ \ \color{green}{\texttt{1}} \ \ \color{blue}{\texttt{0}} \ \ \color{red}{\texttt{1}} \
      6: \ \ \ \ \color{orange}{\texttt{0}} \ \ \color{green}{\texttt{1}} \ \ \color{blue}{\texttt{1}} \ \ \color{red}{\texttt{0}} & &
      14: \ \ \ \ \color{orange}{\texttt{1}} \ \ \color{green}{\texttt{1}} \ \ \color{blue}{\texttt{1}} \ \ \color{red}{\texttt{0}} \
      7: \ \ \ \ \color{orange}{\texttt{0}} \ \ \color{green}{\texttt{1}} \ \ \color{blue}{\texttt{1}} \ \ \color{red}{\texttt{1}} & &
      15: \ \ \ \ \color{orange}{\texttt{1}} \ \ \color{green}{\texttt{1}} \ \ \color{blue}{\texttt{1}} \ \ \color{red}{\texttt{1}} \
      \end{align}
      $$
      用二进制表示一个数字太浪费空间了,因此我们可以使用与之对应的连续函数——正弦函数

      参考文献

      • Transformer Architecture: The Positional Encoding
      • 如何理解Transformer论文中的Positional Encoding,和三角函数有什么关系
      • What is the positional encoding in the transformer model?
      1 Reply Last reply Reply Quote 1
      • First post
        Last post