Tokenizer 基础
我们已经知道,神经网络内部的一切运算都是数值——矩阵乘法、激活函数、梯度更新,它们接受的输入和产生的输出,全都是数字。但我们每天使用的是自然语言,它由文字构成,不是数字。
这一节,我们从零开始实现 Tokenizer。依次构建字符级、词级和子词级三种方案,观察每种切分方式带来的取舍,理解子词级为什么最终成为了现代大语言模型共同的选择。
将文本转换成数值的机制称为 Tokenizer。Tokenizer 先将文本切成小片段,再给每个片段分配一个整数编号。这些小片段称为 token,整数编号称为 token ID。
举个例子,句子 "the cat sat" 被切成 ["the", "cat", "sat"] 三个 token,再通过一张编号表(称为词表)查到对应的 ID 为 [5, 1, 3]。经过这样的处理,文本就变成了整数序列,可以被模型处理了。
切分的粒度有好几种。按字符切,每个字母是一个 token,比如 "cat" 被切成 ["c", "a", "t"],序列会变得很长。按词切,每个单词是一个 token,比如 "the cat sat" 被切成 ["the", "cat", "sat"],序列短了,但词表会很大,而且遇到没见过的词就无法处理。子词级在这两者之间取得了平衡,也是现代大语言模型普遍采用的方案。
# 先用真实的 tokenizer 感受一下:文本是怎么变成 token 的
import tiktoken
tokenizer = tiktoken.get_encoding("gpt2")
text = "the cat sat on the mat"
ids = tokenizer.encode(text)
tokens = [tokenizer.decode([i]) for i in ids]
print(f"原文: {text}")
print(f"token: {tokens}")
print(f"token ID: {ids}")
本节要点
通过这一节的学习,以下问题应该能够回答:
- Tokenizer 在做什么?
- 字符级切分有什么优缺点?
- 词级切分有什么优缺点?
- 子词级为什么是现代 LLM 的默认选择?
1. Token 和 Tokenizer
前面提到,token 是模型处理文本的最小单位。具体到切分方式,token 可以是一个字符、一个词,也可以是一个子词片段:
字符级: "cat" → ["c", "a", "t"]
词级: "the cat" → ["the", "cat"]
子词级: "playing" → ["play", "ing"]
Tokenizer 对外提供两个核心操作:encode(文本 → token ID 序列)和 decode(token ID 序列 → 文本)。
文本 --encode--> token ID 序列
ID序列 --decode--> 文本
需要注意的是,token ID 只是编号,不代表大小关系。ID 为 12 的 token 并不"大于"ID 为 3 的 token——它只是排在第 12 个位置。
下面准备一份小语料,逐一实现三种切分方式。
实验语料
Tokenizer 需要从语料中统计规律、建立词表,因此先准备一小段文本。这里使用英文,因为英文有空格作为天然的词边界,方便观察切分过程。原理清楚之后,中文的情况只是边界标记更隐蔽,需要更细致的规则。
# 我们的语料库 — 故意选有重复模式的简单句子
# 这样 BPE 合并时能清楚看到高频 pair 如何被合并
corpus = [
"the cat sat on the mat",
"the dog sat on the log",
"the cat and the dog",
"i love my cat",
"i love my dog",
"the cat is cute",
"the dog is happy",
"the mat is soft",
"the log is hard",
"cats and dogs are friends",
]
print(f"语料库共 {len(corpus)} 条句子")
for i, s in enumerate(corpus):
print(f" [{i}] {s}")
total_chars = sum(len(s) for s in corpus)
print(f"\n总字符数: {total_chars}")
print(f"总词数(按空格算): {sum(len(s.split()) for s in corpus)}")
语料库共 10 条句子
[0] the cat sat on the mat
[1] the dog sat on the log
[2] the cat and the dog
[3] i love my cat
[4] i love my dog
[5] the cat is cute
[6] the dog is happy
[7] the mat is soft
[8] the log is hard
[9] cats and dogs are friends
总字符数: 175
总词数(按空格算): 46
计算机是怎样表示文字的
屏幕上显示的 the cat,在计算机内部是一串编号(这里以 ASCII 为例):
文本: t h e c a t
↓ ↓ ↓ ↓ ↓ ↓ ↓
ASCII: 116 104 101 32 99 97 116