语言如何被量化:从符号到向量的第一步
人类语言天然是离散的:我们用“词”“字”“标点”“空格”把连续的声音或书写切分成一个个可数的符号单位。然而,现代机器学习的核心算子——加法、乘法、内积、梯度下降——运行在连续空间上。要让模型“处理语言”,第一步并不是理解语义,而是把离散符号系统改写成一种可计算的表示:把文本变成索引,把索引变成向量,再让向量进入后续的几何运算。这里的“向量化”不是装饰性的编码技巧,而是整个大语言模型数学结构得以成立的地基。
离散符号与计算之间的断层
离散符号系统擅长表达、擅长组合,但不擅长“度量”。例如,直觉上“国王”与“女王”比“国王”与“桌子”更相近;但如果我们只把它们视为字符串,计算机看到的只是三段不同的字符序列,既没有连续的距离,也没有可微的相似度函数。更麻烦的是,学习算法需要在“错一点”和“错很多”之间建立梯度信号:当模型把“女王”预测成“王后”,应当惩罚较轻;预测成“桌子”,应当惩罚更重。没有连续空间,就很难自然定义这种“差多少”的概念。
从更抽象的角度看,语言系统的基本对象属于集合(set)或序列(sequence)的范畴,而训练过程需要把目标函数写成可微函数 $L(\theta)$,再用梯度 $\nabla_\theta L$ 更新参数。可微性要求输入表示与参数之间通过一系列可微映射连接;因此我们需要把符号映射到 $\mathbb{R}^d$ 中的点,让“语义差异”在几何上表现为距离、角度或子空间关系。【标签:核心概念】离散到连续(discrete-to-continuous)正是本章的主线。
词元、词表与编码:把文本变成整数
在进入向量空间之前,文本通常先被规范化为一串整数索引。这一步看似工程化,却决定了模型能“看见”的基本颗粒度。
词元(token)是什么
“词元”并不等同于语言学意义上的“词”。在大语言模型里,token 更像一种可重复使用的符号片段:它可能是一个词(English word),一个汉字,一个常见词组,一个子词(subword),甚至是一段字节序列。token 的选择兼顾三个目标:
1. 覆盖性:尽量避免未知词(OOV, out-of-vocabulary)。 2. 效率:序列长度越短,计算越省;但颗粒度过粗会导致词表暴涨。 3. 可泛化性:通过子词组合,模型能处理未见过的新词形与新实体。
中文读者常见的误解是“中文模型一定按字切分”。事实上,许多系统采用类似 BPE(Byte Pair Encoding)或 WordPiece 的子词方案:常见的词组(如“人工智能”“注意力机制”)可能作为整体 token,低频词则被拆成更小的片段。这样既能缩短序列,又能对低频词保持覆盖。
> 侧栏(电子版提示):若想快速建立直觉,可把 token 理解为“模型词典里的最小拼块”,文本只是把这些拼块按顺序排好。[^token]
[^token]: token 译作“词元”是常见约定,也有人译作“标记”。本书用“词元”强调其作为基本计算单元的地位。
词表(vocabulary)与索引
一旦确定 token 集合,就可以建立词表:一个从 token 到整数 ID 的映射 \[ V: \text{token} \mapsto \{0,1,\dots,|V|-1\}. \] 词表大小 $|V|$ 是关键超参数:太小会产生大量拆分,序列变长;太大则带来更高的存储与计算开销。实践中常见量级是几万到十几万(例如 $|V|\approx 50{,}000$ 或 $100{,}000$),这与自然语言的词频分布有关:词频大致服从 Zipf 定律,高频词很少、长尾极长,使得“完全按词建表”既不经济也不稳健。
【标签:核心概念】Zipf 定律(Zipf’s law)常被简述为“第 $k$ 高频词的频率与 $1/k$ 成正比”。它解释了为什么“长尾词”永远学不完:你扩充词表时,新增的多是低频词,边际收益递减。
编码(encoding):从 token 序列到 ID 序列
给定文本 $x$,tokenizer 产生 token 序列 $(t_1,\dots,t_n)$,再映射成 ID 序列 $(i_1,\dots,i_n)$。到这里,文本被改写为整数序列,但这仍然不是模型能直接做“几何运算”的对象,因为整数 ID 的大小并不携带语义:ID=5 并不比 ID=6 “更接近”任何东西。
下面用一个极小示例固定概念。设词表 $V=\{\text{“我”},\text{“喜欢”},\text{“数学”},\text{“。”}\}$,对应 ID 为 0,1,2,3。句子“我 喜欢 数学 。”编码为 $(0,1,2,3)$。此时“数学”并不会因为 ID=2 就天然与“喜欢”(ID=1)更相似。我们需要下一步:把 ID 变成向量。
```mermaid graph TD A[原始文本] --> B[tokenizer: 切分为 token] B --> C[词表映射: token->ID] C --> D[向量化: one-hot 或 embedding] D --> E[后续模型: 注意力/前馈网络] ```
为什么必须进入向量空间:连续、可微与可度量
把符号映射到向量空间的动机,可以归结为三类“数学需求”。
可微:让学习算法能够更新
训练大语言模型本质上是在最小化损失函数,例如交叉熵损失。损失的输入来自模型输出,模型输出来自对输入表示的连续变换。若输入保持离散符号,模型就很难通过微小调整参数来“稍微偏向”某个符号。向量表示提供了连续的载体:参数改变一点,向量变换的结果也改变一点,于是梯度下降能稳定工作。
可度量:相似度与邻近结构
一旦 token 对应于 $\mathbb{R}^d$ 的向量 $e(t)\in\mathbb{R}^d$,我们就能定义相似度,例如余弦相似度 \[ \cos(e_a,e_b)=\frac{e_a^\top e_b}{\|e_a\|\,\|e_b\|}. \] “相似”不再是主观判断,而可以转化为向量夹角的度量。这种度量结构将在后续章节变得至关重要:注意力机制的核心操作就是内积相似度的变体。
可组合:让结构通过线性代数显现
自然语言充满组合性:词组成短语,短语组成句子,句子组成段落。向量空间允许我们用线性变换与张量运算表达组合关系。虽然“语义是否线性”并非严格成立,但线性代数提供了一套高效、可扩展的近似工具:矩阵乘法可并行,统计学习理论与优化工具也围绕它建立。
One-hot:最直接的表示,也是最笨重的表示
最基本的向量化方案是 one-hot。给定词表大小 $|V|$,每个 token $t$ 对应一个长度为 $|V|$ 的向量 $x(t)\in\{0,1\}^{|V|}$,其中只有第 $V(t)$ 个位置为 1,其余为 0。
One-hot 的优点:无歧义、零先验
one-hot 的“意义”非常朴素:它只是一个身份标签。其优点在于:
- **确定性**:每个 token 对应唯一位置,不会混淆。
- **不引入先验相似性**:模型自己学习什么该相似。
- **实现简单**:适合理论推导与入门理解。
但这些优点恰好对应着它在大规模系统中的根本缺点。
维度灾难与稀疏性
若 $|V|=50{,}000$,one-hot 向量维度就是 50k。它们极度稀疏:每次输入只有一个 1。稀疏并不总是坏事,但在深度学习中,稀疏高维表示会造成两类成本:
1. 存储与带宽:直接存储 one-hot 没意义,通常改用索引;但一旦进入线性层,等价于与一个巨大矩阵相乘。 2. 相似度不可用:任意两个不同 token 的 one-hot 内积为 0,余弦相似度也为 0。几何上它们两两正交,无法表达“相近”。
用公式可以清晰看到这一点。对于不同 token $a\neq b$, \[ x(a)^\top x(b)=0,\quad \|x(a)\|=\|x(b)\|=1,\quad \cos(x(a),x(b))=0. \] 也就是说,在 one-hot 空间里,“国王”和“桌子”与“国王”和“女王”同样不相似。这显然违背我们对语义空间应有结构的期待。
关键转折:one-hot + 线性变换 = 嵌入查表
尽管 one-hot 本身笨重,它却引出一个重要等价:对 one-hot 施加线性变换,就得到嵌入(embedding)。
设有矩阵 $E\in\mathbb{R}^{|V|\times d}$,把 one-hot 映射到 $d$ 维: \[ e(t)=x(t)^\top E. \] 由于 $x(t)$ 只有一个位置为 1,这个乘法等价于从矩阵 $E$ 中取出第 $V(t)$ 行。因此,embedding 层在实现上常写成“查表”(lookup):输入是 ID,输出是向量。这一观察把“高维稀疏”转换为“低维稠密”,并使训练变得高效。
稠密表示(Embedding):把语义放进几何里
嵌入矩阵的含义:可学习的坐标系
嵌入层通常是一个可训练参数矩阵 $E\in\mathbb{R}^{|V|\times d}$。第 $i$ 行向量 $E_{i:}$ 就是 ID 为 $i$ 的 token 的表示。维度 $d$ 常取 256、512、768、1024 等量级,远小于词表大小。【标签:核心概念】稠密表示(dense representation)指的是向量大多数分量为非零,信息分布在多个维度上。
从几何视角看,$E$ 为每个 token 分配了一个点;训练过程则不断移动这些点,使得在预测任务上“该靠近的更靠近,该远离的更远离”。这种移动并非凭空发生,而是由语境统计驱动,这一点将在下一节展开。
可学习性:从“符号身份”到“语义特征”
one-hot 只有身份,没有特征。embedding 的每个维度都可以被看作某种抽象特征轴,但它通常难以被直接解释为人类可读的属性(例如“是否为动物”“是否为地点”)。这不是缺陷,而是一种效率:模型用分布式方式编码特征,每个维度共同贡献语义。
在分布式表示中,“相似”变得可计算:我们可以用余弦相似度或点积衡量两个 token 的相近程度。更进一步,我们可以用向量差异表达关系(尽管这类类比并不总是稳健)。至少在直觉层面,向量空间为“语义结构”提供了可操作的对象。
一个小例子:从相似度到最近邻
假设嵌入维度 $d=3$,并且训练后得到:
- “猫”:$(0.9,0.1,0.2)$
- “狗”:$(0.8,0.2,0.1)$
- “桌子”:$(0.1,0.9,0.7)$
则“猫”与“狗”的内积更大、夹角更小,而与“桌子”差异更大。即使我们不知道每个维度代表什么,这种邻近结构仍可用于检索、聚类与下游任务。重要的是:这种结构来自数据与任务,而不是人为规定。
与注意力的连接:点积几何的入口
自注意力机制会对“查询向量”和“键向量”做点积,再经 softmax 得到权重。点积的意义在于衡量两个向量的对齐程度。因此,embedding 层不仅提供“词的表示”,也提供后续几何运算的起点:没有连续向量,就没有可微的相似度;没有相似度,就没有注意力的权重分配。
分布式假设:语义来自语境统计
到目前为止,我们只是声明“向量能学出语义”。真正的问题是:语义凭什么会出现在向量里?答案来自语言学与统计学习交汇处的一条经验原则:分布式假设(distributional hypothesis)。
核心命题:相似语境 → 相似意义
分布式假设通常被概括为:“You shall know a word by the company it keeps.” 若两个词出现在相似的上下文中,它们往往语义相近。将其转译为更可计算的形式就是:
- 定义“上下文窗口”(context window),统计词与词的共现(co-occurrence)。
- 用这些统计信号驱动向量更新,使得共现结构在几何上可被压缩与表达。
这不是严格定理,而是一条在大规模语料上反复验证的经验规律。它解释了为什么即便没有人工标注,仅凭预测下一个 token 这样的自监督任务,模型也能学到大量语义与知识:因为预测任务迫使模型利用语境统计。
从共现矩阵到低维几何:一个可视化的桥
设词表大小为 $|V|$,构造共现矩阵 $C\in\mathbb{R}^{|V|\times|V|}$,其中 $C_{ij}$ 表示 token $i$ 与 token $j$ 在窗口内共同出现的次数(或某种加权计数)。$C$ 极大、稀疏且噪声多,但它包含“谁与谁一起出现”的结构信息。
经典词向量方法(如基于矩阵分解的思想)可以被理解为:寻找低维向量 $u_i, v_j\in\mathbb{R}^d$,使得 \[ u_i^\top v_j \approx \text{某种与 }C_{ij}\text{ 相关的量}. \] 也就是说,用低维点积去逼近高维共现结构。这一思路与神经网络训练出的 embedding 在精神上相通:都是把高维统计关系压缩进低维几何。
> 引用(重点):分布式表示不是把“意义”硬编码进向量,而是把“可预测性”编码进向量;而可预测性由语境统计支撑。
数据支撑:长尾、共现稀疏与子词策略
在真实语料中,绝大多数 token 的出现次数很少,共现矩阵因此更稀疏。长尾现象意味着:如果只按整词建表,许多低频词几乎没有足够统计信号来学习稳定向量。子词 tokenization 的一个重要收益是把统计“聚合”到更常见的片段上:即便某个新词从未出现,它的子词仍有统计基础,从而能组合出较合理的表示。这就是“覆盖性”与“可学习性”之间的折中。
统一符号表:本书后续推导的共同语言
为了在纸书与电子版中保持符号一致,本书约定以下常用记号(后续章节将频繁使用):
- 词表大小:$|V|$
- 词元(token):$t$,词元序列:$(t_1,\dots,t_n)$
- 词元 ID:$i=V(t)$,ID 序列:$(i_1,\dots,i_n)$
- one-hot 向量:$x(t)\in\{0,1\}^{|V|}$
- 嵌入维度:$d$
- 嵌入矩阵:$E\in\mathbb{R}^{|V|\times d}$
- 嵌入向量:$e(t)\in\mathbb{R}^d$,常写作 $e_i$ 表示第 $i$ 个 ID 的向量
- 内积:$a^\top b$,向量范数:$\|a\|$,余弦相似度:$\cos(a,b)$
> 侧栏(电子版用法):读到公式中不熟悉的符号时,可回到本节作为“全书符号索引”。在电子版中可将术语链接到此处,例如:[嵌入矩阵](#统一符号表本书后续推导的共同语言)。
案例:从一句话走完“符号→向量”的全流程
下面用一个尽量贴近工程实践、又足够小的例子,把各步骤串起来。设有文本:
“我喜欢注意力机制。”
第一步:tokenization 与编码
可能的一种切分是:`["我", "喜欢", "注意力", "机制", "。"]` 映射到 ID:`[10, 532, 2031, 778, 3]`
不同 tokenizer 会产生不同切分(例如把“注意力机制”作为一个 token,或拆得更细),但不影响本章的核心:输出是一串整数。
第二步:one-hot(概念上)与 embedding(实现上)
概念上,ID=2031 对应 one-hot 向量 $x\in\{0,1\}^{|V|}$,第 2031 位为 1。 实现上,模型直接查表得到向量 $e_{2031}\in\mathbb{R}^d$。
第三步:相似度进入计算图
当模型需要判断“注意力”与“机制”的关联时,它将用后续网络把这些 embedding 变换为新的向量(例如注意力中的 $q,k,v$),再用点积评估相关性。换言之,embedding 是进入“注意力几何”的入口坐标。
```python import numpy as np
假设词表大小与嵌入维度
V = 50000 d = 768
嵌入矩阵(训练时是可学习参数)
E = np.random.randn(V, d) * 0.02
def embedding_lookup(token_id: int) -> np.ndarray: return E[token_id] # 等价于 one-hot @ E
ids = [10, 532, 2031, 778, 3] vectors = [embedding_lookup(i) for i in ids]
计算两个 token 向量的余弦相似度
def cos(a, b): return float(a @ b / (np.linalg.norm(a) * np.linalg.norm(b)))
print("sim(2031, 778) =", cos(vectors[2], vectors[3])) ```
这段代码刻意回避了训练细节,只强调结构:输入是 ID,输出是向量;相似度可以通过内积或余弦得到。真实模型中 $E$ 不是随机的,而是通过大规模语料训练得到,使得相似语境的 token 在几何上更接近。
对比总结:one-hot 与稠密表示的关键差异
为了便于纸书阅读,这里用条目式归纳两者差异,并指出它们在大模型中的地位分工。
- **维度**:one-hot 维度为 $|V|$(通常数万),embedding 维度为 $d$(通常数百到上千)。
- **信息结构**:one-hot 只有身份;embedding 是分布式特征,信息分散在多个维度。
- **相似度**:one-hot 两两正交,无法表达语义相近;embedding 可通过内积/余弦形成邻近结构。
- **可学习性**:one-hot 本身不可“学出相似性”;embedding 在任务驱动下可调整几何位置。
- **工程实现**:one-hot 常作为概念工具;embedding 以查表方式高效实现,并与后续矩阵运算无缝衔接。
需要强调的是:embedding 并不是“把词典定义得更漂亮”,而是把语言映射进一个可优化、可度量、可组合的空间,使得后续的注意力、前馈网络与概率建模可以统一在同一套线性代数框架下运行。
小结:从符号到向量,为注意力的几何做准备
本章建立了全书最基础的一条链路:文本经过 tokenization 与词表编码成为 ID 序列,再通过 one-hot 的等价线性变换进入 embedding 空间。one-hot 展示了离散身份如何进入计算图,但其稀疏高维与“无相似度”使它不适合作为语义表示;embedding 以低维稠密向量承载可学习的几何结构,并通过