大模型如何理解自然语言:分词器的入门指南

在自然语言处理(NLP)的领域中,"大模型"如同一位精通语言的大师,能够理解并生成各种文本。这些模型并非生来就具备这种能力,而是依赖于大量的训练和精心设计的数据预处理流程。在这一过程中,分词器扮演着核心角色,对于文本预处理至关重要。本文将深入探讨分词器的工作原理,以及一些流行大模型(例如LLaMA)的分词器实现细节,以帮助您理解这些大模型是如何处理自然语言的。

分词器的作用:从“字符”到“意义单元”

考虑这样一句话:“Hello world!”。如果没有分词器,计算机只能将其视为一串字符:

Hello world!

对于人类来说,理解这句话并不困难:“Hello”和“world”是两个独立的词,“!”是一个标点符号。然而,计算机缺乏直观的语言理解能力,它需要一个“分词器”来将这句话分解成有意义的单元。经过分词器的处理,计算机可以将这句话转化为:

['Hello', 'world', '!']

分词器的目标是将原始文本转换为模型可以处理的结构化形式。所谓的“单元”可能是词、子词或字符,这取决于所采用的分词策略。

分词器的工作原理:从规则到复杂算法

虽然分词器看似简单,但其实现涉及多个层次的算法。现代分词器不仅仅按词切割文本,而是采用了一些更复杂的算法,例如子词分词。我们将从传统的分词方法讲起,逐步深入到现代的分词算法。

1. 基于词的分割

最简单的分词方法是按词分割,这种方法在英语等语言中效果显著。例如,句子:

Hello world!

经过按词分割后,得到:

['Hello', 'world', '!']

这种方法直接依赖于空格和标点符号作为分割点,对于英语等词汇间有明确空格的语言非常有效。然而,对于中文和日文等没有空格的语言,需要更复杂的分词方法。

2. 基于字符的分割

对于中文这样的语言,字符本身就是语言的基本单位,因此可以按字符进行分割。例如:

你好,世界!

经过字符分割后,得到:

['你', '好', ',', '世', '界', '!']

这种方法简单直观,但对于一些复杂的任务(如机器翻译),可能不够精细。

3. 子词级分词:BPE与WordPiece

子词级分词的核心思想是通过将词拆解成更小的单位(如子词或字符),来解决词汇表稀疏的问题。现代的预训练大模型,尤其是像BERT、GPT等,都采用了这种方法。最常见的两种子词分词算法是 BPE(Byte Pair Encoding)WordPiece

BPE(Byte Pair Encoding)

BPE是一种基于统计的子词分词算法。其基本原理是通过统计文本中最频繁的字符对,并将它们合并成一个新的子词,直到达到词汇表的大小限制。以简单的文本为例:

原始文本

low lower newest
  1. 初始时,我们按字符分割:

    ['l', 'o', 'w', ' ', 'l', 'o', 'w', 'e', 'r', ' ', 'n', 'e', 'w', 'e', 's', 't']
    
  2. 统计频率并合并最频繁的字符对。例如,lo 频率最高,因此合并成 lo

    ['lo', 'w', ' ', 'lo', 'w', 'e', 'r', ' ', 'n', 'e', 'w', 'e', 's', 't']
    
  3. 继续统计并合并频率较高的字符对,如 low

    ['low', ' ', 'low', 'e', 'r', ' ', 'n', 'e', 'w', 'e', 's', 't']
    
  4. 最终,合并到“newest”变为:

    ['low', 'low', 'er', 'new', 'est']
    

这种方法通过逐步合并字符对,逐步构建出词汇表,能够有效减少词汇表的大小,并且能够处理未见过的词。

WordPiece

WordPiece是另一种子词分词算法,广泛应用于BERT模型中。与BPE不同,WordPiece通过最大化文本的对数似然来合并最优的字对。假设我们有如下文本:

low lower newest

WordPiece的分词过程与BPE相似,但它通过一个最大化似然的方法来优化合并的方式。最终,WordPiece也能将文本拆解成子词单元。

举个例子:

  • “low” 会被分割成 ['lo', 'w']
  • “lower” 会被分割成 ['lo', 'w', 'er']
  • “newest” 会被分割成 ['new', 'est']

WordPiece在实际应用中非常高效,尤其适合处理多语言和复杂的文本结构。

SentencePiece

SentencePiece 是由Google提出的一种分词算法,它不像BPE和WordPiece那样需要预先定义词汇表。它通过无监督的方式直接从文本中学习生成子词单元。SentencePiece特别适合于多语言环境,它能够同时处理多种语言的文本。

比如,对于句子:

低资源语言处理

SentencePiece可能会将它分割成:

['低', '资源', '语', '言', '处理']

SentencePiece的一个重要特点是,它能够在没有预定义词典的情况下直接进行训练,非常适合低资源语言或多语言环境。

常见的大模型分词器

除了BERT等常见模型,LLaMAGPT等现代大语言模型也依赖分词器来处理文本。接下来,我们看一看这些大模型中的分词器实现,特别是它们的Tokenizer类中的常见变量。

LLaMA中的Tokenizer

LLaMA(Large Language Model Meta AI)是Meta(Facebook)发布的一款强大的预训练模型,它也使用了基于BPE的分词器。LLaMA的Tokenizer类实现中,通常包含以下几个关键变量:

  • vocab_size:词汇表的大小。这个变量决定了分词器能处理的最大词汇量,更大的词汇表可以提高模型对新词的处理能力,但也会增加计算和存储开销。
  • tokens:分词器内部存储的词汇表,包含所有的子词单位。
  • encode:用于将文本转换为子词单元的函数。该函数会返回一个整数序列,表示每个子词的ID。
  • decode:与encode相对,用于将模型输出的ID序列转回为可读文本。

在LLaMA的Tokenizer实现中,分词的核心通常依赖于BPE算法,这样可以更好地处理未见过的词汇。

选择合适的分词器

在选择分词器时,我们需要考虑以下几个因素:

  1. 任务类型:如果你的任务需要处理很多未知词,或者你的数据集中包含大量拼写错误,采用子词分词器(如BPE、WordPiece或SentencePiece)会更合适。
  2. 资源限制:不同分词器的效率和词汇表大小差异较大。对于计算资源有限的场景,选择一个更轻量级的分词器,如WordPiece,可能会带来更好的性能。
  3. 多语言支持:如果你的应用需要支持多种语言,SentencePiece是一种非常不错的选择,因为它能够无监督地学习语言的结构,适应多语言环境。
  4. 上下文感知能力:对于对话生成类任务(如chatbot),需要处理更多上下文信息,选择分词器时也要考虑到模型的上下文感知能力。

代码示例:使用Hugging Face的Tokenizer

from transformers import BertTokenizer

# 加载BERT的分词器
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')

# 示例文本
text = "Hello, world!"

# 使用分词器进行编码
encoded = tokenizer.encode(text, add_special_tokens=True)  # add_special_tokens添加[CLS]和[SEP]
print("Encoded:", encoded)

# 解码
decoded = tokenizer.decode(encoded)
print("Decoded:", decoded)

在这段代码中,BertTokenizerencode方法将输入的文本转换成整数ID

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容