Tokenization的目地是将输入文本分割成一个个token,和词典配合以让机器认识文本。它的难点在于如何获得理想的切分,使文本中所有的token都具有正确的表义,并且不会存在OOV问题。
词粒度
词粒度的切分就跟人类平时理解文本原理一样,常常用一些工具来完成,例如英文的NLTK、SpaCy,中文的jieba。
英文
live in New York ———> live / in / New York /中文
在纽约生活 ——-> 在 / 纽约 / 生活
词粒度的切分能够非常好地保留完整语义信息,但是如果出现拼写错误、英文中的缩写等情况,鲁棒性一般。另一方面,词切分会产生非常巨大的词表,而且这都不能确保不会出现OOV问题。
字粒度
字粒度简单说英文就是以字母为单位(对于大小写不敏感的任务,甚至可以先转小写再切分),中文就是以字为单位。
英文
live in New York ——-> l / i / v /e / i / n / N / e / w / Y / o / r /k中文
在纽约生活 ——-> 在 / 纽 / 约 / 生 / 活
可以看出,字粒度的切分很好地解决了词粒度的缺陷,鲁棒性增强、词表大大减小。但另一方面,也会带来一些麻烦:
- 「毫无意义」:一个字母或一个单字本质上并没有任何语义意义;
- 「增加输入计算压力」:减小词表的代价就是输入长度大大增加,从而输入计算变得更耗时耗力;
Subword粒度
subword tokenization不转换最常见的单词,而是将稀有单词分解成有意义的子词单元。如果unfriendly被标记为一个稀有词,它将被分解为un-friendly-ly。这可以通过有限的已知单词列表来处理无限的潜在词汇。
subword粒度切分算法又有一下几种:
- BPE
- WordPiece
- ULM
BPE
BPE全称Byte Pair Encoding。BPE 迭代地合并最频繁出现的字符或字符序列,核心就是根据出现频率不断合并直到减少到词表大小或概率增量低于某一阈值。具体步骤如下:
- 准备足够大的语料库
- 定义好所需要的词表大小
- 将单词拆分为字符序列,在末尾添加后缀
</ w>
,并统计单词频率。 本阶段的subword的粒度是字符。 例如,“ low”的频率为5,那么我们将其改写为l o w </ w>:5
- 统计每一个连续字节对的出现频率,选择最高频者合并成新的subword
- 重复第4步直到达到第2步设定的subword词表大小或下一个最高频的字节对出现频率为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
共现次数最大,合并成es
,有,
{'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
共现次数最大,合并成est
,有,
{'l o w </w>': 5, 'l o w e r </w>': 2, 'n e w est </w>': 6, 'w i d est </w>': 3}
依次继续迭代直到达到预设的subword词表大小或下一个最高频的字节对出现频率为1。
Unigram LM
Unigram LM主要就是训练语言模型LM,然后不断剔除提高整体可能性最小的token,直到达到词表大小。在BPE算法中,我们需要贪婪的去搜索最常一起出现的字符,但该方法会有显著的缺点,就是它可能使得最终的词表显得存在歧义。Unigram LM基于所有子词出现是独立的假设,因此子词序列由子词出现概率的乘积生成。
WordPiece
综合了BPE和Unigram LM ,使用出现频率来选出潜在的组合,然后基于语言模型来决定最终的合并。WordPiece仍然还是一个贪婪的方法。该方法在每一次合并时候仍然选择最优的token对合并,与BPE不同的是WordPiece使用似然而不是频次。而Unigram方法则不同,Unigram方法是一个纯粹基于概率的方法,从通过概率选择要合并的token以及基于概率判断是否合并这些token。
Sentencepiece
可以看到上述3种其实更多的是基于英文为出发点进行考虑的,但是对于中文就不可能先进行切分,英文是分成一个个字母,sentencepiece是将所有输入转化为unicode字符,这就避免了这个情况。
- SentencePiece首先将所有输入转换为unicode字符。这意味着它不必担心不同的语言、字符或符号,可以以相同的方式处理所有输入;
- 空白也被当作普通符号来处理。Sentencepiece显式地将空白作为基本标记来处理,用一个元符号 “▁”( U+2581 )转义空白,这样就可以实现简单地decoding
- Sentencepiece可以直接从raw text进行训练,并且官方称非常快!