Byte Pair Encoding

发布时间 2023-05-06 11:25:22作者: 乐乐章

2. Byte Pair Encoding原理

在NLP模型中,输入通常是一个句子,例如 "I went to New York last week." ,一句话中包含很多单词(token)。传统的做法是将这些单词以空格进行分隔,例如['i', 'went', 'to', 'New', 'York', 'last', 'week']。然而这种做法存在很多问题,例如模型无法通过walked, walking,walker之间的关系学到talked,talking,talker之间的关系。如果我们能使用将一个token分成多个subtokens,上面的问题就能很好的解决。

现在性能比较流行的NLP模型,例如GPT、BERT、RoBERTa等,在数据预处理的时候都会有WordPiece的过程,其主要的实现方式就是BPE(Byte-Pair Encoding)。具体来说,例如['loved', 'loving', 'loves']这三个单词。其实本身的语义都是"爱"的意思,但是如果我们以词为单位,那它们就算不一样的词,在英语中不同后缀的词非常的多,就会使得词表变的很大,训练速度变慢,训练的效果也不是太好。BPE算法通过训练,能够把上面的3个单词拆分成["lov","ed","ing","es"]几部分,这样可以把词的本身的意思和时态分开,有效的减少了词表的数量。算法流程如下:

  1. 设定最大subwords个数
  2. 将所有单词拆分为单个字符,并在最后添加一个停止符</w>,同时标记出该单词出现的次数。例如,"low"这个单词出现了5次,那么它将会被处理为{'l o w </w>': 5}
  3. 统计每一个连续字节对的出现频率,选择最高频者合并成新的subword
  4. 重复第3步直到达到第1步设定的subwords词表大小或下一个最高频的字节对出现频率为1

停止符</w>的意义在于表示subword是词后缀。举例来说:st不加</w>可以出现在词首,如st ar;加了</w>表明改字词位于词尾,如wide st</w>,二者意义截然不同。

举例来说:

原始词表 
{'l o w e r </w>': 2, 'n e w e s t </w>': 6, 'w i d e s t </w>': 3, 'l o w </w>': 5}

Step1:

出现最频繁的序列 
('e', 's') 9
合并最频繁的序列后的词表
 {'n e w es t </w>': 6, 'l o w e r </w>': 2, 'w i d es t </w>': 3, 'l o w </w>': 5}

Step2:

出现最频繁的序列
 ('es', 't') 9
合并最频繁的序列后的词表 
{{'n e w est </w>': 6, 'l o w e r </w>': 2, 'w i d est </w>': 3, 'l o w </w>': 5}

Step3:

出现最频繁的序列
 ('est', '</w>') 9
合并最频繁的序列后的词表
 {'w i d est</w>': 3, 'l o w e r </w>': 2, 'n e w est</w>': 6, 'l o w </w>': 5}

Step4:

出现最频繁的序列 
('l', 'o') 7
合并最频繁的序列后的词表
 {'w i d est</w>': 3, 'lo w e r </w>': 2, 'n e w est</w>': 6, 'lo w </w>': 5}

Step5:

出现最频繁的序列 
('lo', 'w') 7
合并最频繁的序列后的词表 
{'w i d est</w>': 3, 'low e r </w>': 2, 'n e w est</w>': 6, 'low </w>': 5}

Step6:

出现最频繁的序列
 ('n', 'e') 6
合并最频繁的序列后的词表 
{'w i d est</w>': 3, 'low e r </w>': 2, 'ne w est</w>': 6, 'low </w>': 5}

Step7:

出现最频繁的序列 
('ne', 'w') 6
合并最频繁的序列后的词表 
{'w i d est</w>': 3, 'low e r </w>': 2, 'new est</w>': 6, 'low </w>': 5}

Step8:

出现最频繁的序列
 ('new', 'est</w>') 6
合并最频繁的序列后的词表 
{'w i d est</w>': 3, 'low e r </w>': 2, 'newest</w>': 6, 'low </w>': 5}

Step9:

出现最频繁的序列 
('low', '</w>') 5
合并最频繁的序列后的词表 
{'w i d est</w>': 3, 'low e r </w>': 2, 'newest</w>': 6, 'low</w>': 5}

Step10:

出现最频繁的序列
 ('w', 'i') 3
合并最频繁的序列后的词表 
{'wi d est</w>': 3, 'newest</w>': 6, 'low</w>': 5, 'low e r </w>': 2}

Step11:

出现最频繁的序列
 ('wi', 'd') 3
合并最频繁的序列后的词表 
{'wid est</w>': 3, 'newest</w>': 6, 'low</w>': 5, 'low e r </w>': 2}

Step12:

出现最频繁的序列
 ('wid', 'est</w>') 3
合并最频繁的序列后的词表 
{'widest</w>': 3, 'newest</w>': 6, 'low</w>': 5, 'low e r </w>': 2}

Step13:

出现最频繁的序列
 ('low', 'e') 2
合并最频繁的序列后的词表 
{'widest</w>': 3, 'newest</w>': 6, 'low</w>': 5, 'lowe r </w>': 2}

Step14:

出现最频繁的序列
 ('lowe', 'r') 2
合并最频繁的序列后的词表 
{'widest</w>': 3, 'newest</w>': 6, 'low</w>': 5, 'lower </w>': 2}

Step15: