好的,我注意到列表中尚未讲解 隐空间模型(如 Word2Vec)中的负采样(Negative Sampling)算法。因此,本次为你详细讲解这个题目。
Word2Vec 的负采样(Negative Sampling)算法原理与优化过程
题目描述:
Word2Vec 是一种广泛用于学习单词向量表示(词嵌入)的模型,核心思想是“一个单词由其上下文决定”。然而,直接使用标准的神经网络(如全连接层接Softmax)来预测中心词或上下文词时,计算成本极高,因为 Softmax 需要对整个庞大的词汇表中的每个词进行计算。负采样(Negative Sampling, NEG)被提出作为一种高效的优化替代方案,它通过将复杂的多分类问题转化为多个简单的二分类问题,极大地加速了训练过程,同时还能学习到高质量的稠密词向量。
解题过程(循序渐进讲解):
第一步:理解基础模型(Skip-gram 模型)的目标
Word2Vec 有两种结构:CBOW(用上下文预测中心词)和 Skip-gram(用中心词预测上下文)。负采样在 Skip-gram 中应用最为直观。
- 核心任务:给定一个中心词
w(例如 “人工智能”),我们希望模型能够准确地预测出它在一个固定窗口内(如前3后3个词)的上下文词c(例如 “机器学习”)。 - 原始目标函数(Softmax):在原始 Skip-gram 中,这被建模为一个多分类问题。
- 每个单词
w有两个向量表示:输入向量v_w(当它作为中心词时)和输出向量u_w(当它作为上下文词时)。 - 对于给定的 (中心词, 上下文词) 对
(w, c),我们希望c在w的上下文词集合中的概率最大化。这个概率通过 Softmax 函数定义:
其中,P(c | w) = exp(u_c^T * v_w) / Σ_{i=1}^{V} exp(u_i^T * v_w)V是整个词汇表的大小(可能达数百万)。求和项Σ_{i=1}^{V} exp(u_i^T * v_w)是计算的瓶颈,因为它需要对所有词汇计算。
- 每个单词
第二步:负采样的核心思想
负采样将上述“一个中心词 vs. 整个词汇表”的复杂计算,巧妙地转化为 “区分正样本对和负样本对” 的多个简单二分类任务。
- 正样本 (Positive Sample):从真实语料中观察到的 (中心词
w, 上下文词c) 对。这就是我们希望模型能够正确判断为“相关”或“是上下文”的样本。 - 负样本 (Negative Sample):随机抽取的、并非真实出现的 (中心词
w, 错误词n) 对。即,我们从词汇表中随机选择一个(或多个)词n,它与w在实际语境中并不相邻。我们希望模型能够正确判断这些对为“不相关”或“不是上下文”。
核心转变:模型的训练目标不再是精确计算 “上下文词 c 的概率是所有词中最大的”,而是变成 “能够可靠地区分正样本对和负样本对”。
第三步:负采样的目标函数(损失函数)
对于每个正样本对 (w, c),我们同时构造 k 个负样本对 (w, n1), (w, n2), ..., (w, nk)。这里的 k 是一个超参数(通常为 5-20)。
- 正样本的目标:我们希望
P(D=1 | w, c)最大化。D=1表示(w,c)是正样本(来自真实数据)。- 使用 sigmoid 函数
σ(x) = 1 / (1 + exp(-x))来建模这个概率,因为它天然输出一个 0 到 1 之间的值,可以解释为“是正样本的概率”。 - 具体地,
P(D=1 | w, c) = σ(u_c^T * v_w)。
- 使用 sigmoid 函数
- 负样本的目标:对于每个负样本
(w, n),我们希望P(D=0 | w, n) = 1 - P(D=1 | w, n)最大化。- 同样用 sigmoid 建模:
P(D=1 | w, n) = σ(u_n^T * v_w),但我们希望这个概率尽可能小,即希望模型判断其为负样本。
- 同样用 sigmoid 建模:
- 组合损失函数:对于包含一个正样本和
k个负样本的一个训练单元,我们希望最大化它们的联合似然概率。- 最终的目标函数(负对数似然,即需要最小化的损失)为:
J = -log[σ(u_c^T * v_w)] - Σ_{i=1}^{k} log[σ(-u_{n_i}^T * v_w)]- 第一项
-log[σ(u_c^T * v_w)]鼓励正样本对的分数(点积)尽可能高。 - 第二项
-Σ log[σ(-u_{n_i}^T * v_w)]鼓励负样本对的分数(点积)尽可能低。
- 第一项
- 最终的目标函数(负对数似然,即需要最小化的损失)为:
第四步:负样本的采样策略(关键优化)
不是简单地从词汇表中均匀随机抽取词作为负样本。否则,像“的”、“了”、“是”这样的高频词会频繁被抽中,它们与任何词的共现都可能不显著,导致模型学不到有效信息。
- 解决方案:采用一种带权重的采样分布,使得一个词被选为负样本的概率与其在语料中出现的频率正相关,但不是简单的线性关系。
- 常用公式:Word2Vec 中提出了一种平滑的分布
P(w),用于采样负样本:
其中P(w) = f(w)^{3/4} / (Σ f(w_i)^{3/4})f(w)是词w在语料中的频率。3/4次幂是一个经验性的平滑因子。它将高频词的采样概率略微降低(例如,“的”的频率可能降低到原本的f(w)^{0.25}倍),同时将低频词的采样概率相对提高(例如,一个出现10次的词,其概率变为10^{0.75} ≈ 5.6倍于均匀采样),使采样分布更加均衡。
第五步:训练过程(梯度下降与参数更新)
模型需要学习的参数是所有词的输入向量 v_w 和输出向量 u_w(对于负样本词 n 的 u_n 也会被更新)。
- 前向传播:对于一个训练样本
(w, c)及其对应的k个负样本词{n_i}。- 计算正样本分数:
score_pos = u_c^T * v_w,并通过 sigmoid 得到概率p_pos = σ(score_pos)。 - 对于每个负样本词
n_i,计算负样本分数:score_neg_i = u_{n_i}^T * v_w,得到概率p_neg_i = σ(score_neg_i)。
- 计算正样本分数:
- 计算损失:根据第三步的公式
J计算当前损失。 - 反向传播与梯度更新:
- 对
v_w(中心词向量) 的梯度:
这个公式非常直观:∂J/∂v_w = [σ(u_c^T * v_w) - 1] * u_c + Σ_{i=1}^{k} [σ(u_{n_i}^T * v_w)] * u_{n_i}- 正样本部分 (
[σ(score_pos) - 1] * u_c): 当前预测概率σ(score_pos)离目标 1.0 越远,梯度越大。梯度方向是u_c,意味着我们希望v_w向u_c靠近。 - 负样本部分 (
[σ(score_neg_i)] * u_{n_i}): 当前预测概率σ(score_neg_i)离目标 0.0 越远(即越大),梯度越大。梯度方向是u_{n_i},意味着我们希望v_w远离u_{n_i}。
- 正样本部分 (
- 对
u_c(正样本上下文词向量) 的梯度:
同样,我们希望∂J/∂u_c = [σ(u_c^T * v_w) - 1] * v_wu_c向v_w靠近。 - 对
u_{n_i}(负样本词向量) 的梯度:
我们希望∂J/∂u_{n_i} = [σ(u_{n_i}^T * v_w) - 0] * v_w = σ(score_neg_i) * v_wu_{n_i}远离v_w。注意这里σ(score_neg_i)是正值,所以更新方向是与v_w相同的方向,但由于学习率是负的(梯度下降是参数 = 参数 - 学习率 * 梯度),实际效果是使u_{n_i}沿着v_w的反方向移动。
- 对
- 使用梯度下降(或其变种,如 SGD)更新所有涉及的参数
v_w,u_c,{u_{n_i}}。
总结与意义
负采样算法通过将计算复杂度从 O(V)(V为词汇表大小)降低到 O(k)(k为负样本数量,通常为5-20),实现了对大规模语料的高效训练。它本质上是一种 “噪声对比估计” (Noise Contrastive Estimation, NCE) 的简化形式。通过学习区分真实数据(信号)和人为构造的噪声数据,模型被迫捕捉单词之间关键的共现模式,从而在低维向量空间中编码出丰富的语义和语法关系,最终得到高质量的单词嵌入表示。