Word2vec模型

• 46 min read • 9123 words
Tags: Deep Learning NLP Word2vec
Categories: NLP

Word2vec模型

1. 词的表示

1.1 能指与所指

一个词(如 tea)是一个符号/能指 (Signifier),它代表了现实或想象世界中的某个实体/所指 (Signified)。词义是极其复杂的,它源于人类在世界中沟通和实现目标的意图。

1.2 离散词表示:One-Hot 向量

最简单的表示方法是将每个词视为独立的实体。在向量空间中,这通常通过 one-hot 向量(或称标准基向量) 来实现。

例如,在一个词汇表 VV 中:

vtea=[0,0,1,0,,0]Tv_{\text{tea}} = [0, 0, 1, 0, \dots, 0]^T vcoffee=[0,0,0,0,,1,,0]Tv_{\text{coffee}} = [0, 0, 0, 0, \dots, 1, \dots, 0]^T

这种表示方法的缺陷在于,它无法表达词与词之间的相似性关系。任意两个不同词的one-hot向量的点积都为0,意味着在模型看来,所有词都同等地“不相似”

2.3 基于人工标注属性的向量

另一种方法是根据语言学资源(如WordNet)手动为词语标注各种属性(如同义词、上下位词、语法信息等),然后构建特征向量。

例如,v_tea 可能包含 [is_plural: 0, is_beverage: 1, ..., is_synonym_of_chai: 1] 等特征。

3. 分布式语义与 Word2vec

3.1 分布式假设

"You shall know a word by the company it keeps." — J. R. Firth

这是现代NLP中最具影响力的思想之一:一个词的意义可以由其上下文(Context) 中出现的词的分布来定义。与 tea 相似的词(如 coffee)倾向于出现在相似的上下文中。

3.2 共现矩阵

基于分布式假设,我们可以构建一个 共现矩阵 XXXX 的大小为 V×V|V| × |V|,其中 XijX_ij 表示词 ii 和词 jj 在同一上下文(如一个窗口或一篇文档)中出现的次数。

  • 短窗口 (e.g., 2-5 words): 倾向于捕捉句法 (Syntactic) 信息。
  • 长窗口 (e.g., document-level): 倾向于捕捉语义 (Semantic)主题 (Topic) 信息。

这种方法的问题在于,生成的向量维度过高(等于词汇表大小),并且原始计数对高频词(如 the)的权重过高。

3.3 Word2vec 模型与目标函数

Word2vec 是一种从数据中学习词的低维稠密向量(Embedding) 的模型。这里我们介绍 Skip-gram 算法。

a.a. 模型定义

给定一个中心词 cc (center word),模型的目标是预测其上下文中的一个外部词 oo (outside word)。模型为词汇表 VV 中的每个词 ww 学习两个向量:

  • vwv_w:当 ww 作为中心词时的向量。
  • uwu_w:当 ww 作为外部词时的向量。

模型使用 softmax 函数定义条件概率 p(oc)p(o|c)

p(oc)=exp(uoTvc)wVexp(uwTvc)p(o|c) = \frac{\exp(u_o^T v_c)}{\sum_{w \in V} \exp(u_w^T v_c)}

我们通过最小化与真实分布 P(OC)P^*(O \mid C) 的交叉熵损失目标来估计参数 U,VU, V 的取值:

minU,VEo,c[logpU,V(oc)]\min_{U, V} \mathbb{E}{o, c} \left[ -\log p{U, V}(o \mid c) \right]

交叉熵损失:交叉熵损失分为分类交叉熵和二元交叉熵。 对于分类交叉熵,其计算公式如下:

J=j=1Cyjlog(y^j)J = - \sum_{j=1}^{C} y_j \cdot \log(\hat{y}_j)

其中:

CC 是类别的总数。

yjy_j 是真实标签 one-hot 向量的第 jj 个元素(值为 0 或 1)。

y^j\hat{y}_j 是模型预测的第 jj 个类别的概率。

log\log 通常是自然对数(ln)。

对于二元交叉熵,其计算公式如下:

J=[ylog(y^)+(1y)log(1y^)]J = - [y \cdot \log(\hat{y}) + (1 - y) \cdot \log(1 - \hat{y})]

其中:

yy 是真实标签(0 或 1)。

y^\hat{y} 是模型预测样本为正类(y=1y=1)的概率。

1y^1 - \hat{y} 是模型预测样本为负类(y=0y=0)的概率。

b.b. 目标函数

我们的目标是最大化给定中心词时,预测真实上下文词的概率。这等价于最小化负对数似然 (Negative Log Likelihood)

J(θ)=1Tt=1Tjcontext(t),j0logp(wt+jwt)J(\theta) = -\frac{1}{T} \sum_{t=1}^{T} \sum_{j \in \text{context}(t), j \neq 0} \log p(w_{t+j} | w_t)

我们通过梯度下降 (Gradient Descent)等优化算法来调整参数 UUVV,以最小化该损失函数。

3.3 从语料库中训练word2vec模型

a.a. 经验损失函数

设:

  • DD 为文档集合 d{d},每个文档是单词序列 w1(d),,wm(d),wVw_1^{(d)}, \ldots, w_m^{(d)}, w \in V
  • kN++k \in \mathbb{N}^{++} 为正整数窗口大小。

我们来定义中心词随机变量 CC 和外部词随机变量 OO 如何与这个具体数据集对应。OO 取每个文档中每个单词 wiw_i 的值,对于每个 wiw_i,其外部词为 wik,,wi1,wi+1,,wi+k{w_{i-k}, \ldots, w_{i-1}, w_{i+1}, \ldots, w_{i+k}}。因此,我们的目标函数变为:

L(U,V)=dDi=1mj=1klogpU,V(wij(d)wi(d))L(U, V) = \sum_{d \in D} \sum_{i=1}^m \sum_{j=1}^k -\log p_{U,V}(w_{i-j}^{(d)} \mid w_i^{(d)})

这个式子的意义是:对所有文档、文档中所有单词、窗口内所有外部词,计算外部词在中心词条件下的似然的和。

b.b.梯度方法

我们通过梯度方法来寻找较优的 UUVV,以优化我们设定的目标函数:我们从一个相对随机的初始猜测出发,反复沿着能在局部最优地改进目标的方向调整参数。这就是梯度法。

标量函数 ff 关于参数矩阵 UU 的梯度(记作 Uf\nabla_U f),表示在局部上让 ff 增大的 UU 的变化方向。

实际操作中,我们通常将 U(0)U^{(0)}V(0)V^{(0)} 随机初始化为 U,VN(0,0.001)V×dU, V \sim \mathcal{N}(0, 0.001)^{|V| \times d}(即每个元素独立采样自均值为0、方差很小的正态分布),然后进行如下迭代:

U(i+1)=U(i)αUL(U(i),V(i))U^{(i+1)} = U^{(i)} - \alpha \nabla_U L(U^{(i)}, V^{(i)})

这表示在第 i+1i+1 次迭代时,UU 的值等于上一次的值减去一个小步长 α\alpha 乘以梯度,从而在目标 L(U,V)L(U, V) 上取得局部最优的改进。

这里的 α\alpha 也是学习率。

c.c. 梯度具体计算与含义

我们首先写出梯度,并将梯度算子传递到求和符号内:

vcL^(U,V)=dDi=1mj=1kvclogpU,V(wij(d)wi(d))\nabla_{v_c} \hat{L}(U, V) = \sum_{d \in D} \sum_{i=1}^m \sum_{j=1}^k -\nabla_{v_c} \log p_{U,V}(w_{i-j}^{(d)} \mid w_i^{(d)})

这些项的梯度就是它们各自梯度的和。我们将 wij(d)w_{i-j}^{(d)} 记为 oowi(d)w_i^{(d)} 记为 cc,只考虑一项:

vclogpU,V(oc)=vclogexp(uovc)w=1nexp(uwvc)=vclogexp(uovc)vclogw=1nexp(uwvc)\nabla_{v_c} \log p_{U,V}(o \mid c) = \nabla_{v_c} \log \frac{\exp(u_o^\top v_c)}{\sum_{w=1}^n \exp(u_w^\top v_c)} = \nabla_{v_c} \log \exp(u_o^\top v_c) - \nabla_{v_c} \log \sum_{w=1}^n \exp(u_w^\top v_c)

而:

vclogexp(uovc)=uo\nabla_{v_c} \log \exp(u_o^\top v_c) = u_o

将点乘展开,然后对 vcv_c 求偏导即可。最终结果即为 uou_o

vclogw=1nexp(uwvc)=x=1npU,V(xc)ux-\nabla_{v_c} \log \sum_{w=1}^n \exp(u_w^\top v_c) = \sum_{x=1}^n p_{U,V}(x \mid c) u_x

综上可得:

uox=1npU,V(xc)ux=uoE[ux]u_o - \sum_{x=1}^n p_{U,V}(x \mid c) u_x = u_o - \mathbb{E}[u_x]

也就是“观测到的”减去“期望的”。直观上,vcv_c 向量会被更新得更像实际观测到的词向量 uou_o,而不是模型期望的词向量。

“更像实际观测到的词向量 uou_o”:这是由梯度的 +uo+u_o 部分决定的。更新的目标是让 vcv_cuou_o 靠拢。 “而不是模型期望的词向量”:这是由梯度的 E[ux]-\mathbb{E}[u_x] 部分决定的。更新的过程不是简单地加强模型现有的期望,而是要减去这个期望的影响,从而为“事实” uou_o 留出空间

3.4 Skip-gram 负采样

在 Skip-gram 模型中,计算 p(oc)p(o|c) 的分母(归一化项)非常耗时,因为它需要对词汇表中的所有词进行计算。

对此,我们尝试从另一个角度来理解归一化操作的意义。我们先重写 softmax 公式:

pU,V(oc)=exp(uovc)wVexp(uwvc)p_{U,V}(o \mid c) = \frac{\exp(u_o^\top v_c)}{\sum_{w \in V} \exp(u_w^\top v_c)}

其中,分子 exp(uovc)\exp(u_o^\top v_c) 表示词 cc 与上下文 oo 的关联度,分母 wVexp(uwvc)\sum_{w \in V} \exp(u_w^\top v_c) 是分区函数(归一化项)。

从概率的角度看,分区函数保证所有概率之和为 1(指数函数保证分数非负)。而从学习的角度看,分区函数会 “压低”所有非观测词的分数。换句话说,分子鼓励模型让 uou_o 更像 vcv_c,而分母则让所有 wow \neq ouwu_w 更不像 vcv_c

负采样(negative sampling)的直觉是:我们没必要每次都压低所有 uwu_w,因为这会带来很大的计算开销。相反,我们可以提出下面的新的策略:对于每个 (中心词, 上下文词) 正样本对,我们不再更新整个词汇表的权重,而是随机抽取 kk 个负样本(即不太可能出现在上下文中的词)

SGNS 的目标函数为:

J(θ)=logσ(uoTvc)+i=1kEwiPn(w)[logσ(uwiTvc)]J(\theta) = \log \sigma(u_o^T v_c) + \sum_{i=1}^{k} \mathbb{E}_{w_i \sim P_n(w)}[\log \sigma(-u_{w_i}^T v_c)]

其中:

  • σσlogistic 函数 ,用于皈依
σ(x)=1(1+ex)σ(x) = {1 \over (1 + e^{-x})}
  • 第一项最大化观察到的 (c,o)(c, o) 对的概率。
  • 第二项最小化随机采样的负样本 (c,wi)(c, w_i) 的概率。

σ\sigma 函数将可以是任意实数的“相似度分数”压缩到 (0, 1) 区间内。这个输出值就可以被解释为“oo真的是cc的上下文”这件事的概率。

σ\sigma 函数有个非常优美的性质:1σ(x)=σ(x)1-\sigma(x)=\sigma(-x),可以很方便的表示负样本的概率。

这种方法将一个复杂的多分类问题转化为了多个简单的二分类问题,极大地提升了训练效率,同时保证了词向量的质量。