负采样是一种用于训练词嵌入模型的采样方法,特别适用于处理大规模词汇表的情况。负采样的目标是降低计算成本并改善模型的性能,同时有效地训练词向量。
在传统的词嵌入模型中,如Word2Vec,要计算每个词汇在上下文中的概率分布,需要使用softmax函数对整个词汇表进行运算。然而,当词汇表非常庞大时,全局计算softmax会变得非常耗时,因为其计算复杂度与词汇表的大小成正比。
为了解决这个问题,负采样提出了一种更高效的训练策略。负采样的核心思想是将训练目标简化为仅关注正样本(即目标词汇的上下文词汇)和一小部分负样本(即从训练数据中未出现的词汇)之间的关系。相比于原始的softmax分类器需要更新整个权重矩阵,通过负采样这种方式,负采样大大减少了计算量,使得模型训练更加高效。
对于每个训练样本,我们只需要更新一小部分的权重,而不是更新所有的权重。也就是,对于每个训练样本(中心词和上下文词),负采样算法会从词汇表中随机选择一些负样本(通常是一些未出现在上下文中的词汇),并将它们作为负类标签。然后,只有这些负样本的权重会被更新,而其他词汇的权重保持不变。
概括地说,负样本的选择通常基于词频分布,较低频率的词汇更有可能被选为负样本。
在负采样中,负样本是指从训练数据中未出现的词汇,用于与正样本(目标词汇的上下文词汇)进行对比和训练。选择合适的负样本是负采样方法的关键之一,通常采用基于词频分布的采样,根据词汇在语料库中的出现频率来选择负样本,即词频较低的词汇被选中作为负样本的概率较高,而词频较高的词汇被选中的概率较低
如图,当使用负采样时,我们首先需要定义一个负样本采样函数。这个函数根据词汇表中每个词汇的频率分布,以一定的概率选择负样本。
为了提高训练效果,通常会根据词汇表中单词的出现频率来选择负样本。
出现频率较低的单词被选作负样本的原因是,这些单词在正样本(真实配对)中出现的机会较少,因此将它们作为负样本可以更好地区分出真实的上下文词。
以skip-gram中的负采样为例:
这是原本的全局softmax函数,在词汇表规模特别大的时候会耗费大量的计算资源,归一化的时间也会变得很慢
加上负采样之后:
针对一个真正的配对(中心词和其上下文窗口中的一个词)与多个噪声配对(中心词与一个随机词)进行二元逻辑回归训练。
模型通过训练二元逻辑回归模型来区分真正的配对和噪声配对。真正的配对由中心词和上下文窗口中的一个词组成,而噪声配对则是将中心词与一个随机选择的词进行配对。
我们的目标现在变成最大化两个词在第一个对数项中共同出现的概率,并最小化噪声词的概率。也就是说在训练过程中,作者希望模型能够准确地预测真实的词对(中心词和上下文词),同时尽量将噪声词与中心词的共现概率降低(图中第二点)
核心目标:我们希望真正的context word softmax出来的值尽可能接近1,其他则尽可能小
对于负样本词汇,我们希望模型能够将它们的预测概率降低,以更好地区分正样本和负样本。我们选择的负样本词汇在训练样本中并不真实地与中心词共现,因此我们希望模型能够将它们与正样本词汇区分开来。
例如,假设我们有一个包含以下词汇的句子:
“the cat sat on the mat”
现在,我们要训练一个word2vec模型,其中词汇表包含词汇:“the”, “cat”, “sat”, “on”, “mat”。
步骤一:构建训练样本
以Skip-gram模型为例,选择中心词和上下文词对作为训练样本。假设我们设置上下文窗口大小为1,那么我们可以构建以下的训练样本:
对于中心词 “the”,上下文词为 [“cat”]。
对于中心词 “cat”,上下文词为 [“the”, “sat”]。
对于中心词 “sat”,上下文词为 [“cat”, “on”]。
对于中心词 “on”,上下文词为 [“sat”, “the”, “mat”]。
对于中心词 “mat”,上下文词为 [“on”]。
步骤二:负样本采样
对于每个训练样本,我们需要选择一些负样本。假设我们选择两个负样本。我们使用负采样函数根据词汇表中每个词汇的频率分布,以一定的概率选择负样本。
例如,负样本采样函数根据频率分布选择了负样本词汇:“dog"和"house”。
步骤三:更新权重
对于每个训练样本,我们更新权重,以使模型更好地预测上下文词汇。对于中心词和上下文词对,我们将它们视为正样本,更新它们对应的权重。同时,对于负样本词汇,我们将它们视为负样本,仅更新它们对应的权重。
1.正样本权重的更新:
首先,我们计算中心词"cat"的词向量和上下文词"the"的词向量之间的内积,得到一个预测值。假设这个内积为0.8,并将其输入到sigmoid函数中,得到一个概率值为0.689,表示在给定"cat"的情况下,"the"出现的概率。
然后,我们将这个概率值与实际上下文词"the"的标签进行比较。假设标签为1,表示"the"是正样本。我们计算预测值与实际值之间的差距,即损失。假设损失为0.2。
接下来,我们计算损失函数对中心词"cat"和上下文词"the"的词向量的偏导数。假设得到的偏导数分别为[0.1, 0.2]和[0.05, 0.15]。然后,根据学习率来更新中心词和上下文词的词向量。假设学习率为0.01,我们可以将中心词和上下文词的词向量更新如下:
中心词"cat"的词向量更新为[0.1, 0.2] - 0.01 * [0.1, 0.2] = [0.099, 0.198]
上下文词"the"的词向量更新为[0.05, 0.15] - 0.01 * [0.05, 0.15] = [0.0495, 0.1485]
负样本权重的更新:
现在,我们来处理负样本词汇"dog"和"house"。
首先,我们计算负样本词汇"dog"的词向量和中心词"cat"的词向量之间的内积,得到一个预测值。假设这个内积为-0.6,并将其输入到sigmoid函数中,得到一个概率值为0.354,表示在给定"cat"的情况下,"dog"出现的概率。
然后,我们将这个概率值与负样本词汇"dog"的标签进行比较。假设标签为0,表示"dog"是负样本。我们计算预测值与实际值之间的差距,即损失。假设损失为0.354。
接下来,我们计算损失函数对负样本词汇"dog"的词向量的偏导数。假设得到的偏导数为[-0.2, -0.1]。然后,根据学习率来更新负样本词汇"dog"的词向量。假设学习率为0.01,我们可以将负样本词汇"dog"的词向量更新如下:
负样本词汇"dog"的词向量更新为[-0.2, -0.1] - 0.01 * [-0.2, -0.1] = [-0.202, -0.101]
在更新负样本的权重时,我们计算了负样本词汇的预测概率,并将其与实际值进行比较。如果模型在预测负样本时的概率接近于1,说明模型将其错误地预测为正样本,这样就无法区分正样本和负样本了。因此,我们希望通过更新权重,降低负样本的预测概率,使得模型能够更好地区分正样本和负样本。