NLP的tokenizer---分词器

tokenizer作为NLP领域不可缺少的一部分,对于模型的训练时间和效果有着重要的影响,如果分词器的粒度太细,词表会很小,但是能代表的实际含义也会很少;如果粒度较粗,整个词表可能会很大,降低训练效率的同时,对于OOV的问题也不太好解决。

tokenizer从粒度可以划分为char, subword 和 word三个级别。

  • char级别的分词:
    优点:词表很小(英文字母最多就是52个大小写字母 + 特殊字符);鲁棒性强,没有OOV问题。
    缺点:大部分单字母或者单字没有语义意义;根据词表将文本或句子转换为模型输入,其输入长度可能会很长,额外增加模型需要学习的参数,不仅使模型难以训练,训练也更耗时耗力。
  • Word级分词器
    简单理解,对于英文就是使用空格进行分词。
    优点:与人类大脑理解文本的思路一致,包含有实际含义。
    缺点:若使用这种编码方式,词表会很大,在语言模型预测的时候需要在这个拥有几万个单词的列表上计算一个概率分布,那样的计算量是非常恐怖的,而且过大的token列表十分影响模型的预测准确度.
    Subword是最常用的分词粒度,下面是常用的分词算法介绍,包括BPE、WordPiece等。

BPE

BPE 是一种简单的数据压缩算法,它在 1994 年发表的文章“A New Algorithm for Data Compression”中被首次提出。
BPE每一步都将最常见的一对相邻数据单位替换为该数据中没有出现过的一个新单位,反复迭代直到满足停止条件。
简单理解BPE是按照频率来进行迭代的算法。
BPE获得Subword的步骤如下:

  1. 准备足够大的训练语料,并确定期望的Subword词表大小;
  2. 将单词拆分为成最小单元。比如英文中26个字母加上各种符号,这些作为初始词表;
    3.基于基础词表将语料中的单词拆分为字符序列并在末尾添加后缀“ </ w>”;本阶段的subword的粒度是字符。例如单词“ low”的频率为5,那么我们将其改写为“ l o w </ w>”:5
  3. 在语料上统计单词内相邻token对的频数,选取频数最高的单元对合并成新的Subword token;
  4. 重复第4步直到达到第1步设定的Subword词表大小或下一个最高频数为1.

PS:词汇量的设定值是超参数,需要提前设置,大小由两部分组成(基础词汇表大小 + BPE算法合并次数);例如,GPT的词汇量为40478,因为有478个基本字符,在40000次合并后选择停止训练。

从上面的示例可以知道,每次合并后词表大小可能出现3种变化:

+1,表明加入合并后的新子词,同时原来的2个子词还保留(2个字词分开出现在语料中)。
+0,表明加入合并后的新子词,同时原来的2个子词中一个保留,一个被消解(一个子词完全随着另一个子词的出现而紧跟着出现)。
-1,表明加入合并后的新子词,同时原来的2个子词都被消解(2个字词同时连续出现)。

实际上,随着合并的次数增加,词表大小通常先增加后减小

在得到Subword词表后,针对每一个单词,我们可以采用如下的方式来进行编码:

将词典中的所有子词按照长度由大到小进行排序;
对于单词w,依次遍历排好序的词典。查看当前子词是否是该单词的子字符串,如果是,则输出当前子词,并对剩余单词字符串继续匹配。
如果遍历完字典后,仍然有子字符串没有匹配,则将剩余字符串替换为特殊符号输出,如”<unk>”。
单词的表示即为上述所有输出子词。
解码过程比较简单,如果相邻子词间没有中止符,则将两子词直接拼接,否则两子词之间添加分隔符。

BBPE

BBPE的基本思想是将BPE从字符级别扩展到字节(Byte)级别。BPE在处理unicode编码时可能会导致基础字符集过大,而BBPE将每个字节视为一个“字符”,不论实际字符集用多少字节表示。这样,基础字符集的大小就固定为256(2^8),从而实现跨语言共享词表,并显著缩减词表大小。然而,对于像中文这样的语言,文本序列长度会显著增加,这可能使得BBPE模型的性能优于BPE模型,但其序列长度较长也会导致训练和推理时间增加。BBPE的实现与BPE类似,主要差别在于基础词表使用256的字节集。

以下内容来自https://zhuanlan.zhihu.com/p/649030161

BBPE 的兼容性—通用模型(多种语言)

总之,个人感觉BBPE解决一个问题是能比较好支持语料是多种语言的分词,一方面正如上面所说,如果只考虑英文、法语、西班牙语等拉丁美系的语言,BEP足以支持能够以较小词表大小(Vocabulary Size)解决OOV的问题。但中文、日本如果使用BEP对字符(characters)进行构造词表的话,其具有的生僻词会占据浪费比较大词表空间。结合最近有关GPT5加强其翻译的能力的报道,通用人工智能AGI的角度上来看,使用对支持多种语言的友好的Tokenizer可以极大降低成本,同时突出翻译的能力。在LLM时代,如何设计一个兼顾通用且高效推理的Tokenizer是非常重要的事情。

BBPE 不太适合中文

最近,估计考虑到训练语料中不同的语言以及模型的通用性,掀起开源LLM浪潮的原始LLaMa模型的Tokenizer采用的就是BBPE。

从另一方面,即使BBPE支持将中文汉字进行编码,但单个汉字最长还是需要用3个token进行编码。不考虑兼容性,如果只在中文、日本这类语言上只根据单个字,以及词语作为基础单元生成词表,就可以实现将单个、甚至多个汉字的词语都只用1个token进行编码,能够提高模型推理速度。这也能解释基于原始LLaMa继续训练的Chinese-LLaMa, Cui模型第一步就是先扩充中文的词表再进行训练。

BBPE总结

总的来说,BBPE效果与BPE相当,从发明时即为了解决中文、日本编码词表过大的问题,因此在多语言编码上天然具有词表小的优势,但同时导致每种语言不一定是长度最优的编码方式,必然从长度上会增加推理计算的开销。另外UTF-8编码可以在不同语言之间字节编码可能具有一定互通性,可以实现即使字符集不重叠,也可以通过子节层面的共享来实现良好的迁移。有利于模型翻译能力提升

WordPiece

Google的Bert模型在分词的时候使用的是WordPiece算法。与BPE算法类似,WordPiece算法也是每次从词表中选出两个子词合并成新的子词。与BPE的最大区别在于,如何选择两个子词进行合并:BPE选择频数最高的相邻子词合并,而WordPiece选择能够提升语言模型概率最大的相邻子词加入词表

看到这里,你可能不清楚WordPiece是如何选取子词的。这里,通过形式化方法,能够清楚地理解WordPiece在合并这一步是如何作出选择的。假设句子 S=(t_{1},t_{2},...,t_{n})由n个子词组成,t_{i}表示子词,且假设各个子词之间是独立存在的,则句子S的语言模型似然值等价于所有子词概率的乘积:
logP(S) = \sum_{i=1}^{n}logP(t_{i}) \\
假设把相邻位置的x和y两个子词进行合并,合并后产生的子词记为z,此时句子S似然值的变化可表示为:
logP(t_{z})-(logP(t_{x})+logP(t_{y}))=log(\frac {P(t_{z})}{P(t_{x})P(t_{y})}) \\
从上面的公式,很容易发现,似然值的变化就是两个子词之间的互信息。简而言之,WordPiece每次选择合并的两个子词,他们具有最大的互信息值,也就是两子词在语言模型上具有较强的关联性,它们经常在语料中以相邻方式同时出现。

输入:训练语料; 词表大小V
1.准备足够大的训练语料,确定期望的subword词表大小;
2.准备基础词表:比如英文中26个字母加上各种符号;
3.基于基础词表将语料中的单词拆分为最小单元;
4.基于第3步数据训练语言模型,可以是最简单的unigram语言模型,通过极大似然进行估计即可;
5.从所有可能的subword单元中选择加入语言模型后能最大程度地增加训练数据概率的单元作为新的单元;
6.重复第5步直到达到第2步设定的subword词表大小或概率增量低于某一阈值;

UniLM

UniLM算法出自论文:Subword Regularization: Improving Neural Network Translation Models with Multiple Subword Candidates, 可以看成是WordPiece算法在执行过程中进行反向操作。相比WordPiece借助语言模型选择合并计算概率最大的相邻字符对加入词表中作为新的Subword,UniLM是开始时先构建足够大的词表,之后每一步选择一定比例的计算概率低的Subword从词表中删除。因此过程中比较显著差别是WordPiece算法的词表在生成过程中是从小到大的变化,而UniLM的词表则是从大到小的变化,整个过程根据评估不断删除排序靠后的Subword直到词表大小减少到设定值。

在选择语言模型计算每个子词在语料上的概率时,UniLM和WordPiece思路也是一致,这里也可以选择最简单unigram lm(一元分词语言模型)。具体,每个词Score和上面WordPiece计算Score就是一致的。可以看出整个过程,UniLM倾向于保留以较高频率出现在很多句子的分词结果中的子词(Subword)。这点思路上与WordPiece一致,由于每次保留,删除的是一批Subword,其算法复杂度比WordPiece每次合并一个要低。

算法步骤
输入:训练语料;词表大小V; 保留阈值X;

1.准备基础词表:初始化一个很大的词表,比如所有字符+高频Ngram,也可以通过BPE算法初始化;
2.针对当前词表,用语言模型(unigram lm)估计每个子词在语料上的概率;
3.计算删除每个Subword后对总loss的影响及Score得分,作为该Subword排序的Score得分;
4.将子词按照Score大小进行排序,保留前X%的Subword;注意,建议单字符的Subword不能被丢弃,以免OOV;
5.重复步骤2到4,直到词表大小减少到设定值;

常见大模型使用的tokenizer一览

模型 分词器
GPT-4o BPE(BBPE)
GPT3 BPE(BBPE)
GPT2 BPE(BBPE)
GPT BPE
Llama3 BPE(BBPE)
Llama2 BPE(BBPE)
Qwen2 BPE(BBPE)
Qwen BPE(BBPE)
ChatGLM BBPE
Baichuan BPE
RoBERTa BPE
BART BPE
DeBERTa BPE
MobileBERT WordPiece
DistilBERT WordPiece
BERT WordPiece
T5 Unigram
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

友情链接更多精彩内容