大模型 | Tokeninzer自定义
Tokenization是几乎所有NLP任务的第一步,因为我们通常在tokens级别上处理文本。
一. 基础知识
Tokenizer的处理流程如下:
1.1 Normalizers
数据清洗,把输入的文本标准化,如“小写转换”,“Unicode标准化”等。
PS: 这里Unicode标准化能干啥?如所示
print("⾦"=="金")
False
其实两者的汉字的形相同,但Unicode符不同,为了避免这种问题,需要将两个字变成同一个。Unicode官方提供了NFD、NFKD、NFC、NFKC四种标准化方法,选择一个使用即可。
1.2 Pre-tokenizers
将原始字符串切割成子词条。如使用空格,标点符号,字节,其他规则等。如ByteLevel、WhitespaceSplite、CharDelimiterSplit、Metaspace……
分割策略在这里实现!主要分三个流派,按字符切分(Character-based),按词切分(Word-based),按子词切分(Subword-based)。这里就不废话了,BERT和GPT都是最后一种-子字词切分! 它的划分粒度介于词与字符之间,比如可以将”looking”划分为”look”和”ing”两个子词,而划分出来的"look",”ing”又能够用来构造其它词,如"look"和"ed"子词可组成单词"looked",因而Subword方法能够大大降低词典的大小,同时对相近词能更好地处理。
1.3 Tokenizer-Model
基于pre-tokenizer切割后的子词,进行更进一步的”合并分词“。
主要有三种基于子词的主流算法:BPE、WordPiece和Unigram。它们都使用略微不同的技术将不常用的单词分成更小的标记。
模型 | 应用代表 |
---|---|
WordPiece | BERT |
BPE/BBPE | GPT2,RoBERTa,LLaMa, ChatGLM |
Unigram | fast T5,mBART |
SentencePiece | T5, XLNet |
WordLevel | 不知道,不关心 |
BPE(Byte Pair Encoding)
a)构建语料库
在经过数据清洗和初步切割的Subword列表后,设定期望的Subword词表大小。BPE会确定每个单词的频率,并将该数字与单词一起存储在称为语料库的列表中;
b)构建词汇
语料库中的单词被分解成单个字符,并添加到一个称为词汇表的空列表中。该算法将在每次确定哪些字符对可以合并在一起时迭代地添加该词汇表。
c)找出字符对的频率
然后记录语料库中每个单词的字符对频率。例如,单词cats将具有ca, at和ts的字符对。所有单词都以这种方式进行检查,并贡献给全局频率计数器。在任何标记中找到的ca实例都会增加ca对的频率计数器。
d)创建合并规则
当每个字符对的频率已知时,最频繁的字符对被添加到词汇表中。词汇表现在由符号中的每个字母以及最常见的字符对组成。这也提供了一个模型可以使用的合并规则。例如,如果模型学习到ca是最常见的字符对,它已经学习到语料库中所有相邻的c和a实例可以合并以得到ca。现在可以将其作为单个字符ca处理其余步骤。
重复步骤c和d,找到更多合并规则,并向词汇表中添加更多字符对。这个过程一直持续到词汇表大小达到训练开始时指定的Subword目标大小。
WordPiece
WordPiece 与 BPE 非常相似,也是每次从词表中选出两个子词合并成新的子词。最大的区别是在合并的选择标准上略有不同。
为了进行合并,WordPiece 需要首先训练一个语言模型,并用该语言模型对所有可能的词元对进行评分。在每次合并时,选择使得训练数据似然概率增加最多的词元对。由于 Google 并没有发布其WordPiece 算法的官方实现,HuggingFace 在其在线 NLP 课程中提供了一种更直观的选择度量方法:一个词元对的评分是根据训练语料库中两个词元的共现计数除以它们各自的出现计数的乘积。计算公式如下所示:
Unigram
与WordPiece一样,Unigram Language Model(ULM)同样使用语言模型来挑选子词。不同之处在于,BPE和WordPiece算法的词表大小都是从小到大变化,属于增量法。而Unigram Language Model则是减量法, 即先初始化一个大词表,根据评估准则不断丢弃词表,直到满足限定条件。
ULM算法考虑了句子的不同分词可能,因而能够输出带概率的多个子词分段。
SentencePiece(最便捷,简化了预处理步骤)
SentencePiece 的一个主要优点就是它不需要预先进行这些预处理步骤。SentencePiece 可以直接接受原始的、未经分词的文本作为输入,这使得它能够适应各种语言,包括那些没有明确单词边界(如空格)的语言。此外,SentencePiece 还可以处理未在训练数据中出现的字符或字符序列,这使得它具有很好的泛化能力。
SentencePiece 支持多种分词算法,包括 BPE(Byte Pair Encoding)和 unigram。然而,要注意的是,虽然 WordPiece 和 BPE 在某种程度上是相似的,但是 SentencePiece 并没有直接实现 WordPiece 算法。
1.4 Post-Processors
给分词后的句子添加特殊标记。特殊标记都是直接或间接参与到模型训练的,具体不细讲,懂得都懂。
例如BERT会给句子加入分类向量和分隔符”[CLS] My horse is amazing [SEP]”,这时就需要Post-Processors。如BertProcessor……
项目:复用Bert词表架构,定制全新词表
如果业务逻辑简单,只是替换词表,那直接替换开源Model对应的Tokenizer的词表,就完事了。这块代码hugging face已经封装的很好了,不需要从头开始设计。
from transformers import BertTokenizer
# 你的自定义词汇表
vocab = ["click", "scroll", "swipe", "submit"]