词嵌入向量(Word Embedding) 是将词语映射到低维稠密实数向量空间的一种表示方法,常见模型包括 Word2Vec、GloVe、FastText,以及现在主流的上下文相关嵌入(如 BERT、GPT 系列),后者同一个词在不同上下文中会得到不同的向量表示。
符号约定
| 符号 | 含义 | 示例 |
|---|
| V | 词汇表 | ∣V∣=104 |
| V | 词汇表大小 | V=∣V∣ |
| d | 词嵌入向量维度 | d=300(典型值) |
| wt | 位置 t 处的中心词 | wt="apple" |
| wt+j | 位置 t+j 处的上下文词 | wt−1="eat" |
| m | 上下文窗口大小 | m=2(两侧各 2 个词) |
| vw∈Rd | 词 w 作为中心词的嵌入向量 | 输入向量 |
| uw∈Rd | 词 w 作为上下文词的嵌入向量 | 输出向量 |
| Win∈Rd×V | 输入嵌入矩阵 | 每一列是一个词的 vw |
| Wout∈RV×d | 输出嵌入矩阵 | 每一行是一个词的 uw |
1. 从 One-Hot 到分布式表示#
1.1 One-Hot 的困境#
在 word2vec 之前,词的标准表示是 one-hot 向量:每个词 w 被表示为一个长度为 V 的向量,只有词 w 对应的位置为 1,其余为 0。
例如,词汇表 V={"apple","banana","cat","dog","eat"}:
xapple=10000,xbanana=01000,xeat=00001这种表示有两个致命缺陷:
- 维度灾难:实际词汇表 V 可达 105∼106,向量极其稀疏且高维。
- 语义鸿沟:任意两个词的 one-hot 向量内积为 0,无法表达”apple”和”banana”之间的语义相似性——它们都是水果,但在 one-hot 空间里与”cat”和”apple”的距离完全相同。
直观理解
如果词是城市,one-hot 编码相当于给每个城市分配一个唯一的编号(北京=0001,上海=0002),但从编号中你看不出北京和上海都是中国的大都市,也看不出北京和东京的距离比北京和火星的距离更近。
下面的分布式表示则像是给每个城市一组坐标(经纬度、人口、GDP、气候类型…),语义相近的城市自然在向量空间中靠得更近。
1.2 分布式假设#
word2vec 的核心思想来自 分布式假设(Distributional Hypothesis):
“You shall know a word by the company it keeps.” — J.R. Firth, 1957
也就是一个词的语义可以由它周围的上下文词来刻画。
考虑以下句子:
The cat sits on the mat.
在”cat”的上下文中,我们频繁看到”the”、“sits”、“mat”等词;而在”dog”的上下文中,我们也会频繁看到”the”、“sits”、“mat”、“barks”等词。因为”cat”和”dog”有大量相似的上下文,它们的词向量应当相似。
2. Skip-gram 模型#
Skip-gram 的目标是:
给定中心词 wt,预测其上下文窗口内的词 wt+j(j∈{−m,…,−1,1,…,m})。
Skip-gram 需要训练的参数是两套词嵌入向量矩阵:
- 输入嵌入矩阵 Win∈Rd×V(每列是中心词向量 vw)
- 输出嵌入矩阵 Wout∈RV×d(每行是上下文词向量 uw)
每个词 w 对应两个嵌入向量:作为中心词时的 vw 和作为上下文词时的 uw。总参数量为 2⋅V⋅d。实际使用中通常取 Win(或 2vw+uw)作为最终词向量。
2.1 模型结构以及前向传播#
Skip-gram 是一个极简的两层神经网络:
输入层 (one-hot) → 隐藏层 (d维) → 输出层 (V维 softmax)
对于隐藏层,设中心词 wt 的 one-hot 向量为 x∈RV(只有 wt 对应位置为 1),则:
h=Winx=vwt因为 x 是 one-hot 的,隐藏层向量 h 本质上就是从 Win 中”查表”取出词 wt 对应的列向量 vwt。这是 embedding lookup 操作。
隐藏层 h 就是中心词的嵌入向量 vwt,一个 d 维的稠密向量,
和普通神经网络不同:
- 没有偏置项:h=Winx,无 +b
- 没有激活函数:不经过 tanh/ReLU 等非线性变换
- 没有多个隐藏层:就这一层 embedding lookup
它本质上就是一个线性投影:把 V 维的 one-hot 稀疏向量,映射为 d 维的稠密向量。整个模型的非线性只来自 输出层 的 softmax(或负采样中的 sigmoid)。
embedding-lookup举例
把矩阵展开来看就清楚了。假设 V=4,d=3,词汇表为 {apple, banana, cat, eat}。
Win∈R3×4,每一列是一个词的中心词向量:
Win=↑vapple↓↑vbanana↓↑vcat↓↑veat↓=0.20.40.90.50.10.70.10.60.20.80.30.5现在中心词是 cat,其 one-hot 向量为 x=[0,0,1,0]T(4×1 列向量)。
h=Win⋅x=0.20.40.90.50.10.70.10.60.20.80.30.5⋅0010=0.10.60.2=vcat
对于输出层,每个上下文词 wo 的得分,就是用uwo (是词 wo 作为上下文词时的 d 维向量,存放在 Wout 中) 与中心词向量 vwt 作 内积 :
score(wo∣wt)=uwoTvwts=Wout⋅h=Wout⋅vwt输出举例
Wout∈RV×d,每一行是一个词的 uw。沿用 V=4,d=3 的例子:
Wout=←←←←uappleTubananaTucatTueatT→→→→=0.30.50.40.80.10.90.60.30.70.20.10.5输出层计算所有词的得分,就是矩阵乘:
s=Wout⋅h=Wout⋅vwt对于 wt="cat",vcat=[0.1,0.6,0.2]T:
s=0.30.50.40.80.10.90.60.30.70.20.10.5⋅0.10.60.2=score(apple∣cat)score(banana∣cat)score(cat∣cat)score(eat∣cat)其中 score(apple∣cat)=0.3⋅0.1+0.1⋅0.6+0.7⋅0.2=uappleTvcat。
经过 softmax 归一化得到概率:
P(wo∣wt)=∑w∈Vexp(uwTvwt)exp(uwoTvwt)
当前步骤
选择中心词
点击下方词汇表中的词,将其设为 中心词 wt。
2.2 损失函数与参数更新#
Skip-gram 的训练目标很朴素:让模型看到中心词 wt 时,预测出真实上下文词 wo 的概率尽可能大。
极大似然估计+对数变换#
给定一个语料库 D,包含所有 (中心词, 上下文词) 对,我们希望最大化所有观测数据的联合概率,用 极大似然估计(Maximum Likelihood Estimation, MLE)
max(wt,wo)∈D∏P(wo∣wt)取对数后,连乘变成连加,单调性不变:
max(wt,wo)∈D∑logP(wo∣wt)梯度下降默认做最小化,所以加个负号,把最大化问题转化为最小化问题:
min(wt,wo)∈D∑−logP(wo∣wt)对于单对 (wt,wo),损失函数为:
J=−logP(wo∣wt)=−uwoTvwt+logw∈V∑exp(uwTvwt)与交叉熵的等价性#
负对数似然本质上就是交叉熵损失。真实分布 y 是关于 wo 的 one-hot 向量(ywo=1,其余为 0),模型预测分布 y^=P(⋅∣wt)。交叉熵 H(y,y^)=−∑wywlogy^w 展开后只有 wo 那一项非零,恰好等于 −logP(wo∣wt):
H(y,y^)=−w∈V∑ywlogP(w∣wt)=−logP(wo∣wt)所以最小化负对数似然,等价于最小化真实分布与预测分布之间的交叉熵。
内积作为相似度
uwoTvwt 是两个向量的内积。如果中心词向量 vcat 和上下文词向量 usits 的内积很大,说明模型认为”cat”和”sits”经常共现,softmax 会给 P("sits"∣"cat") 分配较高的概率。
训练的目标是:让真实共现的词对 (vwt,uwo) 内积变大,让随机词对的内积变小。
梯度推导#
对 vwt(中心词向量)求梯度。损失函数由两项组成:
J=第一项−uwoTvwt+第二项logw∈V∑exp(uwTvwt)第一项直接求导:∂vwt∂(−uwoTvwt)=−uwo。
第二项需要链式法则。设 S=∑w∈Vexp(uwTvwt),则第二项为 logS:
∂vwt∂logS=S1⋅∂vwt∂S对 S 求导,exp(uwTvwt) 的导数是 exp(uwTvwt)⋅uw:
∂vwt∂S=w∈V∑exp(uwTvwt)⋅uw代回:
∂vwt∂logS=∑w′∈Vexp(uw′Tvwt)1⋅w∈V∑exp(uwTvwt)⋅uw=w∈V∑∑w′∈Vexp(uw′Tvwt)exp(uwTvwt)⋅uw=w∈V∑P(w∣wt)⋅uw两项合并,得到最终梯度:
∂vwt∂J=−uwo+w∈V∑P(w∣wt)⋅uw第二项是所有输出向量 uw 的加权平均,权重恰好是模型当前预测的概率分布 P(w∣wt)。换句话说,它是模型对输出向量的期望 Ew∼P(⋅∣wt)[uw]。第一项 −uwo 将中心词向量 vwt 「拉向」真实上下文词的向量 uwo;第二项则将 vwt 「推开」所有词(按模型当前置信度加权),防止模型把所有词都预测成高频词。当二者平衡时,梯度为零,模型收敛。
这就是 softmax 的瓶颈所在:每次更新都需要对全体词汇表 V 求和,当 V=105 时计算量不可接受。
对输出向量 uw 的梯度同样重要,推导过程类似:
∂uw∂J=(P(w∣wt)−δw,wo)⋅vwt其中 δw,wo=1 当 w=wo(真实上下文词),否则为 0。
- 对于真实上下文词 wo:P(wo∣wt)−1<0,梯度为负,uwo 向 vwt 靠拢。
- 对于其他词 w=wo:P(w∣wt)>0,梯度为正,uw 远离 vwt。
参数更新#
反向传播需要前向传播的中间结果。具体来说:
| 前向输出 | 反向传播中的用途 |
|---|
| P(w∣wt)(所有词的 softmax 概率) | 计算 ∂vwt∂J 和 ∂uw∂J 都需要 |
| vwt(中心词向量,即隐藏层 h) | 所有 ∂uw∂J 的梯度中共用 |
| uwo(真实上下文词的输出向量) | ∂vwt∂J 的第一项直接用到 |
训练时,对每个 (中心词, 上下文词) 对,用梯度下降同时更新两个矩阵:
vwt←vwt−η⋅∂vwt∂J,uw←uw−η⋅∂uw∂J(∀w∈V)注意 Wout 中的每一行 uw 都会被更新——因为每个词都参与了 softmax 分母的计算。这也是 softmax 计算量大的根源。
当前步骤
前向传播 · softmax 输出
模型预测 P(wo | "cat"),其中 "sits" 仅得 3.0%,损失 J = 3.50
3. CBOW 模型#
CBOW(Continuous Bag of Words)是 Skip-gram 的镜像:给定上下文词 {wt−m,…,wt−1,wt+1,…,wt+m},预测中心词 wt。
对于一个上下文窗口 Ct={wt+j:j∈{−m,…,m},j=0},将上下文词向量取平均:
h=∣Ct∣1w∈Ct∑vw然后送入 softmax:
P(wt∣Ct)=∑w∈Vexp(uwTh)exp(uwtTh)CBOW 将多个上下文词的信息聚合到一个向量中,训练速度比 Skip-gram 快(因为一次预测一个中心词,而 Skip-gram 一次预测 2m 个上下文词),但对稀有词的表示效果略差。
| 模型 | 输入 | 输出 | 适合 | 训练速度 |
|---|
| Skip-gram | 1 个中心词 | 2m 个上下文词 | 稀有词、小数据集 | 慢 |
| CBOW | 2m 个上下文词 | 1 个中心词 | 高频词、大数据集 | 快 |
CBOW 的参数结构与 Skip-gram 完全相同——仍然需要训练两套词向量:
- Win∈Rd×V:输入嵌入矩阵,每列是词 w 作为上下文词时的向量 vw
- Wout∈RV×d:输出嵌入矩阵,每行是词 w 作为中心词时的向量 uw
总参数量同样是 2⋅V⋅d。
但更新的对象不同。一次 CBOW 训练中:
- 对 Win:更新上下文窗口内所有 2m 个词的 vw(Skip-gram 一次只更新 1 个中心词)
- 对 Wout:只需要更新中心词 wt 对应的 uwt(Skip-gram 需要更新所有 V 个词)
因为 CBOW 的输出端只需要对 1 个词求梯度,而 Skip-gram 需要对 2m 个词分别求梯度并累加,所以 CBOW 训练更快。但代价是 CBOW 对每个上下文词只更新了一次(平均后梯度被稀释),对稀有词的学习不如 Skip-gram 充分。这也解释了为什么 Skip-gram 对稀有词更友好——每个稀有词作为中心词时都会被单独训练。
4. 近似训练方法#
softmax 分母 ∑w∈Vexp(uwTvwt) 需要对所有 V 个词求和,计算量 O(V)。两种近似方法将复杂度降到 O(logV) 或 O(k)。
4.1 负采样(Negative Sampling)#
负采样的核心思想:不必对所有负例建模,只需随机采样 k 个”噪声词”作为负例。
对于每个正样本 (wt,wo),随机采样 k 个噪声词 {w1,…,wk},目标函数变为:
J=−logσ(uwoTvwt)−i=1∑klogσ(−uwiTvwt)其中 σ(x)=1+e−x1 是 sigmoid 函数。
直观理解
这本质上是一个二分类问题:对于每个词对,模型需要判断它们是”真实共现”(正例)还是”随机配对”(负例)。
- σ(uwoTvwt):模型认为 (wt,wo) 是真实共现的概率
- σ(−uwiTvwt):模型认为 (wt,wi) 不是真实共现的概率
和 softmax 的区别在于:softmax 对所有词做 V-分类;负采样对每个词对做独立的二分类,只需计算 k+1 次 sigmoid。
噪声词的采样分布通常为:
P(w)∝count(w)3/43/4 次幂的作用是提升低频词的采样概率,防止它们被完全忽略。
4.2 层次 Softmax(Hierarchical Softmax)#
另一种思路:用 Huffman 树将 V-分类转化为 logV 次二分类。
将词汇表中的每个词放在 Huffman 树的叶子节点上(高频词路径短,低频词路径长)。对于中心词 wt,预测上下文词 wo 的概率为从根节点走到 wo 叶子节点的路径上各次二分类概率的乘积:
P(wo∣wt)=l=1∏L(wo)−1σ([[n(wo,l+1)=left(n(wo,l))]]⋅un(wo,l)Tvwt)其中 L(wo) 是路径长度,n(wo,l) 是路径上第 l 个节点,[[⋅]] 是指示函数(走左子树为 +1,右子树为 −1)。
直观理解
想象一个猜词游戏。softmax 的做法是:一次列出所有 V 个词,直接选一个。层次 softmax 的做法是:不断问”是水果吗?”→“是红色的吗?”→“是苹果吗?“,每次只需做二选一。
Huffman 编码保证高频词路径短,所以平均只需 log2V 次二分类。
5. 词向量的语义性质#
训练完成后,word2vec 的词向量展现出令人惊讶的语义结构。
5.1 类比推理#
最经典的例子:
vking−vman+vwoman≈vqueen向量运算捕捉到了”性别”这个语义维度:从”king”中减去”man”的语义,加上”woman”的语义,得到”queen”。
其他类比:
- vParis−vFrance+vItaly≈vRome(首都-国家关系)
- vwalking−vwalk+vswim≈vswimming(动词时态)
5.2 为什么会出现线性结构?#
负采样的目标函数可以重写为点互信息(Pointwise Mutual Information, PMI)的矩阵分解:
uwTvc≈PMI(w,c)−logk其中 PMI(w,c)=logP(w)P(c)P(w,c) 衡量两个词的实际共现频率与随机共现频率之比。这说明 word2vec 本质上在做共现矩阵的隐式分解,将高维稀疏的 PMI 矩阵压缩为低维稠密的词向量。
6. 从 word2vec 到现代 LLM#
word2vec 奠定了现代 NLP 的基石,但也存在局限性:
| 方面 | word2vec | 现代 LLM (Transformer) |
|---|
| 词表示 | 静态:每个词只有一个固定向量 | 上下文相关:同一个词在不同句子中向量不同 |
| 多义词处理 | 无法区分”bank”(银行/河岸) | 根据上下文自动消歧 |
| 上下文范围 | 固定窗口 m | 自注意力机制,理论上无限长 |
| 训练目标 | 预测邻居词 | 预测下一个 token(语言模型) |
具体来说,word2vec 训练出的词向量是静态的:无论”bank”出现在”river bank”还是”central bank”中,它都使用同一个向量。而 Transformer 的 self-attention 机制会为每个词生成上下文相关的表示——这正是我们已经在 Transformer 编码器核心:self-attention 中详细讨论过的。
然而,word2vec 的核心思想——用低维稠密向量表示词,通过共现信息学习语义——仍然是所有现代词嵌入方法(包括 BERT、GPT 的 embedding 层)的基础。在下一节中,我们将看到 GloVe 如何改进 word2vec 的统计信息利用,以及 BPE 子词嵌入如何解决 OOV 问题。
参考文献#
- Mikolov, T., et al. (2013). Efficient Estimation of Word Representations in Vector Space. arXiv:1301.3781.
- Mikolov, T., et al. (2013). Distributed Representations of Words and Phrases and their Compositionality. NIPS 2013.
- Goldberg, Y., & Levy, O. (2014). word2vec Explained: Deriving Mikolov et al.’s Negative-Sampling Word-Embedding Method. arXiv:1402.3722.