- Tokenizer的种类和区别
Tokenize有三种粒度:
- Word:对于英文等自然语言来说,存在着天然的分隔符;但是对于一些东亚文字包括中文来说,就需要某种分词算法才行。由于长尾现象的存在,词汇表可能会超大。
- Char:词汇表只有最基本的字符。这样做的问题是,由于字符数量太小,我们在为每个字符学习嵌入向量的时候,每个向量就容纳了太多的语义在内,学习起来非常困难。
- Subword:介于字符和单词之间,平衡了词汇量和语义独立性。处理原则是,常用词应该保持原状,生僻词应该拆分成子词以共享token压缩空间。
常用的BPE、WordPiece等都属于Subword的tokenization。
BPE(Byte Pair Encoding)
BPE的原理
BPE每一步都将最常见的一对相邻数据单位替换为该数据中没有出现过的一个新单位,反复迭代直到满足停止条件。
- 首先Pre-tokenization得到所有单词及频次的集合,初始的vocabulary为基础字符。(每个单词末尾会添加</w>来区分词尾和词中)
- 挑选出频次最高的vocab pair,将其合并然后加入到vocabulary中构成新token。
- 将(单词,频次)集合中的单词使用vocabulary更新。
- 重复上述2-3,直到vocab达到要求。
BPE的编码与解码
编码:对于每个空格分开的单词使用merge rule进行贪婪匹配。编码时对于没见过的用
token代替,BPE 只会将不在词汇表中的单个字符 tokenize 为 unknown 。 例如 “bum”,由于”##m” 不在词表中,由此产生的tokenization 是 [“b”, “##u”, “[UNK]”]。 解码:对于每个token,根据是否有</w>加上空格,然后进行拼接。
Byte-level BPE
BPE的一个问题是,如果遇到了unicode,基本字符集可能会很大。一种处理方法是我们以一个字节为一种“字符”,不管实际字符集用了几个字节来表示一个字符。这样的话,基础字符集的大小就锁定在了256。
例如,像GPT-2的词汇表大小为50257 = 256 +
+ 50000 mergers, 是句子结尾的特殊标记。
WordPiece
很多著名的Transformer模型如BERT/DistilBERT都使用了它。
WordPiece的原理。
与BPE一样,WordPiece从一个小的vocab开始学习merge规则。二者的区别在于:WordPiece不是选择最高频的pair,而是选择最大化如下score的一对token。
score(t1,t2) = freq(t12) / (freq(t1)*freq(t2)),freq(t)为t在语料库中出现的频次。
WordPiece的物理意义为:通过将t1和t2合并为t12后,语料库的对数似然的增量最大化。
具体步骤与BPE相似。注意:注意:WordPiece 通过添加前缀(在 BERT 中是 ##)来识别子词,这可以识别一个子词是否是单词的开始。这里通过将前缀添加到单词内的每个字符来拆分的,单词的首字符不添加前缀。WordPiece的编码和解码
编码: 找到词表中能够匹配到的最长的子词,然后对单词进行拆分。当tokenization 无法在词表中找到子词时,整个单词被 tokenize 为 unknown 。 例如 “bum”,由于”##m” 不在词表中,由此产生的tokenization 将只是 [“[UNK]”], 不是 [“b”, “##u”, “[UNK]”]。
解码:与BPE类似,对于有前缀的合并成一个单词,无前缀的加上空格。WordPiece与BPE的区别
- WordPiece 仅保存最终词表,而不保存学到的 merge rule 。
- 对于Unknown字符的处理不同。
SentencePiece
一般与Unigram算法连用。Unigram的算法思想是从一个巨大的词汇表出发,再逐渐删除trim down其中的词汇,直到size满足预定义。初始的词汇表可以采用所有预分词器分出来的词,再加上所有高频的子串。每次从词汇表中删除词汇的原则是使预定义的损失最小。
Unigram算法每次会从词汇表中挑出使得loss增长最小的10%~20%的词汇来删除。