在看本文前最好先了解Self Attention,这样会更容易理解。

为什么需要Postional Encoding?

因为在使用Self Attention时,它是两两单词计算相似度得到一个权重,也就是忽略了位置信息,或者说时序信息。举例来说:“我爱你”和“你爱我”的含义是不同的,但是通过Self Attention计算得到的结果是相同的。

因此需要想一个办法,让计算得到的Attention Value中包含一定的位置信息(时序信息)。因此就提出了Positional Encoding,用于表示位置信息的编码,让网络能够知道每个词的位置和彼此的顺序。

总的来说,Positional Encoding的功能就是让网络知道每个词的位置和彼此的顺序。

Positional Encoding如何让网络知道位置信息的?

这里先不讲Positional Encoding的计算公式,现在先知道它的就是和词向量维度相同的向量。

img

上图就是实现过程,从下往上看,很直观。

首先,现将输入的单词Embedding为词向量,得到$x_1,x_2,x_3$;然后加上对应的Positional Encoding $t_1,t_2,t_3$;此时得到的$x_1’,x_2’,x_3’$就是在原始输入的基础上包含了位置信息的词向量。此时利用这样的输入矩阵去进行Self Attention计算计算得出的结果当然也会包含有位置信息。

即得出公式: $X = Embedding+Positional \; Embedding$

如何得到Positional Encoding?

此时应处Positional Encoding的计算公式(PE即为Positional Encoding):

其中$pos$表示当前计算单词的位置,$i$也表示当前计算单词的位置(但其功能只是为了区分当前是奇数位还是偶数位),$d_{model}$表示整个位置向量的维度(长度)。

根据公式理解:如果是偶数位($2i$),那么位置编码使用$\sin$函数计算,如果是奇数位($2i+1$),那么位置编码使用$\cos$函数计算。可以发现函数内部的值是相同的,我们可以看成$P$,这样容易理解一点。

即又可以将上述公式转换为如下更好理解的形式:

这里可以提一下$d_{model}$​是和词向量整体维度有关,一般取512和128比较多。

计算出了每个位置的Positional Encoding就可以和Embedding相加得到输入了,如下图:

img

Positional Encoding如何表示位置信息?

上面引出的是位置编码的计算,可以发现,每个位置的位置编码都是固定的,与实际的输入没有关系(因为参与计算的参数只有$pos$)。那么它是如何表示前后的位置关系的呢?

这就要提到使用三角函数的巧妙之处了,上高中就学过和角公式:

根据这个公式,我们可以得到PE也满足这样的关系:

其中$pos_1$表示单词1的位置,$pos_2$表示单词2的位置,$pos_1+pos_2$表示由二者位置计算出的单词3的位置,即新的位置的单词。上述公式就描述了这三个单词的关系,即$pos_1+pos_2$处的单词3是单词1和单词2的位置信息的线性组合。这样就记录了单词1、单词2、单词3的位置信息。

还是拿句子”我爱你”举例:$pos_1=1=$我;$pos_2=2=$爱;$pos_1+pos_2=1+2=3=$你。

因为3为奇数,那么$2i+1=3 \rightarrow i = 1$

总之,这样就将某个单词的位置信息表示为其他位置信息的线性组合,利用这样的线性组合来表达不同位置之间的相对位置信息。