文章来源 | 恒源云社区
原文地址 | BPE 算法详解
原文作者 | Mathor
Byte Pair Encoding
在NLP模型中,输入通常是一个句子,例如"I went to New York last week."
,一句话中包含很多单词(token)。传统的做法是将这些单词以空格进行分隔,例如['i', 'went', 'to', 'New', 'York', 'last', 'week']
。然而这种做法存在很多问题,例如模型无法通过old, older, oldest
之间的关系学到smart, smarter, smartest
之间的关系。如果我们能使用将一个token分成多个subtokens,上面的问题就能很好的解决。本文将详述目前比较常用的subtokens算法——BPE(Byte-Pair Encoding)
现在性能比较好一些的NLP模型,例如GPT、BERT、RoBERTa等,在数据预处理的时候都会有WordPiece的过程,其主要的实现方式就是BPE(Byte-Pair Encoding)。具体来说,例如['loved', 'loving', 'loves']
这三个单词。其实本身的语义都是"爱"的意思,但是如果我们以词为单位,那它们就算不一样的词,在英语中不同后缀的词非常的多,就会使得词表变的很大,训练速度变慢,训练的效果也不是太好。BPE算法通过训练,能够把上面的3个单词拆分成["lov","ed","ing","es"]
几部分,这样可以把词的本身的意思和时态分开,有效的减少了词表的数量。算法流程如下:
- 设定最大subwords个数 V V V
- 将所有单词拆分为单个字符,并在最后添加一个停止符
</w>
,同时标记出该单词出现的次数。例如,"low"
这个单词出现了5次,那么它将会被处理为{'l o w </w>': 5}
- 统计每一个连续字节对的出现频率,选择最高频者合并成新的subword
- 重复第3步直到达到第1步设定的subwords词表大小或下一个最高频的字节对出现频率为1
例如
{'l o w </w>': 5, 'l o w e r </w>': 2, 'n e w e s t </w>': 6, 'w i d e s t </w>': 3}
出现最频繁的字节对是** e
和s
**,共出现了6+3=9次,因此将它们合并
{'l o w </w>': 5, 'l o w e r </w>': 2, 'n e w es t </w>': 6, 'w i d es t </w>': 3}
出现最频繁的字节对是** es
和t
**,共出现了6+3=9次,因此将它们合并
{'l o w </w>': 5, 'l o w e r </w>': 2, 'n e w est </w>': 6, 'w i d est </w>': 3}
出现最频繁的字节对是** est
和</w>
**,共出现了6+3=9次,因此将它们合并
{'l o w </w>': 5, 'l o w e r </w>': 2, 'n e w est</w>': 6, 'w i d est</w>': 3}
出现最频繁的字节对是** l
和o
**,共出现了5+2=7次,因此将它们合并
{'lo w </w>': 5, 'l