LLM 课程文档
归一化和预分词
并获得增强的文档体验
开始使用
归一化和预分词
在深入了解 Transformer 模型中最常用的三种子词分词算法(字节对编码 [BPE]、WordPiece 和 Unigram)之前,我们首先来看看每个分词器对文本应用的预处理。以下是分词管道步骤的高级概述:
在将文本(根据其模型)拆分为子词之前,分词器执行两个步骤:*归一化*和*预分词*。
归一化
归一化步骤涉及一些常规清理,例如删除不必要的空格、小写和/或删除重音。如果您熟悉Unicode 归一化(例如 NFC 或 NFKC),这也是分词器可能应用的内容。
🤗 Transformers 的 tokenizer
有一个名为 backend_tokenizer
的属性,它提供了对 🤗 Tokenizers 库中底层分词器的访问。
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
print(type(tokenizer.backend_tokenizer))
<class 'tokenizers.Tokenizer'>
tokenizer
对象的 normalizer
属性有一个 normalize_str()
方法,我们可以使用它来查看归一化是如何执行的。
print(tokenizer.backend_tokenizer.normalizer.normalize_str("Héllò hôw are ü?"))
'hello how are u?'
在此示例中,由于我们选择了 bert-base-uncased
检查点,因此应用的归一化将文本转换为小写并删除了重音。
✏️ 试试看! 从 bert-base-cased
检查点加载分词器,并将相同的示例传递给它。您能看到区分大小写和不区分大小写的两个版本的分词器之间有哪些主要区别?
预分词
正如我们将在下一节中看到的那样,分词器不能仅凭原始文本进行训练。相反,我们首先需要将文本分割成小的实体,例如单词。这就是预分词步骤的作用。正如我们在第 2 章中看到的那样,基于单词的分词器可以简单地将原始文本按空格和标点符号分割成单词。这些单词将成为分词器在其训练过程中可以学习的子词的边界。
要查看快速分词器如何执行预分词,我们可以使用 tokenizer
对象的 pre_tokenizer
属性的 pre_tokenize_str()
方法。
tokenizer.backend_tokenizer.pre_tokenizer.pre_tokenize_str("Hello, how are you?")
[('Hello', (0, 5)), (',', (5, 6)), ('how', (7, 10)), ('are', (11, 14)), ('you', (16, 19)), ('?', (19, 20))]
请注意,分词器是如何已经跟踪偏移量的,这就是它如何能够为我们提供我们在上一节中使用的偏移映射。在这里,分词器忽略了两个空格,并将其替换为一个,但偏移量在 are
和 you
之间跳跃以考虑到这一点。
由于我们使用的是 BERT 分词器,预分词包括按空格和标点符号进行拆分。其他分词器在此步骤中可能有不同的规则。例如,如果我们使用 GPT-2 分词器:
tokenizer = AutoTokenizer.from_pretrained("gpt2")
tokenizer.backend_tokenizer.pre_tokenizer.pre_tokenize_str("Hello, how are you?")
它也会按空格和标点符号进行拆分,但它会保留空格并将其替换为 Ġ
符号,从而使我们能够在解码标记时恢复原始空格。
[('Hello', (0, 5)), (',', (5, 6)), ('Ġhow', (6, 10)), ('Ġare', (10, 14)), ('Ġ', (14, 15)), ('Ġyou', (15, 19)),
('?', (19, 20))]
另请注意,与 BERT 分词器不同,此分词器不会忽略双空格。
最后一个例子,我们来看看基于 SentencePiece 算法的 T5 分词器:
tokenizer = AutoTokenizer.from_pretrained("t5-small")
tokenizer.backend_tokenizer.pre_tokenizer.pre_tokenize_str("Hello, how are you?")
[('▁Hello,', (0, 6)), ('▁how', (7, 10)), ('▁are', (11, 14)), ('▁you?', (16, 20))]
与 GPT-2 分词器一样,它保留空格并将其替换为特定标记 (_
),但 T5 分词器只按空格拆分,不按标点符号拆分。另请注意,它默认在句子开头(Hello
之前)添加了一个空格,并忽略了 are
和 you
之间的双空格。
现在我们已经了解了一些不同的分词器如何处理文本,我们可以开始探索底层算法本身。我们将首先快速了解广泛适用的 SentencePiece;然后,在接下来的三节中,我们将研究用于子词分词的三种主要算法是如何工作的。
SentencePiece
SentencePiece 是一种用于文本预处理的分词算法,您可以将其与我们将在接下来的三节中看到的任何模型一起使用。它将文本视为 Unicode 字符序列,并将空格替换为特殊字符
。与 Unigram 算法(参见第 7 节)结合使用时,它甚至不需要预分词步骤,这对于不使用空格字符的语言(如中文或日文)非常有用。
SentencePiece 的另一个主要特性是*可逆分词*:由于没有对空格进行特殊处理,因此解码标记只需通过连接它们并将 _
替换为空格来完成——这会产生规范化文本。正如我们前面所看到的,BERT 分词器会删除重复的空格,因此它的分词是不可逆的。
算法概述
在以下部分中,我们将深入探讨三种主要的子词分词算法:BPE(由 GPT-2 及其他模型使用)、WordPiece(例如由 BERT 使用)和 Unigram(由 T5 及其他模型使用)。在开始之前,这里简要概述了它们各自的工作原理。如果您还不理解,请在阅读完接下来的每个部分后随时返回此表。
模型 | BPE | WordPiece | Unigram |
---|---|---|---|
训练 | 从一个小的词汇表开始,学习合并标记的规则。 | 从一个小的词汇表开始,学习合并标记的规则。 | 从一个大的词汇表开始,学习删除标记的规则。 |
训练步骤 | 合并对应于最常见对的标记。 | 根据词对的频率,将得分最高的词对合并,优先考虑每个独立词都较不频繁的词对。 | 移除词汇表中所有会使整个语料库上计算的损失最小化的词元。 |
学习 | 合并规则和词汇表 | 仅词汇表 | 包含每个标记得分的词汇表。 |
编码 | 将一个单词拆分为字符,并应用训练期间学习到的合并规则。 | 从开头找到词汇表中包含的最长子词,然后对单词的其余部分执行相同的操作。 | 利用训练期间学到的分数,找到最可能的词元分割。 |
现在让我们深入了解 BPE!
< > 在 GitHub 上更新