← cd ../posts

词向量小史:从 one-hot 到 embedding

2026-05-27

AI 系列第 6 篇。上一篇讲了 Transformer 是怎么把整句话并行处理的。 这一篇回头补一课:那些被丢进 Transformer 的"词",本身是怎么变成向量的? 你会发现,词向量 这个概念,是过去 15 年 NLP 最被低估、也最重要的发明。

0. 一个被忽略的根本问题

我们已经讲了好几篇神经网络。但有件事我们一直含糊带过——

神经网络只能处理数字。一段文字怎么进去?

input: "今天天气真好"
   ▼
神经网络: ??? 这是什么乱码?

机器看不懂中文。也看不懂英文。它只懂浮点数向量。所以在所有 NLP 工作之前,必须先把字符串变成数字。这就是 embedding(词嵌入)的任务。

听起来好像无关紧要的预处理?错。embedding 决定了模型能"理解"的语义粒度。embedding 做得不好,后面再厉害的 Transformer 也救不了。

这一篇我们就讲:人类是怎么花了 60 年,才搞清楚"机器眼里的词"应该长什么样的。


1. 第一代:one-hot 编码——"暴力但天真"

最朴素的想法:给每个词一个编号。

词典:
  "今天" → 0
  "天气" → 1
  "真好" → 2
  "下雨" → 3
  "可惜" → 4
  ...   (总共 5 万个词)

但直接用编号不行——神经网络会把"3"当成"比 2 大、比 4 小"的有序数字,而实际上"下雨"和"真好"之间没有任何"大小关系"。

解决方案:one-hot 向量

"今天" → [1, 0, 0, 0, 0, ...]   ← 第 0 位是 1
"天气" → [0, 1, 0, 0, 0, ...]   ← 第 1 位是 1
"真好" → [0, 0, 1, 0, 0, ...]   ← 第 2 位是 1

每个词被表示成一个 5 万维的向量,只有自己那一位是 1,其他全是 0。

one-hot 的两个致命缺陷

缺陷 1:维度灾难

一个英文词典有 50 万词。一个 5 万词的 one-hot 向量乘以一个全连接层,参数量就要爆炸:

输入 50000 维 × 隐藏层 1024 维 = 5120 万个参数

光是第一层就 5000 万参数。整个网络?吓人。

缺陷 2:所有词都"等距离"

"猫" → [1, 0, 0, ...]
"狗" → [0, 1, 0, ...]
"汽车" → [0, 0, 1, ...]

在 one-hot 空间里,"猫"和"狗"的距离 = "猫"和"汽车"的距离 = √2。

模型根本无法知道"猫"和"狗"语义相近、"猫"和"汽车"不相关。 每个词都是孤岛。

这就是 one-hot 的根本问题——它编码了身份,但没编码意义


2. 中间过渡:词频统计与 LSA(1957 → 2000s)

人们很早就想:能不能让"语义相近的词"在向量空间里"距离相近"?

1957 年,语言学家 J.R. Firth 说过一句被引爆的话:

"You shall know a word by the company it keeps."一个词的意思,由它经常和谁一起出现来定义。

这就是 分布假说(distributional hypothesis)。它的逻辑是:

  • "猫"经常和"狗"、"宠物"、"喵"、"喂食"一起出现。
  • "汽车"经常和"司机"、"轮胎"、"加油"、"高速"一起出现。
  • 所以"猫"和"狗"的"邻居词集"高度重合 → 它们语义相近。

LSA:第一个把这个假说落地的方法

1988 年 出现的 LSA(Latent Semantic Analysis) 就是这个思路:

  1. 建一个超大的"词-文档"矩阵:行是词,列是文档,单元格是词频。
  2. 用矩阵分解(SVD)压缩到几百维。
  3. 每个词变成一个 300 维的稠密向量。

这是历史上第一次把词变成"低维稠密向量"。但 LSA 的问题是它只用了统计,没有学习。给定一个新句子,它没法处理。

90 年代到 2000 年代,词表示一直停留在"统计 + 降维"的阶段。神经网络派偶尔在尝试,但因为算力不够,效果不显著。


3. 2013:word2vec——那个让"国王 − 男人 + 女人 ≈ 女王"成立的算法

2013 年 1 月,Google 的 Tomas Mikolov 团队发了两篇论文,提出了 word2vec。这是词向量史上最重要的一个里程碑。

word2vec 的核心思想还是 Firth 那句话——用上下文定义词义。但它用神经网络来学。

训练目标:从上下文预测词(或反过来)

word2vec 有两种训练方式:

方式 1:CBOW(Continuous Bag of Words)—— 用周围猜中间

输入: ["今天", "天气", ___, "出去", "玩"]
任务: 猜 ___ 是什么词
答案: "不错"

方式 2:Skip-gram —— 用中间猜周围

输入: "不错"
任务: 猜它周围最可能出现的词
答案: ["今天", "天气", "出去", "玩"]

训练时,给模型 1000 亿条这样的句子。模型为了猜对,必须学会一件事:让经常出现在相似上下文里的词,向量靠近

训完之后,每个词得到一个 300 维的稠密向量。

让全世界震惊的发现

word2vec 训完后,研究者发现这些向量有数学结构

vec("国王") − vec("男人") + vec("女人") ≈ vec("女王")
vec("Paris") − vec("France") + vec("Italy") ≈ vec("Rome")
vec("walked") − vec("walk") + vec("swim") ≈ vec("swam")

这就是著名的 word analogy(词类比)。它说明 word2vec 不只是把相似的词放近,它还把"语义关系"编码成了向量空间里的方向

  • "国王 → 男人"和"女王 → 女人"是平行的方向 = 性别关系。
  • "Paris → France"和"Rome → Italy"是平行的方向 = 首都-国家关系。
  • "walked → walk"和"swam → swim"是平行的方向 = 过去时关系。

模型没人教过它"性别"或"时态"这些概念。它自己从数据里涌现出来了。

一句你可以拿去吹的话: word2vec 第一次让人类相信:神经网络不只是在做分类、回归。它能从纯文本里,自动提取出语言学家几百年来一直在研究的"语义结构"。

word2vec 的影响

2013 之后,几乎所有 NLP 任务都先跑一遍 word2vec 拿到词向量,再喂进下游模型。

[原始文本] → [word2vec] → [词向量] → [LSTM/CNN] → [任务输出]

这成了 2013–2018 的标配流水线。word2vec 那篇论文今天引用 4 万次。


4. 2014 年:GloVe——把统计派和神经派合一

word2vec 几乎完美,但有个理论上的不满——它只用了局部窗口(左右几个词),没用全局统计。

2014 年,斯坦福的 Pennington、Socher、Manning 三人提出 GloVe(Global Vectors)。它的目标:让词向量同时反映全局共现统计 + 局部上下文

GloVe 的训练目标可以简化为:

学习词向量 w_i 和 w_j,使得:
   w_i · w_j ≈ log(共现次数(i, j))

直觉是:两个词在语料里一起出现得越多,它们向量的点积越大。

GloVe 在 word analogy 任务上比 word2vec 略好。但俩兄弟的差异已经不大了。2014 之后的几年,word2vec / GloVe 几乎成了同义词


5. 2018:ELMo / BERT——"一个词在不同句子里,应该有不同向量"

word2vec 有个隐性假设:一个词只有一个向量

"我去银行存钱。"
"河边有一棵银行树。"  ← (假设有这个东西)
"银行" → [0.2, -0.3, 0.5, ...]  ← 永远是这个向量

但显然,"银行"在两个句子里意思完全不同。word2vec 把它们混在了同一个向量里,丢了上下文信息。

ELMo:用 LSTM 算"上下文相关"的向量

2018 年 2 月,Allen AI 的研究员提出 ELMo(Embeddings from Language Models)。它的核心改变:

同一个词,在不同句子里,给不同向量。

"我去银行存钱"  → "银行" 向量 ≈ "金融机构"方向
"河边有银行树"  → "银行" 向量 ≈ "植物"方向

ELMo 用一个双向 LSTM 在大语料上预训练,给每个句子里的每个词单独算一个向量。这种向量叫 contextualized embedding(上下文化嵌入)。

BERT:用 Transformer 把这件事做到极致

2018 年 10 月,Google 的 BERT 把 ELMo 的思路推到顶——但用的不是 LSTM,是 双向 Transformer encoder

BERT 的训练任务很有意思——它玩完形填空

原句: "今天天气真好,我想出去散步。"
训练: "今天天气[MASK]好,我想出去[MASK]步。"
任务: 预测 [MASK] 处该填什么

为了猜对 mask,模型必须深度理解上下文。训完之后,BERT 内部每一层对每个词的向量表示,都包含了深度上下文信息

BERT 一出现,几乎所有 NLP benchmark 都被它刷爆——情感分类、问答、命名实体识别、相似度…… 2018 年是 NLP 圈的"BERT 之年"

一句你可以拿去吹的话: 从 word2vec 到 BERT,词向量经历了从"一个词一个固定向量"到"一个词在每个句子里都有专属向量"的范式转换。这是 NLP 史上第一次,机器能"读懂语境"。


6. 今天的 LLM:embedding 已经"看不见"了

ChatGPT、Claude、Llama 这些大模型里还有 embedding 吗?有,但它已经被深度藏起来了。

现代 LLM 处理一段文本的完整流程:

"今天天气真好"
   │
   ▼
[Tokenizer] 把文本切成 token   →  ["今", "天天气", "真好"]
   │
   ▼
[Embedding Layer] 把每个 token 转成向量
                                  → [v_1, v_2, v_3]
                                    每个 v_i 大约 4096 维
   │
   ▼
[Transformer 96 层]
   │
   ▼
最终输出

Embedding Layer 就是一个查找表:input 是 token id(一个整数),output 是一个固定的向量。这个表的大小是 vocab_size × hidden_dim

GPT-3 的 vocab 是 50,257 个 token,hidden_dim 是 12,288。embedding 表就是:

50,257 × 12,288 = 6.17 亿个参数

光这个表就比 BERT 整个模型还大。

但这是 word2vec 那种"独立学习"的 embedding 吗?

不是。现代 LLM 的 embedding 是端到端学的——和整个网络一起训练,不再单独搞一个 word2vec 步骤。

1990s:  one-hot                 ── 静态、稀疏
2013:   word2vec / GloVe        ── 静态、稠密、独立预训练
2018:   ELMo / BERT             ── 上下文化、独立预训练
2020+:  现代 LLM 内嵌 embedding   ── 上下文化、端到端学

Embedding 在今天还有什么用?

虽然 LLM 把 embedding 内化了,但作为单独工具的 embedding 模型反而越来越火。原因是 RAG 和向量搜索

1. 把所有知识库文档切成小段。
2. 用 embedding 模型把每段编成一个向量。
3. 用户问问题时,把问题也变成向量。
4. 在向量库里找"距离最近"的几段。
5. 把这几段 + 问题一起喂给 LLM。

这就是 RAG(Retrieval-Augmented Generation)的核心。今天主流的 embedding 模型:

  • OpenAI text-embedding-3-large
  • Cohere embed-v3
  • BGE / GTE(开源)
  • Voyage AI voyage-3

这些模型本质上都是 BERT 的变种,专门优化了"语义相似度"。今天创业公司搞 RAG 时,第一步就是挑一个 embedding 模型——这又把 word2vec 时代的"独立 embedding 训练"思路带了回来。


7. 关于 tokenizer:embedding 之前还有一步

讲到这要补一刀:embedding 不是直接作用在"词"上的,是作用在 token 上的。

token 是什么?是 tokenizer 切分出来的"子词"。例如 GPT 的 BPE tokenizer:

"GPT-4 是 OpenAI 发布的模型"
   │
   ▼ tokenize
["GPT", "-", "4", " 是", " Open", "AI", " 发布", "的", "模型"]
   │
   ▼ token ids
[3877, 12, 19, 1234, 9012, ...]
   │
   ▼ embedding layer
[v_1, v_2, v_3, ...]

注意几件事:

  • "GPT-4" 被切成了 GPT, -, 4 三个 token。
  • " 是" 包含前导空格(GPT BPE 这么干)。
  • "OpenAI" 被切成 Open + AI,不在一个 token 里。

中文也是同理。一个汉字可能是一个 token,也可能两三个汉字组成一个 token,看 tokenizer 怎么训的。

这是为什么 LLM 偶尔会犯一些"低级错误"——比如数不清 "strawberry" 里有几个 r。因为它看到的是 token,不是字符。

第 10 篇会专门讲 tokenizer 和 context window 的故事。


8. 总结这条线

1957  分布假说:"一个词由它的邻居定义"
1988  LSA:用矩阵分解把这个假说落地
2013  word2vec:用神经网络把它落地,规模爆炸
2014  GloVe:统计派 + 神经派合一
2018  ELMo / BERT:上下文化 embedding,"一词多向量"
2020+ 现代 LLM:embedding 端到端集成

一句你可以拿去吹的话: 从"词是一个独热编号"到"词是一个 12288 维的上下文相关向量",机器对语言的理解走了 60 年。但真正的飞跃,只在最后 10 年。


9. 给你的小作业

  1. gensim 这个 Python 库加载预训练 word2vec,试试 vec('国王') - vec('男人') + vec('女人') 最近的几个词是什么。 提示:可能不只是"女王",还会有"王后"、"公主"等。
  2. 解释为什么 word2vec 给"银行"只有一个向量,而 BERT 给不同句子里的"银行"不同向量。
  3. 写一段伪代码描述 RAG 的工作流程,明确指出 embedding 在哪里发挥作用。

下一篇钩子:到这里,我们已经把"模型怎么读懂顺序"和"词怎么变成向量"都搞清楚了。 下一篇起,我们正式进入大模型时代—— GPT-1 (2018)、GPT-2 (2019)、GPT-3 (2020)、GPT-3.5 (2022)、GPT-4 (2023)、GPT-4o / o1 (2024–2025),每一代到底变了什么? 答案可能让你意外:架构基本没变。变的是规模、数据、训练技巧——以及一些你以为是"smarter"的小动作。