2.9 Tokenization与词嵌入
Transformer 处理的不是原始文字,而是向量。在一段文字变成模型输入之前,需要先经过两道关键变换:Tokenization(分词) 和 Embedding(词嵌入)。这两步看似简单,却决定了模型能”看到”什么、能”理解”什么——是整个 Transformer 流水线的起点,也是语言建模的基础认知。
📑 目录
- 1. 为什么需要把文字变成向量
- 2. Tokenization:把文字切分成基本单元
- 3. 独热编码:第一次尝试的失败
- 4. Word Embedding:几何空间里的语义地图
- 5. 位置信息的空缺:为什么还需要 Positional Encoding
- 6. 从 Token ID 到输入矩阵:Transformer 的输入层
- 自我检验清单
- 参考资料
1. 为什么需要把文字变成向量
计算机只认识数字,不认识文字。”猫”、”cat”、”Katze”——这些对计算机来说都是无意义的符号串,它不知道”猫”和”狗”都是动物,也不知道”happy”和”joyful”意思相近。
但神经网络的输入必须是数字矩阵。所以在文字进入 Transformer 之前,需要解决两个问题:
- 切分问题:怎么把一段连续文字拆成一个个可以处理的”单元”(Tokenization)?
- 编码问题:怎么把每个”单元”表示成一个能捕捉语义关系的数字向量(Embedding)?
这两个问题的解决方案,深刻影响着模型的理解能力和推理效率。
2. Tokenization:把文字切分成基本单元
2.1 Token 是什么
Token 是 Transformer 处理语言的最小单元——不是字,也不是词,而是介于两者之间的”词元”。
根据不同的切分策略,同一段文字会产生不同的 token 序列:
1 | 输入: "Tokenization" |
2.2 子词切分:大模型的实际选择
现代大模型普遍采用子词(Subword)切分策略,最常用的是 BPE(Byte Pair Encoding)。
📌 关键点:BPE 从字符出发,把高频的字符组合逐步合并成更大的 token,最终得到一个覆盖常用词、生词用子词拼接的词表。
直觉上理解:BPE 把高频组合合并为单一 token,把低频组合保留为子词拼接。常见词(”play”、”run”)通常作为完整 token 存在;生僻词或新词(如 “tokenization”)可能被拆成 “token” + “ization”,用已有子词拼接表示,不会出现未知词(OOV)问题。需要注意的是,BPE 的切分是纯数据驱动的统计结果,不一定按语言学意义上的词根/后缀切分,具体结果取决于训练词表。
实际大模型的词表规模:
| 模型 | 词表大小 | 分词策略 |
|---|---|---|
| GPT-2 / GPT-3 | 50,257 | BPE |
| LLaMA-2 | 32,000 | SentencePiece BPE |
| LLaMA-3 | 128,256 | Tiktoken BPE |
| GPT-4 | ~100,000 | Tiktoken cl100k |
⚠️ 注意:词表越大,覆盖越好,但 Embedding 矩阵(下文讲)也越大。LLaMA-3 把词表从 32K 扩到 128K,直接让 Embedding 层参数量增加了 4 倍。
2.3 Tokenization 的中文处理
中文没有天然的空格分隔,处理方式与英文不同:
- 大多数大模型对中文做字符级 Tokenization(每个汉字一个 token),或者将汉字的 UTF-8 字节序列作为切分依据
- 专门优化中文的模型(如 Qwen、ChatGLM 系列)通常有更大的词表,包含更多中文词组作为单独 token,生成效率更高
3. 独热编码:第一次尝试的失败
有了 Token ID,最简单的向量化方法是独热编码(One-Hot Encoding):假设词表有 $V$ 个 token,每个 token 用一个长度为 $V$ 的向量表示,对应位置为 1,其余全为 0。
举例:假设词表 = [“猫”, “狗”, “鱼”, “河”, “银行”],词表大小 $V = 5$:
$$
\text{猫} = [1, 0, 0, 0, 0] \qquad \text{狗} = [0, 1, 0, 0, 0] \qquad \text{鱼} = [0, 0, 1, 0, 0]
$$
看起来可以用,但有两个致命问题:
问题一:维度爆炸
真实词表有数万个 token,每个 token 的向量就有数万维,存储和计算开销极大。更严重的是,把这个稀疏向量作为神经网络输入,后续层需要极大的权重矩阵才能处理它——效率极差。
问题二:语义丢失
独热向量之间完全正交——“猫”和”狗”的向量内积为 0,”猫”和”鱼”的内积也是 0。从数学上看,所有 token 的距离完全相等,彼此之间毫无关联。这意味着模型无法从编码中学到任何语义关系:”猫”和”狗”都是宠物、都是动物,这个信息在独热编码里完全不存在。
$$
\text{猫} \cdot \text{狗} = 0, \quad \text{猫} \cdot \text{鱼} = 0 \quad \Rightarrow \text{模型看来”猫狗”关系 = “猫鱼”关系}
$$
4. Word Embedding:几何空间里的语义地图
4.1 核心思想:语义相似的词距离相近
Word Embedding(词嵌入)的核心思想是:把每个 token 映射到一个低维连续向量空间,使得语义相似的词在这个空间里距离相近。
从独热编码的 $V$ 维稀疏向量,压缩到 $d_{model}$ 维稠密向量(通常 $d_{model} \ll V$):
| 模型 | 词表大小 $V$ | 向量维度 $d_{model}$ | 压缩比 |
|---|---|---|---|
| BERT-base | 30,522 | 768 | ~40:1 |
| LLaMA-2-7B | 32,000 | 4,096 | ~8:1 |
| GPT-3 | 50,257 | 12,288 | ~4:1 |
用一个二维示意图来理解(真实 Embedding 空间维度远高于此):
1 | 动物类 |
可以看到,”猫”和”狗”在这个空间里距离很近(都是常见宠物)。需要注意:在静态 Word Embedding(如 Word2Vec)中,”银行”这个 token 只有一个固定向量,位置由它在所有语料中的平均共现模式决定——金融语境和河岸语境各占一部分,向量会落在两者之间。真正消除歧义是 Self-Attention 的工作:它根据上下文中其他词(”money” 或 “river”)动态调整每个 token 的表示,为”银行”在不同语境中生成不同的上下文向量。Embedding 层提供的是起点,Self-Attention 完成动态消歧。
4.2 Embedding 空间的神奇属性
经过大量语料训练的 Word Embedding 会涌现出令人惊叹的几何属性:
词语类比关系:
$$
\text{king} - \text{man} + \text{woman} \approx \text{queen}
$$
这意味着在 Embedding 空间里,”王”→”女王”的方向向量,和”男人”→”女人”的方向向量几乎平行!语义关系被编码成了几何关系。
语法变形的平行性:
$$
\text{walking} - \text{walk} \approx \text{swimming} - \text{swim} \approx \text{running} - \text{run}
$$
所有动词从原形到进行时的位移向量几乎相同——“时态变化”这个语法规律变成了一个统一的位移方向。
💡 提示:这些属性不是人工设计的,而是模型从海量文本中自动学习到的。正是因为全人类几百年的文字记录里,”狗追猫”、”猫抓鱼”这类共现关系远多于”猫追猫”,这些词语的空间位置才逐渐形成了今天的格局。
4.3 Embedding 矩阵:一张可学习的查找表
在 Transformer 中,Word Embedding 实现为一个可学习的查找矩阵 $W_{emb}$:
$$
W_{emb} \in \mathbb{R}^{V \times d_{model}}
$$
输入一个 Token ID,直接取对应行,得到 $d_{model}$ 维的向量:
1 | Token ID = 1234 → W_emb[1234, :] → [0.12, -0.34, 0.07, ..., 0.91] (d_model 维) |
这等价于一个输入为独热向量的线性层,但实现为查表(index lookup)操作,计算效率远高于实际的矩阵乘法。
Embedding 层的参数量:$V \times d_{model}$
以 LLaMA-2-7B 为例:$32000 \times 4096 \approx 131M$ 参数。看起来不少,但在 6.7B 总参数中只占约 2%,原因是其余参数都在 32 层 Decoder Block 里。
5. 位置信息的空缺:为什么还需要 Positional Encoding
Word Embedding 解决了”语义编码”的问题,但留下了一个关键缺陷:它不包含任何位置信息。
把句子 “猫追狗” 的三个 token 打乱为 “狗猫追”,它们的 Embedding 向量完全不变——模型根本分不清顺序。但语言的意思高度依赖词序:”猫追狗”和”狗追猫”意思截然相反。
这就是为什么 Transformer 在输入层还需要额外加上 Positional Encoding(位置编码):
$$
\text{Input}{i} = W{emb}[\text{token}_i] + \text{PE}(\text{pos}_i)
$$
Word Embedding 提供语义信息,Positional Encoding 提供位置信息,两者相加,才构成 Transformer 的完整输入。Positional Encoding 的详细设计(Sinusoidal 和 RoPE)在 2.5 位置编码深入理解 中详细讲解。
6. 从 Token ID 到输入矩阵:Transformer 的输入层
把上面的流程串起来,看一个完整的例子:
1 | 用户输入: "猫在桌子上" |
最终,4 个 token 变成一个 $(4, d_{model})$ 的矩阵,每行是一个 token 的向量表示(包含语义 + 位置信息)。这个矩阵就是 Transformer Block 的输入。
AI Infra 视角:Embedding 层的 $W_{emb}$ 矩阵有时会和输出层的 LM Head 共享权重(称为 Weight Tying),这样可以节省 $V \times d_{model}$ 的显存。例如 LLaMA-2 就采用了 Weight Tying,将 Embedding 参数量从 262M 降到 131M(只算一次)。在做量化时,Embedding 层通常不量化(因为它是查表操作,量化收益有限但精度损失较大)。
🎯 自我检验清单
- 能说清 Tokenization 的三种粒度(字符级、词级、子词级),以及现代大模型为什么选择子词切分
- 能解释独热编码的两大缺陷:维度爆炸和语义丢失
- 能说清 Word Embedding 的几何直觉:语义相近的词在 Embedding 空间中距离相近
- 能说出 king - man + woman ≈ queen 这类类比关系背后的几何含义
- 能写出 Embedding 层的参数量计算公式($V \times d_{model}$),并用 LLaMA-2-7B 实例验证
- 能解释为什么 Word Embedding 之上还需要 Positional Encoding(位置信息缺失)
- 能完整描述 “文字” → Token ID → Embedding → 加位置编码 → 输入矩阵的完整流程
📚 参考资料
- Attention Is All You Need — Transformer 原始论文,输入层设计见第 3.4 节
- Neural Machine Translation of Rare Words with Subword Units — BPE 分词算法原论文(Sennrich et al., 2016)
- Efficient Estimation of Word Representations in Vector Space — Word2Vec 原始论文(Mikolov et al., 2013),Word Embedding 的奠基性工作
- LLaMA 2: Open Foundation and Fine-Tuned Chat Models — LLaMA-2 模型细节,包含 Tokenizer 和 Embedding 层设计
- tiktoken — OpenAI 开源的 BPE 分词库,GPT 系列的实际使用工具