大语言模型(LLM)正以惊人的速度改变着各行各业,从自然语言处理到机器翻译,LLM的身影无处不在。 然而,对于大多数人来说,LLM仍然像一个黑盒子,令人望而却步。 本文将以“从零开始构建LLM”为主题,结合Tokenization技术,一步步揭开LLM的神秘面纱, 让你对LLM的构建有一个更深入的理解。本文将重点探讨Tokenization技术在LLM构建中的重要作用,并结合实际案例进行分析。

LLM构建三阶段

在深入探讨Tokenization之前,我们先来了解LLM构建的三个主要阶段:

  1. LLM构建:这个阶段是基础,涉及到数据准备、Attention机制以及LLM架构的设计。 数据是LLM的基石,而优秀的架构则决定了LLM的上限。
  2. Foundation Models:在这个阶段,我们开始训练LLM,评估模型性能,并生成预训练权重。 训练过程需要大量的计算资源和时间。
  3. Finetuned Models:在这个阶段,我们针对特定任务对LLM进行微调,使其能够胜任诸如语言翻译、文本摘要等具体应用。 此时,Langchain和Olama等工具可以帮助我们更高效地完成任务。

Tokenization:LLM 理解语言的第一步

计算机只能理解0和1,那如何让LLM理解人类的语言呢? 这就要用到Tokenization技术。 Tokenization是将文本分割成更小的单元(tokens)并将其转换为数字的过程。 这些数字化的tokens是LLM理解和处理文本的基础。 简单来说,Tokenization就是LLM理解语言的第一步。

Tokenization 的质量直接影响 LLM 的性能,选择合适的 Tokenization 方法至关重要。 不同的 Tokenization 方法各有优缺点,适用于不同的场景。

三种主流 Tokenization 方法

目前,主流的 Tokenization 方法有三种:

  1. Word Level Tokenization(词级别 Tokenization):

    • 原理:将句子按照单词进行分割。通常使用空格或标点符号作为分隔符。

    • 例子:句子 “What does the LLM do?” 会被分割成 [“What”, “does”, “the”, “LLM”, “do”, “?”]。

    • 优点:简单易懂,易于实现。

    • 缺点

      • Out of Vocabulary (OOV)问题:如果遇到词汇表中没有的新词,会导致错误。例如,如果词汇表中没有 “Finance” 这个词,模型将无法处理包含该词的句子。
      • 词汇表庞大:每个独特的单词都需要一个单独的条目,导致词汇表非常大。例如,在处理大规模语料库时,词汇表可能会包含数百万个单词,这会增加模型的存储和计算负担。
      • 无法处理词形变化:将 “run”, “runs”, “running”, 和 “ran” 视为完全不同的tokens,尽管它们具有相同的语义。这会导致模型难以理解词形变化带来的含义变化。
    • 实际案例:早期的自然语言处理系统,例如基于规则的机器翻译系统,通常使用词级别 Tokenization

    为了解决这些问题,人们引入了 <BOS>, <EOS>, <PAD>, <UNK> 等特殊 token。<BOS> 表示句子的开始,<EOS> 表示句子的结束,<PAD> 用于填充句子,<UNK> 表示未知词。 这些特殊 token 的引入可以在一定程度上缓解 OOV 问题和处理不同长度的句子。

  2. Character Level Tokenization(字符级别 Tokenization):

    • 原理:将句子分割成单个字符。

    • 例子:句子 “What does the LLM do?” 会被分割成 [“W”, “h”, “a”, “t”, ” “, “d”, “o”, “e”, “s”, ” “, “t”, “h”, “e”, ” “, “L”, “L”, “M”, ” “, “d”, “o”, “?”]。

    • 优点

      • 避免 OOV 问题:任何单词都可以被token化,即使是生僻词或自造词。
      • 词汇表小:通常只需要 100-200 个字符,大大减小了词汇表的大小。
      • 适用于多种语言:尤其适用于形态丰富的语言,例如俄语和土耳其语。
    • 缺点

      • 序列长度过长:即使是短句子也会被分割成很长的序列,增加训练和推理的时间。
      • 缺乏语义信息:单个字符本身不携带意义,模型需要从头学习单词和短语的结构,需要更多的数据和计算资源。
    • 实际案例:一些早期的文本生成模型,例如 Char-RNN,使用字符级别 Tokenization 来生成文本。

  3. Sub-word Level Tokenization(子词级别 Tokenization):

    • 原理:将单词分割成更小的子词单元。它试图在词级别 Tokenization 和字符级别 Tokenization 之间找到一个平衡点,既能避免 OOV 问题,又能减少词汇表的大小。

    • 例子:”boy” 和 “boys”,”boy” 经常出现,”boys” 可以被分解成 “boy” 和 “s”。

    • 方法

      • Byte Pair Encoding (BPE):一种基于压缩的 Tokenization 方法,将频繁出现的字符对合并成新的子词单元。
        • 步骤
          1. 从字符级别开始。
          2. 合并最频繁出现的字符对,形成新的子词单元。
          3. 重复步骤2,直到达到预定义的词汇表大小。
        • 例子
          • 原始文本: “aaabdaaabac”
          • 压缩数据: “ZabdZabac” (Z = aa)
          • 再次压缩: “ZYdZYac” (Y = Zab)
        • 优点:能够有效地平衡词汇表大小和 OOV 问题。
        • 实际案例:GPT 和 BERT 模型都使用了 BPE Tokenization
      • WordPiece:类似于 BPE,但使用基于最大似然的贪婪方法,而不是纯粹的频率。
        • 实际案例:BERT 模型使用了 WordPiece Tokenization
    • 优点

      • 兼顾词级别和字符级别的优点:能够有效地处理 OOV 问题,同时保持较小的词汇表大小。
      • 能够处理词形变化:能够将具有相同词根的单词token化为相似的子词单元。
    • 缺点

      • 实现较为复杂:相对于词级别和字符级别 Tokenization,子词级别 Tokenization 的实现较为复杂。
    • 实际案例:BERT、GPT 等先进的 LLM 模型都使用了子词级别 Tokenization。 例如,GPT 使用了 BPE Tokenization,而 BERT 使用了 WordPiece Tokenization

BPE Tokenization 案例详解

BPE Tokenization 的核心思想是迭代地合并频繁出现的字符或子词对,直到达到预设的词汇表大小。 让我们通过一个更详细的例子来理解 BPE 的工作原理:

假设我们有以下文本:

low low low newer newer newer wider wider new new

1. 初始化词汇表:

首先,我们将文本中的每个字符都添加到词汇表中:

{'l', 'o', 'w', 'n', 'e', 'r', 'i', 'd', ' '}

同时,我们统计每个字符对出现的频率:

('l', 'o'): 3
('o', 'w'): 3
('w', ' '): 3
('n', 'e'): 3
('e', 'w'): 3
('w', 'e'): 2
('e', 'r'): 3
('r', ' '): 2
('w', 'i'): 2
('i', 'd'): 2
('d', 'e'): 2
(' ', 'n'): 2
(' ', 'w'): 2

2. 迭代合并:

接下来,我们迭代地合并最频繁出现的字符对。

  • 第一次合并:最频繁出现的字符对是 (‘l’, ‘o’),频率为 3。我们将 ‘l’ 和 ‘o’ 合并成一个新的子词 ‘lo’,并更新词汇表和频率统计。
{'l', 'o', 'w', 'n', 'e', 'r', 'i', 'd', ' ', 'lo'}

('lo', 'w'): 3
('w', ' '): 3
('n', 'e'): 3
('e', 'w'): 3
('w', 'e'): 2
('e', 'r'): 3
('r', ' '): 2
('w', 'i'): 2
('i', 'd'): 2
('d', 'e'): 2
(' ', 'n'): 2
(' ', 'w'): 2
  • 第二次合并:最频繁出现的字符对是 (‘lo’, ‘w’),频率为 3。我们将 ‘lo’ 和 ‘w’ 合并成一个新的子词 ‘low’,并更新词汇表和频率统计。
{'l', 'o', 'w', 'n', 'e', 'r', 'i', 'd', ' ', 'lo', 'low'}

('w', ' '): 3
('n', 'e'): 3
('e', 'w'): 3
('e', 'r'): 3
('low', ' '): 3
('w', 'e'): 2
('r', ' '): 2
('w', 'i'): 2
('i', 'd'): 2
('d', 'e'): 2
(' ', 'n'): 2
(' ', 'w'): 2
  • 第三次合并:最频繁出现的字符对是 (‘w’, ‘ ‘),频率为 3。我们将 ‘w’ 和 ‘ ‘ 合并成一个新的子词 ‘w ‘,并更新词汇表和频率统计。
{'l', 'o', 'w', 'n', 'e', 'r', 'i', 'd', ' ', 'lo', 'low', 'w '}

('n', 'e'): 3
('e', 'w'): 3
('e', 'r'): 3
('low', ' '): 3
('w e'): 2
('r', ' '): 2
('w', 'i'): 2
('i', 'd'): 2
('d', 'e'): 2
(' ', 'n'): 2

依此类推,直到词汇表达到预设的大小。

3. token化:

最终,我们使用学习到的词汇表对原始文本进行 Tokenization

low low low newer newer newer wider wider new new

将会被 token 化为:

['low', 'low', 'low', 'new', 'er', 'new', 'er', 'new', 'er', 'wid', 'er', 'wid', 'er', 'new', 'new']

可以看到,BPE Tokenization 将一些单词(例如 “low” 和 “new”)直接token化,而将另一些单词(例如 “newer” 和 “wider”)分割成更小的子词单元。

Tiktoken:强大的 Tokenization 工具

实际应用中,我们通常不会从头开始编写 Tokenization 代码,而是使用现成的库。 其中,Tiktoken 是 OpenAI 开发的一个高性能 Tokenization 库,被广泛应用于 GPT 模型。Tiktoken 实现了 BPE Tokenization,并针对 GPT 的特点进行了优化。 使用 Tiktoken 可以方便地对文本进行 Tokenization 和 de-Tokenization,并获取 token 的 ID。

TokenIDs:连接文本和模型

Tokenization 之后,我们需要将 tokens 转换成数字 ID,也就是 TokenIDs。 每个 token 对应一个唯一的 ID。 TokenIDs 是 LLM 的输入,也是 LLM 学习和理解语言的基础。 有了 TokenIDs,LLM 就可以将文本表示成数字向量,从而进行计算和推理。

从 TokenIDs 到 Token Embeddings

有了 TokenIDs,我们就可以将它们转换成 Token Embeddings。 Token Embeddings 是将每个 TokenID 映射到一个高维向量空间的过程。 这个向量空间可以捕捉到 token 的语义信息。 相似的 token 在向量空间中会更加接近。 Token Embeddings 是 LLM 理解语言的关键。 通过学习 Token Embeddings,LLM 可以将词语之间的关系表示成向量之间的关系,从而进行语义推理。

Tokenization 在 LLM 应用中的案例

1. 文本生成:

在文本生成任务中,Tokenization 用于将输入的文本 prompt 转换成 TokenIDs,然后 LLM 根据这些 TokenIDs 生成新的 TokenIDs。 最后,通过 de-Tokenization 将生成的 TokenIDs 转换成文本。 例如,在使用 GPT-3 生成文本时,首先需要使用 BPE Tokenization 将 prompt 转换成 TokenIDs,然后 GPT-3 根据这些 TokenIDs 预测下一个 token 的概率分布,并从中采样生成新的 TokenIDs。 最后,通过 de-Tokenization 将生成的 TokenIDs 转换成文本。

2. 文本分类:

在文本分类任务中,Tokenization 用于将输入的文本转换成 TokenIDs,然后 LLM 根据这些 TokenIDs 提取文本的特征,并进行分类。 例如,在使用 BERT 进行文本分类时,首先需要使用 WordPiece Tokenization 将文本转换成 TokenIDs,然后 BERT 根据这些 TokenIDs 提取文本的特征,并使用这些特征进行分类。

3. 机器翻译:

在机器翻译任务中,Tokenization 用于将源语言的文本转换成 TokenIDs,然后 LLM 根据这些 TokenIDs 生成目标语言的 TokenIDs。 最后,通过 de-Tokenization 将生成的目标语言 TokenIDs 转换成文本。 例如,在使用 Transformer 进行机器翻译时,首先需要使用 BPE Tokenization 将源语言文本转换成 TokenIDs,然后 Transformer 根据这些 TokenIDs 生成目标语言的 TokenIDs。 最后,通过 de-Tokenization 将生成的目标语言 TokenIDs 转换成文本。

总结与展望

Tokenization从零开始构建LLM的关键步骤,也是 LLM 理解和处理语言的基础。 本文详细介绍了三种主流的 Tokenization 方法:词级别 Tokenization、字符级别 Tokenization 和子词级别 Tokenization,并结合实际案例分析了它们的优缺点。 此外,本文还介绍了 BPE Tokenization 的工作原理,以及 Tiktoken 这一强大的 Tokenization 工具。

理解 Tokenization 技术,是深入了解 LLM 的第一步。 在接下来的文章中,我们将继续探讨 LLM 构建的其他关键技术,例如 Attention 机制、Transformer 架构、训练循环、模型评估、预训练权重、以及微调等。 最终,我们将从零开始构建一个 LLM,并用它来预测下一个单词或创建一个个人助理。 敬请期待!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注