9794 字
49 分钟
词嵌入基础:word2vec

词嵌入向量(Word Embedding) 是将词语映射到低维稠密实数向量空间的一种表示方法,常见模型包括 Word2Vec、GloVe、FastText,以及现在主流的上下文相关嵌入(如 BERT、GPT 系列),后者同一个词在不同上下文中会得到不同的向量表示。

符号约定
符号含义示例
V\mathcal{V}词汇表V=104\vert\mathcal{V}\vert = 10^4
VV词汇表大小V=VV = \vert\mathcal{V}\vert
dd词嵌入向量维度d=300d = 300(典型值)
wtw_t位置 tt 处的中心词wt="apple"w_t = \text{"apple"}
wt+jw_{t+j}位置 t+jt+j 处的上下文词wt1="eat"w_{t-1} = \text{"eat"}
mm上下文窗口大小m=2m = 2(两侧各 2 个词)
vwRd\mathbf{v}_w \in \mathbb{R}^dww 作为中心词的嵌入向量输入向量
uwRd\mathbf{u}_w \in \mathbb{R}^dww 作为上下文词的嵌入向量输出向量
WinRd×V\mathbf{W}_{\text{in}} \in \mathbb{R}^{d \times V}输入嵌入矩阵每一列是一个词的 vw\mathbf{v}_w
WoutRV×d\mathbf{W}_{\text{out}} \in \mathbb{R}^{V \times d}输出嵌入矩阵每一行是一个词的 uw\mathbf{u}_w

1. 从 One-Hot 到分布式表示#

1.1 One-Hot 的困境#

在 word2vec 之前,词的标准表示是 one-hot 向量:每个词 ww 被表示为一个长度为 VV 的向量,只有词 ww 对应的位置为 11,其余为 00

例如,词汇表 V={"apple","banana","cat","dog","eat"}\mathcal{V} = \{\text{"apple"}, \text{"banana"}, \text{"cat"}, \text{"dog"}, \text{"eat"}\}

xapple=[10000],xbanana=[01000],xeat=[00001]\mathbf{x}_{\text{apple}} = \begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \\ 0 \end{bmatrix},\quad \mathbf{x}_{\text{banana}} = \begin{bmatrix} 0 \\ 1 \\ 0 \\ 0 \\ 0 \end{bmatrix},\quad \mathbf{x}_{\text{eat}} = \begin{bmatrix} 0 \\ 0 \\ 0 \\ 0 \\ 1 \end{bmatrix}

这种表示有两个致命缺陷:

  1. 维度灾难:实际词汇表 VV 可达 10510610^5 \sim 10^6,向量极其稀疏且高维。
  2. 语义鸿沟:任意两个词的 one-hot 向量内积为 00,无法表达”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 的目标是:

给定中心词 wtw_t,预测其上下文窗口内的词 wt+jw_{t+j}j{m,,1,1,,m}j \in \{-m, \dots, -1, 1, \dots, m\})。

Skip-gram 需要训练的参数是两套词嵌入向量矩阵:

  • 输入嵌入矩阵 WinRd×V\mathbf{W}_{\text{in}} \in \mathbb{R}^{d \times V}(每列是中心词向量 vw\mathbf{v}_w
  • 输出嵌入矩阵 WoutRV×d\mathbf{W}_{\text{out}} \in \mathbb{R}^{V \times d}(每行是上下文词向量 uw\mathbf{u}_w

每个词 ww 对应两个嵌入向量:作为中心词时的 vw\mathbf{v}_w 和作为上下文词时的 uw\mathbf{u}_w。总参数量为 2Vd2 \cdot V \cdot d。实际使用中通常取 Win\mathbf{W}_{\text{in}}(或 vw+uw2\frac{\mathbf{v}_w + \mathbf{u}_w}{2})作为最终词向量。

2.1 模型结构以及前向传播#

Skip-gram 是一个极简的两层神经网络:

输入层 (one-hot) → 隐藏层 (d维) → 输出层 (V维 softmax)

对于隐藏层,设中心词 wtw_t 的 one-hot 向量为 xRV\mathbf{x} \in \mathbb{R}^V(只有 wtw_t 对应位置为 11),则:

h=Winx=vwt\mathbf{h} = \mathbf{W}_{\text{in}}\mathbf{x} = \mathbf{v}_{w_t}

因为 x\mathbf{x} 是 one-hot 的,隐藏层向量 h\mathbf{h} 本质上就是从 Win\mathbf{W}_{\text{in}} 中”查表”取出词 wtw_t 对应的列向量 vwt\mathbf{v}_{w_t}。这是 embedding lookup 操作。

隐藏层 h\mathbf{h} 就是中心词的嵌入向量 vwt\mathbf{v}_{w_t},一个 dd 维的稠密向量, 和普通神经网络不同:

  • 没有偏置项:h=Winx\mathbf{h} = \mathbf{W}_{\text{in}} \mathbf{x},无 +b+b
  • 没有激活函数:不经过 tanh/ReLU 等非线性变换
  • 没有多个隐藏层:就这一层 embedding lookup

它本质上就是一个线性投影:把 VV 维的 one-hot 稀疏向量,映射为 dd 维的稠密向量。整个模型的非线性只来自 输出层 的 softmax(或负采样中的 sigmoid)。

embedding-lookup举例

把矩阵展开来看就清楚了。假设 V=4,d=3V=4, d=3,词汇表为 {apple, banana, cat, eat}。 WinR3×4\mathbf{W}_{\text{in}} \in \mathbb{R}^{3 \times 4},每一列是一个词的中心词向量:

Win=[vapplevbananavcatveat]=[0.20.50.10.80.40.10.60.30.90.70.20.5]\mathbf{W}_{\text{in}} = \begin{bmatrix} \uparrow & \uparrow & \uparrow & \uparrow \\ \mathbf{v}_{\text{apple}} & \mathbf{v}_{\text{banana}} & \mathbf{v}_{\text{cat}} & \mathbf{v}_{\text{eat}} \\ \downarrow & \downarrow & \downarrow & \downarrow \end{bmatrix} = \begin{bmatrix} 0.2 & 0.5 & 0.1 & 0.8 \\ 0.4 & 0.1 & 0.6 & 0.3 \\ 0.9 & 0.7 & 0.2 & 0.5 \end{bmatrix}

现在中心词是 cat,其 one-hot 向量为 x=[0,0,1,0]T\mathbf{x} = [0, 0, 1, 0]^T(4×1 列向量)。

h=Winx=[0.20.50.10.80.40.10.60.30.90.70.20.5][0010]=[0.10.60.2]=vcat\mathbf{h} = \mathbf{W}_{\text{in}} \cdot \mathbf{x} = \begin{bmatrix} 0.2 & 0.5 & \mathbf{0.1} & 0.8 \\ 0.4 & 0.1 & \mathbf{0.6} & 0.3 \\ 0.9 & 0.7 & \mathbf{0.2} & 0.5 \end{bmatrix} \cdot \begin{bmatrix} 0 \\ 0 \\ 1 \\ 0 \end{bmatrix} = \begin{bmatrix} \mathbf{0.1} \\ \mathbf{0.6} \\ \mathbf{0.2} \end{bmatrix} = \mathbf{v}_{\text{cat}}

对于输出层,每个上下文词 wow_o 的得分,就是用uwo\mathbf{u}_{w_o} (是词 wow_o 作为上下文词时的 dd 维向量,存放在 Wout\mathbf{W}_{\text{out}} 中) 与中心词向量 vwt\mathbf{v}_{w_t}内积

score(wowt)=uwoTvwts=Wouth=Woutvwt\text{score}(w_o \mid w_t) = \mathbf{u}_{w_o}^T \mathbf{v}_{w_t}\\ \mathbf{s}=\mathbf{W}_{\text{out}} \cdot \mathbf{h} = \mathbf{W}_{\text{out}} \cdot \mathbf{v}_{w_t}
输出举例

WoutRV×d\mathbf{W}_{\text{out}} \in \mathbb{R}^{V \times d},每一行是一个词的 uw\mathbf{u}_w。沿用 V=4,d=3V=4, d=3 的例子:

Wout=[uappleTubananaTucatTueatT]=[0.30.10.70.50.90.20.40.60.10.80.30.5]\mathbf{W}_{\text{out}} = \begin{bmatrix} \leftarrow & \mathbf{u}_{\text{apple}}^T & \rightarrow \\ \leftarrow & \mathbf{u}_{\text{banana}}^T & \rightarrow \\ \leftarrow & \mathbf{u}_{\text{cat}}^T & \rightarrow \\ \leftarrow & \mathbf{u}_{\text{eat}}^T & \rightarrow \end{bmatrix} = \begin{bmatrix} 0.3 & 0.1 & 0.7 \\ 0.5 & 0.9 & 0.2 \\ 0.4 & 0.6 & 0.1 \\ 0.8 & 0.3 & 0.5 \end{bmatrix}

输出层计算所有词的得分,就是矩阵乘:

s=Wouth=Woutvwt\mathbf{s} = \mathbf{W}_{\text{out}} \cdot \mathbf{h} = \mathbf{W}_{\text{out}} \cdot \mathbf{v}_{w_t}

对于 wt="cat"w_t = \text{"cat"}vcat=[0.1,0.6,0.2]T\mathbf{v}_{\text{cat}} = [0.1, 0.6, 0.2]^T

s=[0.30.10.70.50.90.20.40.60.10.80.30.5][0.10.60.2]=[score(applecat)score(bananacat)score(catcat)score(eatcat)]\mathbf{s} = \begin{bmatrix} 0.3 & 0.1 & 0.7 \\ 0.5 & 0.9 & 0.2 \\ 0.4 & 0.6 & 0.1 \\ 0.8 & 0.3 & 0.5 \end{bmatrix} \cdot \begin{bmatrix} 0.1 \\ 0.6 \\ 0.2 \end{bmatrix} = \begin{bmatrix} \text{score}(\text{apple} \mid \text{cat}) \\ \text{score}(\text{banana} \mid \text{cat}) \\ \text{score}(\text{cat} \mid \text{cat}) \\ \text{score}(\text{eat} \mid \text{cat}) \end{bmatrix}

其中 score(applecat)=0.30.1+0.10.6+0.70.2=uappleTvcat\text{score}(\text{apple} \mid \text{cat}) = 0.3 \cdot 0.1 + 0.1 \cdot 0.6 + 0.7 \cdot 0.2 = \mathbf{u}_{\text{apple}}^T \mathbf{v}_{\text{cat}}

经过 softmax 归一化得到概率:

P(wowt)=exp(uwoTvwt)wVexp(uwTvwt)P(w_o \mid w_t) = \frac{\exp(\mathbf{u}_{w_o}^T \mathbf{v}_{w_t})}{\sum_{w \in \mathcal{V}} \exp(\mathbf{u}_{w}^T \mathbf{v}_{w_t})}
就绪 · 选择中心词开始 步骤 0 / 4
当前步骤
选择中心词
点击下方词汇表中的词,将其设为 中心词 wt
词汇表 · 点击选择中心词
当前数据
点击中心词后,这里将显示各步骤的数值。

2.2 损失函数与参数更新#

Skip-gram 的训练目标很朴素:让模型看到中心词 wtw_t 时,预测出真实上下文词 wow_o 的概率尽可能大

极大似然估计+对数变换#

给定一个语料库 D\mathcal{D},包含所有 (中心词, 上下文词) 对,我们希望最大化所有观测数据的联合概率,用 极大似然估计(Maximum Likelihood Estimation, MLE)

max(wt,wo)DP(wowt)\max \prod_{(w_t, w_o) \in \mathcal{D}} P(w_o \mid w_t)

取对数后,连乘变成连加,单调性不变:

max(wt,wo)DlogP(wowt)\max \sum_{(w_t, w_o) \in \mathcal{D}} \log P(w_o \mid w_t)

梯度下降默认做最小化,所以加个负号,把最大化问题转化为最小化问题:

min(wt,wo)DlogP(wowt)\min \sum_{(w_t, w_o) \in \mathcal{D}} -\log P(w_o \mid w_t)

对于单对 (wt,wo)(w_t, w_o),损失函数为:

J=logP(wowt)=uwoTvwt+logwVexp(uwTvwt)J = -\log P(w_o \mid w_t) = -\mathbf{u}_{w_o}^T \mathbf{v}_{w_t} + \log \sum_{w \in \mathcal{V}} \exp(\mathbf{u}_{w}^T \mathbf{v}_{w_t})

与交叉熵的等价性#

负对数似然本质上就是交叉熵损失。真实分布 yy 是关于 wow_o 的 one-hot 向量(ywo=1y_{w_o}=1,其余为 0),模型预测分布 y^=P(wt)\hat{y} = P(\cdot \mid w_t)。交叉熵 H(y,y^)=wywlogy^wH(y, \hat{y}) = -\sum_w y_w \log \hat{y}_w 展开后只有 wow_o 那一项非零,恰好等于 logP(wowt)-\log P(w_o \mid w_t)

H(y,y^)=wVywlogP(wwt)=logP(wowt)H(y, \hat{y}) = -\sum_{w \in \mathcal{V}} y_w \log P(w \mid w_t) = -\log P(w_o \mid w_t)

所以最小化负对数似然,等价于最小化真实分布与预测分布之间的交叉熵。

内积作为相似度

uwoTvwt\mathbf{u}_{w_o}^T \mathbf{v}_{w_t} 是两个向量的内积。如果中心词向量 vcat\mathbf{v}_{\text{cat}} 和上下文词向量 usits\mathbf{u}_{\text{sits}} 的内积很大,说明模型认为”cat”和”sits”经常共现,softmax 会给 P("sits""cat")P(\text{"sits"} \mid \text{"cat"}) 分配较高的概率。

训练的目标是:让真实共现的词对 (vwt,uwo)(\mathbf{v}_{w_t}, \mathbf{u}_{w_o}) 内积变大,让随机词对的内积变小。

梯度推导#

vwt\mathbf{v}_{w_t}(中心词向量)求梯度。损失函数由两项组成:

J=uwoTvwt第一项+logwVexp(uwTvwt)第二项J = \underbrace{-\mathbf{u}_{w_o}^T \mathbf{v}_{w_t}}_{\text{第一项}} + \underbrace{\log \sum_{w \in \mathcal{V}} \exp(\mathbf{u}_{w}^T \mathbf{v}_{w_t})}_{\text{第二项}}

第一项直接求导:vwt(uwoTvwt)=uwo\frac{\partial}{\partial \mathbf{v}_{w_t}} (-\mathbf{u}_{w_o}^T \mathbf{v}_{w_t}) = -\mathbf{u}_{w_o}

第二项需要链式法则。设 S=wVexp(uwTvwt)S = \sum_{w \in \mathcal{V}} \exp(\mathbf{u}_{w}^T \mathbf{v}_{w_t}),则第二项为 logS\log S

vwtlogS=1SSvwt\frac{\partial}{\partial \mathbf{v}_{w_t}} \log S = \frac{1}{S} \cdot \frac{\partial S}{\partial \mathbf{v}_{w_t}}

SS 求导,exp(uwTvwt)\exp(\mathbf{u}_{w}^T \mathbf{v}_{w_t}) 的导数是 exp(uwTvwt)uw\exp(\mathbf{u}_{w}^T \mathbf{v}_{w_t}) \cdot \mathbf{u}_{w}

Svwt=wVexp(uwTvwt)uw\frac{\partial S}{\partial \mathbf{v}_{w_t}} = \sum_{w \in \mathcal{V}} \exp(\mathbf{u}_{w}^T \mathbf{v}_{w_t}) \cdot \mathbf{u}_{w}

代回:

vwtlogS=1wVexp(uwTvwt)wVexp(uwTvwt)uw\frac{\partial}{\partial \mathbf{v}_{w_t}} \log S = \frac{1}{\sum_{w' \in \mathcal{V}} \exp(\mathbf{u}_{w'}^T \mathbf{v}_{w_t})} \cdot \sum_{w \in \mathcal{V}} \exp(\mathbf{u}_{w}^T \mathbf{v}_{w_t}) \cdot \mathbf{u}_{w}=wVexp(uwTvwt)wVexp(uwTvwt)uw=wVP(wwt)uw= \sum_{w \in \mathcal{V}} \frac{\exp(\mathbf{u}_{w}^T \mathbf{v}_{w_t})}{\sum_{w' \in \mathcal{V}} \exp(\mathbf{u}_{w'}^T \mathbf{v}_{w_t})} \cdot \mathbf{u}_{w} = \sum_{w \in \mathcal{V}} P(w \mid w_t) \cdot \mathbf{u}_{w}

两项合并,得到最终梯度:

Jvwt=uwo+wVP(wwt)uw\frac{\partial J}{\partial \mathbf{v}_{w_t}} = -\mathbf{u}_{w_o} + \sum_{w \in \mathcal{V}} P(w \mid w_t) \cdot \mathbf{u}_w

第二项是所有输出向量 uw\mathbf{u}_w加权平均,权重恰好是模型当前预测的概率分布 P(wwt)P(w \mid w_t)。换句话说,它是模型对输出向量的期望 EwP(wt)[uw]\mathbb{E}_{w \sim P(\cdot \mid w_t)}[\mathbf{u}_w]。第一项 uwo-\mathbf{u}_{w_o} 将中心词向量 vwt\mathbf{v}_{w_t} 「拉向」真实上下文词的向量 uwo\mathbf{u}_{w_o};第二项则将 vwt\mathbf{v}_{w_t} 「推开」所有词(按模型当前置信度加权),防止模型把所有词都预测成高频词。当二者平衡时,梯度为零,模型收敛。

这就是 softmax 的瓶颈所在:每次更新都需要对全体词汇表 VV 求和,当 V=105V = 10^5 时计算量不可接受。

对输出向量 uw\mathbf{u}_w 的梯度同样重要,推导过程类似:

Juw=(P(wwt)δw,wo)vwt\frac{\partial J}{\partial \mathbf{u}_{w}} = \big(P(w \mid w_t) - \delta_{w, w_o}\big) \cdot \mathbf{v}_{w_t}

其中 δw,wo=1\delta_{w, w_o} = 1w=wow = w_o(真实上下文词),否则为 00

  • 对于真实上下文词 wow_oP(wowt)1<0P(w_o \mid w_t) - 1 < 0,梯度为负,uwo\mathbf{u}_{w_o}vwt\mathbf{v}_{w_t} 靠拢。
  • 对于其他词 wwow \neq w_oP(wwt)>0P(w \mid w_t) > 0,梯度为正,uw\mathbf{u}_w 远离 vwt\mathbf{v}_{w_t}

参数更新#

反向传播需要前向传播的中间结果。具体来说:

前向输出反向传播中的用途
P(wwt)P(w \mid w_t)(所有词的 softmax 概率)计算 Jvwt\frac{\partial J}{\partial \mathbf{v}_{w_t}}Juw\frac{\partial J}{\partial \mathbf{u}_w} 都需要
vwt\mathbf{v}_{w_t}(中心词向量,即隐藏层 h\mathbf{h}所有 Juw\frac{\partial J}{\partial \mathbf{u}_w} 的梯度中共用
uwo\mathbf{u}_{w_o}(真实上下文词的输出向量)Jvwt\frac{\partial J}{\partial \mathbf{v}_{w_t}} 的第一项直接用到

训练时,对每个 (中心词, 上下文词) 对,用梯度下降同时更新两个矩阵:

vwtvwtηJvwt,uwuwηJuw(wV)\mathbf{v}_{w_t} \leftarrow \mathbf{v}_{w_t} - \eta \cdot \frac{\partial J}{\partial \mathbf{v}_{w_t}}, \qquad \mathbf{u}_{w} \leftarrow \mathbf{u}_{w} - \eta \cdot \frac{\partial J}{\partial \mathbf{u}_{w}} \quad (\forall w \in \mathcal{V})

注意 Wout\mathbf{W}_{\text{out}} 中的每一行 uw\mathbf{u}_w 都会被更新——因为每个词都参与了 softmax 分母的计算。这也是 softmax 计算量大的根源。

Skip-gram 反向传播

中心词 "cat" → 目标上下文词 "sits" · 观察前向输出如何驱动梯度计算

就绪 步骤 0 / 5
当前步骤
前向传播 · softmax 输出
模型预测 P(wo | "cat"),其中 "sits" 仅得 3.0%,损失 J = 3.50
当前数据
点击步骤按钮开始。

3. CBOW 模型#

CBOW(Continuous Bag of Words)是 Skip-gram 的镜像:给定上下文词 {wtm,,wt1,wt+1,,wt+m}\{w_{t-m}, \dots, w_{t-1}, w_{t+1}, \dots, w_{t+m}\},预测中心词 wtw_t

对于一个上下文窗口 Ct={wt+j:j{m,,m},j0}\mathcal{C}_t = \{w_{t+j} : j \in \{-m, \dots, m\}, j \neq 0\},将上下文词向量取平均:

h=1CtwCtvw\mathbf{h} = \frac{1}{|\mathcal{C}_t|} \sum_{w \in \mathcal{C}_t} \mathbf{v}_w

然后送入 softmax:

P(wtCt)=exp(uwtTh)wVexp(uwTh)P(w_t \mid \mathcal{C}_t) = \frac{\exp(\mathbf{u}_{w_t}^T \mathbf{h})}{\sum_{w \in \mathcal{V}} \exp(\mathbf{u}_{w}^T \mathbf{h})}

CBOW 将多个上下文词的信息聚合到一个向量中,训练速度比 Skip-gram 快(因为一次预测一个中心词,而 Skip-gram 一次预测 2m2m 个上下文词),但对稀有词的表示效果略差。

模型输入输出适合训练速度
Skip-gram1 个中心词2m2m 个上下文词稀有词、小数据集
CBOW2m2m 个上下文词1 个中心词高频词、大数据集

CBOW 的参数结构与 Skip-gram 完全相同——仍然需要训练两套词向量:

  • WinRd×V\mathbf{W}_{\text{in}} \in \mathbb{R}^{d \times V}输入嵌入矩阵,每列是词 ww 作为上下文词时的向量 vw\mathbf{v}_w
  • WoutRV×d\mathbf{W}_{\text{out}} \in \mathbb{R}^{V \times d}输出嵌入矩阵,每行是词 ww 作为中心词时的向量 uw\mathbf{u}_w

总参数量同样是 2Vd2 \cdot V \cdot d

更新的对象不同。一次 CBOW 训练中:

  • Win\mathbf{W}_{\text{in}}:更新上下文窗口内所有 2m2m 个词vw\mathbf{v}_w(Skip-gram 一次只更新 1 个中心词)
  • Wout\mathbf{W}_{\text{out}}:只需要更新中心词 wtw_t 对应的 uwt\mathbf{u}_{w_t}(Skip-gram 需要更新所有 VV 个词)

因为 CBOW 的输出端只需要对 1 个词求梯度,而 Skip-gram 需要对 2m2m 个词分别求梯度并累加,所以 CBOW 训练更快。但代价是 CBOW 对每个上下文词只更新了一次(平均后梯度被稀释),对稀有词的学习不如 Skip-gram 充分。这也解释了为什么 Skip-gram 对稀有词更友好——每个稀有词作为中心词时都会被单独训练。

4. 近似训练方法#

softmax 分母 wVexp(uwTvwt)\sum_{w \in \mathcal{V}} \exp(\mathbf{u}_{w}^T \mathbf{v}_{w_t}) 需要对所有 VV 个词求和,计算量 O(V)O(V)。两种近似方法将复杂度降到 O(logV)O(\log V)O(k)O(k)

4.1 负采样(Negative Sampling)#

负采样的核心思想:不必对所有负例建模,只需随机采样 kk 个”噪声词”作为负例

对于每个正样本 (wt,wo)(w_t, w_o),随机采样 kk 个噪声词 {w1,,wk}\{w_1, \dots, w_k\},目标函数变为:

J=logσ(uwoTvwt)i=1klogσ(uwiTvwt)J = -\log \sigma(\mathbf{u}_{w_o}^T \mathbf{v}_{w_t}) - \sum_{i=1}^{k} \log \sigma(-\mathbf{u}_{w_i}^T \mathbf{v}_{w_t})

其中 σ(x)=11+ex\sigma(x) = \frac{1}{1 + e^{-x}} 是 sigmoid 函数。

直观理解

这本质上是一个二分类问题:对于每个词对,模型需要判断它们是”真实共现”(正例)还是”随机配对”(负例)。

  • σ(uwoTvwt)\sigma(\mathbf{u}_{w_o}^T \mathbf{v}_{w_t}):模型认为 (wt,wo)(w_t, w_o) 是真实共现的概率
  • σ(uwiTvwt)\sigma(-\mathbf{u}_{w_i}^T \mathbf{v}_{w_t}):模型认为 (wt,wi)(w_t, w_i) 不是真实共现的概率

和 softmax 的区别在于:softmax 对所有词做 VV-分类;负采样对每个词对做独立的二分类,只需计算 k+1k+1 次 sigmoid。

噪声词的采样分布通常为:

P(w)count(w)3/4P(w) \propto \text{count}(w)^{3/4}

3/43/4 次幂的作用是提升低频词的采样概率,防止它们被完全忽略。

4.2 层次 Softmax(Hierarchical Softmax)#

另一种思路:用 Huffman 树将 VV-分类转化为 logV\log V 次二分类

将词汇表中的每个词放在 Huffman 树的叶子节点上(高频词路径短,低频词路径长)。对于中心词 wtw_t,预测上下文词 wow_o 的概率为从根节点走到 wow_o 叶子节点的路径上各次二分类概率的乘积:

P(wowt)=l=1L(wo)1σ([ ⁣[n(wo,l+1)=left(n(wo,l))] ⁣]un(wo,l)Tvwt)P(w_o \mid w_t) = \prod_{l=1}^{L(w_o)-1} \sigma\left([\![n(w_o, l+1) = \text{left}(n(w_o, l))]\!] \cdot \mathbf{u}_{n(w_o, l)}^T \mathbf{v}_{w_t}\right)

其中 L(wo)L(w_o) 是路径长度,n(wo,l)n(w_o, l) 是路径上第 ll 个节点,[ ⁣[] ⁣][\![\cdot]\!] 是指示函数(走左子树为 +1+1,右子树为 1-1)。

直观理解

想象一个猜词游戏。softmax 的做法是:一次列出所有 VV 个词,直接选一个。层次 softmax 的做法是:不断问”是水果吗?”→“是红色的吗?”→“是苹果吗?“,每次只需做二选一。

Huffman 编码保证高频词路径短,所以平均只需 log2V\log_2 V 次二分类。

5. 词向量的语义性质#

训练完成后,word2vec 的词向量展现出令人惊讶的语义结构。

5.1 类比推理#

最经典的例子:

vkingvman+vwomanvqueen\mathbf{v}_{\text{king}} - \mathbf{v}_{\text{man}} + \mathbf{v}_{\text{woman}} \approx \mathbf{v}_{\text{queen}}

向量运算捕捉到了”性别”这个语义维度:从”king”中减去”man”的语义,加上”woman”的语义,得到”queen”。

其他类比:

  • vParisvFrance+vItalyvRome\mathbf{v}_{\text{Paris}} - \mathbf{v}_{\text{France}} + \mathbf{v}_{\text{Italy}} \approx \mathbf{v}_{\text{Rome}}(首都-国家关系)
  • vwalkingvwalk+vswimvswimming\mathbf{v}_{\text{walking}} - \mathbf{v}_{\text{walk}} + \mathbf{v}_{\text{swim}} \approx \mathbf{v}_{\text{swimming}}(动词时态)

5.2 为什么会出现线性结构?#

负采样的目标函数可以重写为点互信息(Pointwise Mutual Information, PMI)的矩阵分解:

uwTvcPMI(w,c)logk\mathbf{u}_w^T \mathbf{v}_c \approx \text{PMI}(w, c) - \log k

其中 PMI(w,c)=logP(w,c)P(w)P(c)\text{PMI}(w, c) = \log \frac{P(w, c)}{P(w)P(c)} 衡量两个词的实际共现频率与随机共现频率之比。这说明 word2vec 本质上在做共现矩阵的隐式分解,将高维稀疏的 PMI 矩阵压缩为低维稠密的词向量。

6. 从 word2vec 到现代 LLM#

word2vec 奠定了现代 NLP 的基石,但也存在局限性:

方面word2vec现代 LLM (Transformer)
词表示静态:每个词只有一个固定向量上下文相关:同一个词在不同句子中向量不同
多义词处理无法区分”bank”(银行/河岸)根据上下文自动消歧
上下文范围固定窗口 mm自注意力机制,理论上无限长
训练目标预测邻居词预测下一个 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.
词嵌入基础:word2vec
https://biscuit0613.github.io/posts/nlp/01-word2vec/
作者
Biscuit
发布于
2026-07-18
许可协议
CC BY-NC-SA 4.0
MiniMind 代码导读(一):从 Token IDs 到训练 Loss
BERT:预训练+微调范式