(超易懂) Transformer位置编码设计原理详解

写在前面

(本文的灵感和部分图片来自Transformer的位置编码详解, 详解自注意力机制中的位置编码

相信大家第一次看到Attention All You Need这篇文章时,一定被这个位置编码公式震撼过:
在这里插入图片描述

啥?这都咋想出来的,有种拉马努金造公式的美感
但如果我们从头开始,一步一步去设计一个位置编码,或许这个公式的思想并没有那么复杂

位置编码如何跟语义向量配合

最直接的想法时把位置编码向量和语义嵌入向量拼起来,但是Transformer的做法是把它俩直接相加。这个原因咱们放在文章尾部介绍,现在我们把这个当成前提,来讨论怎么设计位置编码

什么是一个好的位置编码

一个好的位置编码,要满足着两个条件:

  • 值要有界:位置编码的值必须有界,出现极端的大数值会导致训练不稳定。而且后面要跟语义向量相加,会喧宾夺主
  • 唯一:每个词的位置编码必须唯一,并且编码差异要够大,这样transformer才能更好地区分不同的位置

最简单的想法:单值,单调递增

如果给第一个词编码为0,第二个词编码为1,以此类推,随着词位置往后,这个编码一定是无界的,越来越大

改进:用有界的单调函数?

那我们改进一下,用某种有界的单调函数,比如 ( k + 1 ) x ( x + k ) \frac{(k+1)x}{(x+k)} (x+k)(k+1)x,会发现x趋近于无穷时,相邻两个位置的编码值无限接近,这显然不利于区分两个位置
在这里插入图片描述

于是我们抛弃单调函数,用周期函数怎么样呢?

改进:用周期函数

问题很明显,周期函数过了一个周期它会重复啊!那在transformer眼里这两个词位置就一样了,这显然不行

改进:多维,周期函数,每个维度频率不一样

但如果我们使用多维向量,每个维度是不同频率的周期函数。这样还会重复吗
我们常见的二进制其实有这个特点
0:000
1:001
2:010
3:011
4:100
5:101
6:110
7:111

我们竖着看:
第一列:0000000011111111
第二列:00001111 00001111
第三列:0011 0011 0011 0011
第三列:01 01 01 01 01 01 01 01
这不就是周期成等比数列的周期函数嘛!并且二进制表示一个数字是唯一的(假设可以使用无限位二进制),不会出现两个数字编码相同,要的就是这个感觉。

多维周期函数的细节

我们可以模仿二进制,把不同维度频率设为等比数列,但公比设置为多少呢?
我们发现,因为公比小于1,如果维度数 d k d_k dk太大的话,最后几个维度的频率将相当低。所以我们根据维度数 d k d_k dk自动调节公比, d k d_k dk越大,公比越小,以此来控制频率下降速度: 1 1000 0 1 d \frac{1}{10000^{\frac{1}{d}}} 10000d11

第i个维度频率公式:
ω i = ( 1 1000 0 1 d ) i      1 ≤ i ≤ d k \omega_i = (\frac{1}{10000^{\frac{1}{d}}})^i~~~~1\le {i} \le{d_k} ωi=(10000d11)i    1idk

不过,如果只用01,频率随着维度增加下降的非常剧烈,而频率太低会导致相邻词的该维度的位置编码值几乎一样,那就区分不开位置了!用浮点数域的三角函数就可以延缓频率的下降。最简单的想法就是用sin函数,t代表词的位置index,i代表维度index
p ( t , i ) = s i n ( 1 1000 0 1 d i t )        1 ≤ i ≤ d k p(t,i)=sin(\frac{1}{10000^{\frac{1}{d}}}^i t) ~~~~~~1\le{i}\le{d_k} p(t,i)=sin(10000d11it)      1idk

改进:一个频率用两次,用sin和cos交替

不过呢,transformer一个频率用了两次,先用sin,后用cos
p ( t , i ) = { s i n ( 1 1000 0 1 d k t )          i = 2 k c o s ( 1 1000 0 1 d k t )          i = 2 k + 1    1 ≤ i ≤ d k p(t,i) = \begin{cases} sin(\frac{1}{10000^{\frac{1}{d}}}^k t) ~~~~~~~~i =2k \\ cos(\frac{1}{10000^{\frac{1}{d}}}^k t) ~~~~~~~~i=2k+1\\ \end{cases} ~~1\le{i}\le{d_k} p(t,i)= sin(10000d11kt)        i=2kcos(10000d11kt)        i=2k+1  1idk
为啥?原文里说:“我们猜测这将允许模型轻松地学习到由相对位置获得的attention,因为对于任何固定的偏移量k, P E t + k PE_{t+k} PEt+k可以表示为 P E t PE_{t} PEt 的线性函数”。也就是说纯sin的PE是没法满足上面说的线性变换的

如果是PE是纯sin函数组成的(为了简化讨论,假设 d k d_k dk=2)
( s i n ( t + k ) s i n ( t + k ) )   = M ( s i n ( t ) s i n ( t ) ) \begin{pmatrix} sin(t+k) \\ sin(t+k) \end{pmatrix} ~= M \begin{pmatrix} sin(t) \\ sin(t) \end{pmatrix} (sin(t+k)sin(t+k)) =M(sin(t)sin(t))
这个M肯定不是线性的。但如果PE是sin和cos交替
( s i n ( t + k ) c o s ( t + k ) )   = M ( s i n ( t ) c o s ( t ) ) \begin{pmatrix} sin(t+k) \\ cos(t+k) \end{pmatrix} ~= M \begin{pmatrix} sin(t) \\ cos(t) \end{pmatrix} (sin(t+k)cos(t+k)) =M(sin(t)cos(t))
可以求出来M是一个常数矩阵,代表着一个线性的变换(其实是旋转哦!)

M = [ cos ⁡ ( w i k ) sin ⁡ ( w i k ) − sin ⁡ ( w i k ) cos ⁡ ( w i k ) ] M = \begin{bmatrix} \cos(w_i k) & \sin(w_i k) \\ -\sin(w_i k) & \cos(w_i k) \end{bmatrix} M=[cos(wik)sin(wik)sin(wik)cos(wik)]

最终方案

在这里插入图片描述
t是词汇位置索引,i是维度索引

可以看出,对于同一维度(也就是下图中的一列),位置编码是一个正弦函数在整数处的采样。不同维度时正弦函数的频率不同,维度越高频率越慢

  • 每一列都是标准sin函数(或者cos函数)的整数采样
  • 相邻两列是频率相同的sin和cos,比如0列和1列,2列和3列
  • 从左到右频率越来越慢,下图可以看出感觉后面的列被拉长了
    在这里插入图片描述

为什么位置编码是和词嵌入相加而不是将二者拼接起来?

我们可以观察到,位置编码向量中前几个维度频率大,编码值变化比较剧烈,因此是储存位置信息的主力军。后几个维度就没那么重要了

国外有人讨论这个问题,并做了一些实验。发现Transformer经过训练,在编码嵌入向量的时候,将语义信息往后面的维度放。也就是说,虽然没有直接把位置向量和语义向量拼接,但是进行了隐式拼接
在这里插入图片描述

参考网站
Why add positional embedding instead of concatenate?
Discussion:Positional Encoding in Transformer

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值