目录
2 位置编码Positional Encoding(PE):
1 切分方式的变化:
1.1 传统的切分方式:
在RNN中,我们一般以空格作为分隔符的方式进行简单的单词划分,但是这样子的缺点就是
- 词表维度过高,也即词表中词的数量过多;
- 另一个就是无法捕捉到单词之间的联系(例如同一个单词的单数和复数会对应不一样的ID(embedding)。
1.2 byte pair encoding(BPE):
- 首先将语料库中的单词切分为一个个字母;
- 然后统计预料库中每一个Bigram(相邻2个)出现的次数;
- 接着把Bigram出现频率最高的词抽象为一个全新的词N加入词表,同时从原词表中剔除只在N中出现的词;
- 不断重复上述2-3过程,直到词表数量达到一定规模,进而实现了将该语料库划分为一个个高质量的token。
1.3 BPE的其余优点:
BPE的出现也可以很好地解决在NLP中经常出现的OOV问题(out of vocabulary)(在输入文本中出现了一些在词表中没有出现过的词),这就导致模型无法理解这个新单词的含义,模型也无法找到这个对应的向量表示,这个时候往往会使用一个UNK的符号来代替。
比如对于单词“lowest",如果在现有词表中没有这个单词的话,通过BPE我们可以将其分解为low和est,这样就实现了对新的单词的一个表示,同样通过这样一种方式可以让模型学习到这三者之间的关系,这样的关系也可以泛化到像其他的单词中,比如smart和smartest。
2 位置编码Positional Encoding(PE):
2.1 提出背景:
为了不同于RNN中顺序执行的方式(无法通过顺序执行来建模每个单词的位置关系),我们需要引入位置编码,否则不同位置的相同单词其实是没有办法区分的。
2.2 实现方式:
在原有的embedding(嵌入层)上加入一个位置向量,使得不同位置的单词具备不同的表示。
我们假设BPE后词表中每个词经过embedding之后的向量维度为d,那么其对应的位置编码也需要是一个维度为d的向量。
其中pos表示当前token在句子中的位置(它是一个从0到序列长度的一个数(注意这里的序列长度是指语句序列,而非词表的维度)) ,i则是从0-d/2的一个数(表示当前位置在embedding后的向量维度中的index);
观察上式,可以发现embedding中的偶数位置是一个正弦函数,奇数位置是一个余弦函数。
通过这样的操作,我们可以发现:
- token的一个具体的位置和它的编码向量其实是一一对应的。
- 位置编码是有界的,因为三角函数是有界的。
- 不同位置的位置编码的向量的差别取决于它们之间的相对位置。
2.3 一个可视化例子:
token是10个,词表维度是64;
- 可以看到对于同一个维度(竖线),它其实是一个周期的正弦或者余弦函数(注意是或,也就是说要么是正弦,要么是余弦,而不能在同一个维度中两者兼有,对应上述公式就是pos不同,i相同);
- 而相同位置(横线),它其实是一个不同周期的正弦和余弦函数(注意是和,也就是说既包括正弦,也包括余弦,对应上述公式就是pos相同,i不同)
2.4 输出(BPE+PE):
我们最终输入到transformer block(主体部分)中的其实就是BPE后的向量和PE后的向量按位置相加得到的一个向量