【位置编码】【Positional Encoding】直观理解位置编码!把位置编码想象成秒针!
你们有没有好奇过为啥位置编码非得长成这样:
P E ( p o s , 2 i ) = s i n ( p o s 1000 0 2 i / d m o d e l ) P E ( p o s , 2 i + 1 ) = c o s ( p o s 1000 0 2 i / d m o d e l ) PE(pos,2i)=sin(\frac{pos}{10000^{2i/d_{model}}})\\ PE(pos,2i+1)=cos(\frac{pos}{10000^{2i/d_{model}}}) PE(pos,2i)=sin(100002i/dmodelpos)PE(pos,2i+1)=cos(100002i/dmodelpos)
- 为什么位置编码一定要分为奇数和偶数分别考虑?
- 为什么又要有sin又要有cos?
这里提供一个直观的理解方案,位置编码想象成秒针可以帮助你轻松理解为什么要如此编码。
【转载注明出处】
为了解释位置编码,我们先考虑下面的场景:
不一样的秒表
假设我们手上有三个不一样的“秒表”,这些秒表长这样:
这三个秒表都只有一个指针,不同的是第一个秒表的指针10s转一圈,第二个秒表的指针100s转一圈,第三个秒表1000s转一圈。
现在,考虑一个问题:
Q: 如果我在 0 0 0秒时同时按下这3个秒表,问在 t t t秒时这三个表的指针转过的角度 ϕ 1 , ϕ 2 , ϕ 3 \phi_1,\phi_2,\phi_3 ϕ1,ϕ2,ϕ3分别是多少?
这个答案很简单!
A: 我们可以知道,第一个表每秒钟转 2 π / 10 2\pi/10 2π/10,第二个表每秒钟转 2 π / 100 2\pi/100 2π/100,第三个表每秒钟转 2 π / 1000 2\pi/1000 2π/1000,因此:
ϕ 1 = t × 2 π / 10 , ϕ 2 = t × 2 π / 100 , ϕ 3 = t × 2 π / 1000 \phi_1=t\times2\pi/10,\phi_2=t\times2\pi/100,\phi_3=t\times2\pi/1000 ϕ1=t×2π/10,ϕ2=t×2π/100,ϕ3=t×2π/1000
从时间到角度
现在,其实我们可以把每个时间 t t t对应成一个坐标:
t → ( ϕ 1 , ϕ 2 , ϕ 3 ) t\rightarrow(\phi_1,\phi_2,\phi_3) t→(ϕ1,ϕ2,ϕ3)同样的这样的一个坐标也能唯一的对应一个时间!(如果第三个秒表没有转完完整一圈的话)
从角度到坐标
进一步,我们还可以用三角函数来表达一个角度 ϕ \phi ϕ,比如在0到2 π \pi π的范围内 ( s i n ( ϕ ) , c o s ( ϕ ) ) (sin(\phi),cos(\phi)) (sin(ϕ),cos(ϕ))这个坐标可以唯一确定 ϕ \phi ϕ。这个坐标也就是指针的端点的平面坐标(指针长度为1的话):
到目前为止我们就得到了这样的一个变化过程:
t → ( ϕ 1 , ϕ 2 , ϕ 3 ) → ( s i n ( ϕ 1 ) , c o s ( ϕ 1 ) , s i n ( ϕ 2 ) , c o s ( ϕ 2 ) , s i n ( ϕ 3 ) , c o s ( ϕ 3 ) ) t\rightarrow(\phi_1,\phi_2,\phi_3)\\\rightarrow(sin(\phi_1),cos(\phi_1),sin(\phi_2),cos(\phi_2),sin(\phi_3),cos(\phi_3)) t→(ϕ1,ϕ2,ϕ3)→(sin(ϕ1),cos(ϕ1),sin(ϕ2),cos(ϕ2),sin(ϕ3),cos(ϕ3))
因此我们就可以反过来,用这些角度表达时间 t t t:
( s i n ( ϕ 1 ) , c o s ( ϕ 1 ) , s i n ( ϕ 2 ) , c o s ( ϕ 2 ) , s i n ( ϕ 3 ) , c o s ( ϕ 3 ) ) → t (sin(\phi_1),cos(\phi_1),sin(\phi_2),cos(\phi_2),sin(\phi_3),cos(\phi_3))\rightarrow t (sin(ϕ1),cos(ϕ1),sin(ϕ2),cos(ϕ2),sin(ϕ3),cos(ϕ3))→t其中 ϕ 1 = t × 2 π / 10 , ϕ 2 = t × 2 π / 100 , ϕ 3 = t × 2 π / 1000 \phi_1=t\times2\pi/10,\phi_2=t\times2\pi/100,\phi_3=t\times2\pi/1000 ϕ1=t×2π/10,ϕ2=t×2π/100,ϕ3=t×2π/1000
位置编码
在上述的例子中,令时间 t ← p o s t\leftarrow pos t←pos。且我们有 d m o d e l / 2 d_{model}/2 dmodel/2个秒表,第 i i i个秒表转一圈的需要的时间是 2 π × 1000 0 2 i / d m o d e l 2\pi\times 10000^{2i/d_{model}} 2π×100002i/dmodel,那么经过时间 p o s pos pos之后第 i i i个秒表的角度 ϕ i = p o s × 2 π 2 π × 1000 0 2 i / d m o d e l = p o s 1000 0 2 i / d m o d e l \phi_i=pos\times \frac{2\pi}{2\pi\times10000^{2i/d_{model}}}=\frac{pos}{10000^{2i/d_{model}}} ϕi=pos×2π×100002i/dmodel2π=100002i/dmodelpos
那么我们同样可以用这 d m o d e l / 2 d_{model}/2 dmodel/2个秒表的端点坐标表达 p o s pos pos
( s i n ( ϕ 1 ) , c o s ( ϕ 1 ) , ⋯ ) → p o s (sin(\phi_1),cos(\phi_1),\cdots)\rightarrow pos (sin(ϕ1),cos(ϕ1),⋯)→pos
可以直接注意到,上式就是我们提到的位置编码!
P E ( p o s , 2 i ) = s i n ( p o s 1000 0 2 i / d m o d e l ) P E ( p o s , 2 i + 1 ) = c o s ( p o s 1000 0 2 i / d m o d e l ) PE(pos,2i)=sin(\frac{pos}{10000^{2i/d_{model}}})\\ PE(pos,2i+1)=cos(\frac{pos}{10000^{2i/d_{model}}}) PE(pos,2i)=sin(100002i/dmodelpos)PE(pos,2i+1)=cos(100002i/dmodelpos) 一摸一样!