赞
踩
提示:以下是本篇文章正文内容
class PositionalEncoding(nn.Module): """位置编码""" def __init__(self, num_hiddens, dropout, max_len=1000): super(PositionalEncoding, self).__init__() self.dropout = nn.Dropout(dropout) # 创建一个足够长的P self.P = torch.zeros((1, max_len, num_hiddens)) X = torch.arange(max_len, dtype=torch.float32).reshape( -1, 1) / torch.pow(10000, torch.arange( 0, num_hiddens, 2, dtype=torch.float32) / num_hiddens) self.P[:, :, 0::2] = torch.sin(X) self.P[:, :, 1::2] = torch.cos(X) def forward(self, X): X = X + self.P[:, :X.shape[1], :].to(X.device) return self.dropout(X)
在位置嵌入矩阵 P \mathbf{P} P中,[行代表词元在序列中的位置,列代表位置编码的不同维度]。
[位置编码]
在处理词元序列时,循环神经网络是逐个的重复地处理词元的,而自注意力则因为并行计算而放弃了顺序操作。
为了使用序列的顺序信息,我们通过在输入表示中添加位置编码(positional encoding)来注入绝对的或相对的位置信息。位置编码可以通过学习得到也可以直接固定得到。接下来,我们描述的是基于正弦函数和余弦函数的固定位置编码
假设输入表示 X ∈ R n × d \mathbf{X} \in \mathbb{R}^{n \times d} X∈Rn×d包含一个序列中 n n n个词元的 d d d维嵌入表示。
位置编码使用相同形状的位置嵌入矩阵
P
∈
R
n
×
d
\mathbf{P} \in \mathbb{R}^{n \times d}
P∈Rn×d输出
X
+
P
\mathbf{X} + \mathbf{P}
X+P,矩阵第
i
i
i行、第
2
j
2j
2j列和
2
j
+
1
2j+1
2j+1列上的元素为:
p
i
,
2
j
=
sin
(
i
1000
0
2
j
/
d
)
,
p
i
,
2
j
+
1
=
cos
(
i
1000
0
2
j
/
d
)
.
其中公式中的i指的是下图中的索引Index of token,它表示的每一个次元的位置索引。j指的是词元中d维度方向把奇数列当作sin函数,偶数列当做cos函数。其中关于为什么要用cos和sin函数来进行位置信息的表示,在下文末尾进行说明讨论。
P
t
P_t
Pt指的是序列中的第T位置或者时间步为T时刻的向量位置编码
最重要的是我们需要这个编码方式可以取得两个方向的编码信息。
1、是在每个词元所经过embeding后在维度上的每个位置( P 00 , P 01 . . . , P 0 d P_{00},P_{01}...,P_{0d} P00,P01...,P0d)的先后信息。
2、是每个词元的先后信息,也就是能体现输入序列的先后顺序的信息
对于邻近的奇偶数列地三角函数之间存在关系,因此在模型每层的特征提取中,模型可以捕捉到这种关系,从而确定邻近维度地前后关系。
s
i
n
2
+
c
o
s
2
=
1
也就是对应的$P_t
s
i
n
2
(
w
k
t
)
+
c
o
s
2
(
w
k
t
)
=
1
对于同一token中较长远的三角函数之间,由上图公式可以看到三角函数频率沿着向量维度递减。因此,它形成了一个几何级数,波长从
2
Π
2Π
2Π到
10000
×
2
Π
10000×2Π
10000×2Π,也就是说在同一个token词元中,编码信息越靠后,对应的三角函数波长有规律地增长,模型也可以捕捉到这种关系,从而得到一个前后关系信息。
在下面的例子中,我们可以看到位置嵌入矩阵的第 6 6 6列和第 7 7 7列对应的三角函数频率高于第 8 8 8列和第 9 9 9列。
第 6 6 6列和第 7 7 7列之间的偏移量(第 8 8 8列和第 9 9 9列相同)是由于正弦函数和余弦函数的交替。第六列的三角函数波长就要大于第七列和后面序列的的波长。
下面是一个对映的热力图:
我们选择这个函数是因为我们假设它可以让模型很容易地通过相对位置来学习,因为对于任何固定的偏移量k, P (Epos+k)可以表示为的线性函数
证明位置编码中相对位置之间的线性关系:有以下三角函和差化积的公式。
sin
(
A
+
B
)
=
sin
A
cos
B
+
cos
A
sin
B
cos
(
A
+
B
)
=
cos
A
cos
B
−
sin
A
sin
B
cos
(
A
−
B
)
=
cos
A
cos
B
+
sin
A
sin
B
cos
(
A
−
B
)
=
cos
A
cos
B
+
sin
A
sin
B
\sin(A + B) = \sin A \cos B + \cos A \sin B \\\cos(A + B) = \cos A \cos B - \sin A \sin B\\ \cos(A - B) = \cos A \cos B + \sin A \sin B \\\cos(A - B) = \cos A \cos B + \sin A \sin B
sin(A+B)=sinAcosB+cosAsinBcos(A+B)=cosAcosB−sinAsinBcos(A−B)=cosAcosB+sinAsinBcos(A−B)=cosAcosB+sinAsinB对于存在一个旋转矩阵
M
∈
R
2
×
2
M \in \mathbb{R}^{2\times2}
M∈R2×2,等于以下旋转矩阵:
M
=
[
u
1
v
1
u
2
v
2
]
M=
继而对于假设任意时间步为t处的位置编码,乘以旋转矩阵
M
M
M,可以得到以下时间步为
t
+
ϕ
t+\phi
t+ϕ处的位置编码
[
u
1
v
1
u
2
v
2
]
.
[
sin
(
ω
k
.
t
)
cos
(
ω
k
.
t
)
]
=
[
sin
(
ω
k
.
(
t
+
ϕ
)
)
cos
(
ω
k
.
(
t
+
ϕ
)
)
]
[
u
1
v
1
u
2
v
2
]
.
[
sin
(
ω
k
.
t
)
cos
(
ω
k
.
t
)
]
=
[
sin
(
ω
k
.
t
)
cos
(
ω
k
.
ϕ
)
+
cos
(
ω
k
.
t
)
sin
(
ω
k
.
ϕ
)
cos
(
ω
k
.
t
)
cos
(
ω
k
.
ϕ
)
−
sin
(
ω
k
.
t
)
sin
(
ω
k
.
ϕ
)
]
% <![CDATA[
ϕ \phi ϕ是指的序列之间的位置的差值,具体说明见内容三。
u
1
=
cos
(
ω
k
.
ϕ
)
v
1
=
sin
(
ω
k
.
ϕ
)
u
2
=
−
sin
(
ω
k
.
ϕ
)
v
2
=
cos
(
ω
k
.
ϕ
)
% <![CDATA[
这里可以得到以下结论:
{
P
E
(
p
o
s
+
ϕ
,
2
i
)
=
P
E
(
p
o
s
,
2
i
)
×
P
E
(
ϕ
,
2
i
+
1
)
+
P
E
(
p
o
s
,
2
i
+
1
)
×
P
E
(
ϕ
,
2
i
)
P
E
(
p
o
s
+
ϕ
,
2
i
+
1
)
=
P
E
(
p
o
s
,
2
i
+
1
)
×
P
E
(
ϕ
,
2
i
+
1
)
−
P
E
(
p
o
s
,
2
i
)
×
P
E
(
ϕ
,
2
i
)
\left.\left\{
我们先假设一个文本序列“I am a robor”,经过token划分和embeding操作后,开始进行位置编码。
设当前位置Pos = 2,那么对于
ϕ
\phi
ϕ=1,,由公式
P
E
(
p
o
s
+
ϕ
,
2
i
)
=
P
E
(
p
o
s
,
2
i
)
×
P
E
(
ϕ
,
2
i
+
1
)
+
P
E
(
p
o
s
,
2
i
+
1
)
×
P
E
(
ϕ
,
2
i
)
PE(pos+\phi,2i)=PE(pos,2i)\times PE(\phi,2i+1)+PE(pos,2i+1)\times PE(\phi,2i)
PE(pos+ϕ,2i)=PE(pos,2i)×PE(ϕ,2i+1)+PE(pos,2i+1)×PE(ϕ,2i)
可以得到 P 30 = P 20 ∗ P 11 + P 21 ∗ P 10 P_{30} = P_{20}*P_{11} + P_{21}*P_{10} P30=P20∗P11+P21∗P10。也就是上图所示的0.1386 = 0.91×0.54-0.84×0.42。这样的隐藏的语义信息能被学习能力强大的模型提取,即使没有直接学到各个句子的关联信息,同时由于每层都有残差连接,将这样的位置信息保留下来让高层提取特征能力更强的深层次网络进行学习。
转自Transformer Architecture: The Positional Encoding
Why are both sine and cosine used?
1. I think a more intuitive explanation of positional embedding is to think about it as a clock (as cos and sin are just concept from unit circle). Every two dimension of the positional embedding just specifies one of the clock’s hand (the .0hour hand, the minute hand, the second hand, for example). Then moving from one position to the next position is just rotating those hands at different frequencies. Thus, without formal proof, it immediately tells you why a rotation matrix exist.
我认为位置嵌入更直观的解释是把它想象成一个时钟(因为cos和sin只是单位圆的概念)。位置嵌入的每两个维度只指定时钟的一个指针(例如,时针、分针、秒针)。然后从一个位置移动到下一个位置只是以不同的频率旋转这些手。因此,在没有正式证明的情况下,它立即告诉你为什么旋转矩阵存在。
2. Personally, I think, only by using both sine and cosine, we can express the sine(x+k) and cosine(x+k) as a linear transformation of sin(x) and cos(x). It seems that you can’t do the same thing with the single sine or cosine. If you can find a linear transformation for a single sine/cosine, please let me know in the comments section.
只有同时使用正弦和余弦,我们才能将sin(x +k)和cos(x +k)表示为sin(x)和cos(x)的线性变换。似乎你不能对单个正弦或余弦函数做同样的事情。
A Gentle Introduction to Positional Encoding in Transformer Models, Part 1
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。