transfomer的位置编码

发布时间:2024年01月17日

什么是位置编码

在transformer的encoder和decoder的输入层中,使用了Positional Encoding,使得最终的输入满足:
在这里插入图片描述

input_embedding+=positional_encoding

这里,input_embedding的shape为[n,b,embed_dim],positional_encoding和input_embedding形状一致.

位置编码的作用

Transformer模型抛弃了RNN、CNN作为序列学习的基本模型。循环神经网络本身就是一种顺序结构,天生就包含了词在序列中的位置信息。当抛弃循环神经网络结构,完全采用Attention取而代之,这些词序信息就会丢失,模型就没有办法知道每个词在句子中的相对和绝对的位置信息。因此,有必要把词序信号加到词向量上帮助模型学习这些信息,位置编码(Positional Encoding)就是用来解决这种问题的方法。

位置编码的方法

用整型值标记位置

一种自然而然的想法是,给第一个token标记1,给第二个token标记2…,以此类推。
在这里插入图片描述
这种方法产生了以下几个主要问题:
(1)模型可能遇见比训练时所用的序列更长的序列。不利于模型的泛化。
(2)模型的位置表示是无界的。随着序列长度的增加,位置值会越来越大。

用[0,1]范围标记位置

为了解决无界问题,可以考虑将位置值的范围限制在[0, 1]之内,其中,0表示第一个token,1表示最后一个token。比如有3个token,那么位置信息就表示成[0, 0.5, 1];若有四个token,位置信息就表示成[0, 0.33, 0.69, 1]。
但这样产生的问题是,当序列长度不同时,token间的相对距离是不一样的。例如在序列长度为3时,token间的相对距离为0.5;在序列长度为4时,token间的相对距离就变为0.33。
因此,我们需要这样一种位置表示方式,满足于:
(1)它能用来表示一个token在序列中的绝对位置
(2)在序列长度不同的情况下,不同序列中token的相对位置/距离也要保持一致
(3)可以用来表示模型在训练过程中从来没有看到过的句子长度。

用one-hot编码标记位置

在这里插入图片描述
这种编码的问题是有可能重复,最多可以独立表示2^embed_dim中pos,否在就会重复.

用周期函数(sin)来表示位置

通过纵向观察one-hot编码可以知道,从右到左是一个频率逐渐降低的函数.因此考虑使用三角函数去模拟这个过程.
设每一行从左到右为[0,…i…,embed_dim-1],每一列从上到下为[0,…t…,len]
则上述编码过程可以表示为函数:
P E = [ P E ( t , 0 ) , . . . P E ( t , i ) . . . , P E ( t , e m b e d d i m ? 1 ) ] = [ s i n ( 1 2 0 t ) , . . . s i n ( 1 2 i t ) . . . , s i n ( 1 2 e m b e d d i m ? 1 t ) ] PE=[PE(t,0),...PE(t,i)...,PE(t,embed_{dim}-1)]=[sin(\frac{1}{2^{0}}t),...sin(\frac{1}{2^{i}}t)...,sin(\frac{1}{2^{embed_{dim}-1}}t)] PE=[PE(t,0),...PE(t,i)...,PE(t,embeddim??1)]=[sin(201?t),...sin(2i1?t)...,sin(2embeddim??11?t)]
为了使得在固定的embed_dim的范围内,不容易出现重复编码,可以增加sin函数的周期.在transformer的论文中,采用了
P E ( t , i ) = s i n ( w i t ) , 其中 w i = 1 1000 0 i / ( e m b e d d i m ? 1 ) PE(t,i)=sin(w_it),其中w_i=\frac{1}{10000^{i/(embed_{dim}-1)}} PE(t,i)=sin(wi?t),其中wi?=10000i/(embeddim??1)1?
为了可以将某个位置编码通过线性转换到另一个位置编码,即:
P E ( t + δ t ) = T ( δ t ) ? P E ( t ) PE(t+\delta t)=T(\delta t)*PE(t) PE(t+δt)=T(δt)?PE(t)
联想向量空间的旋转转换关系:
( s i n ( t + δ t ) c o s ( t + δ t ) ) = ( c o s ( δ t ) s i n ( δ t ) ? s i n ( δ t ) c o s ( δ t ) ) ? ( s i n ( t ) c o s ( t ) ) (\begin{matrix} sin(t+\delta t)\\cos(t+\delta t)\end{matrix})=(\begin{matrix} cos(\delta t)&sin(\delta t)\\-sin(\delta t)&cos(\delta t) \end{matrix})*(\begin{matrix} sin(t)\\cos(t)\end{matrix}) (sin(t+δt)cos(t+δt)?)=(cos(δt)?sin(δt)?sin(δt)cos(δt)?)?(sin(t)cos(t)?)
使用正余弦交叉的编码
P E = [ P E ( t , 0 ) , . . . , P E ( t , e m b e d d i m ? 1 ) ] = [ s i n ( w 0 t ) , c o s ( w 0 t ) , . . . . , s i n ( w e m b e d d i m 2 ? 1 t ) , c o s ( w e m b e d d i m 2 ? 1 t ) ] PE=[PE(t,0),...,PE(t,embed_{dim}-1)]=[sin(w_0t),cos(w_0t),....,sin(w_{\frac{embed_{dim}}{2}-1}t),cos(w_{\frac{embed_{dim}}{2}-1}t)] PE=[PE(t,0),...,PE(t,embeddim??1)]=[sin(w0?t),cos(w0?t),....,sin(w2embeddim???1?t),cos(w2embeddim???1?t)]
实际使用中可以不用交叉:即
P E = [ P E ( t , 0 ) , . . . , P E ( t , e m b e d d i m ? 1 ) ] = [ s i n ( w 0 t ) , s i n ( w e m b e d d i m 2 ? 1 t ) , . . . . , c o s ( w 0 t ) , c o s ( w e m b e d d i m 2 ? 1 t ) ] PE=[PE(t,0),...,PE(t,embed_{dim}-1)]=[sin(w_0t),sin(w_{\frac{embed_{dim}}{2}-1}t),....,cos(w_0t),cos(w_{\frac{embed_{dim}}{2}-1}t)] PE=[PE(t,0),...,PE(t,embeddim??1)]=[sin(w0?t),sin(w2embeddim???1?t),....,cos(w0?t),cos(w2embeddim???1?t)]
因为本质上cos(0)在位置1还是在位置embed_dim/2没有区别,都是可以通过矩阵变换得到

位置编码可视化:

在这里插入图片描述
位置编码实现及其可视化代码,请移步手撕代码专栏的博客

参考

文章来源:https://blog.csdn.net/zwhdldz/article/details/135633820
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。