Word2Vec教程-Negative Sampling 负采样

2,666 阅读6分钟
原文链接: www.jianshu.com

这篇word2vec教程2中(教程1 Word2Vec教程-Skip-Gram模型),作者主要讲述了skip-gram 模型优化的策略-Negative Sampling,使得模型更加快速地训练。通过教程1,我们了解到word2vec它是一个庞大的神经忘网络!
例如,有一个包含10000个单词的词汇表,向量特征为300维,我们记得这个神经网络将会有两个weights矩阵----一个隐藏层和一个输出层。这两层都会有一个300x10000=3000000的weight矩阵。
在如此大的神经网络上进行梯度下降是非常慢的,更加严重的是,我们需要大量训练数据去调整weights和避免over-fitting。

Word2Vec作者在这篇论文解决列这些问题,主要提到3种措施:

  • 在模型种将共同出现的单词对或者短语当做单个“词”
  • 二次采样经常出现的单词,以减少训练数据的数量
  • 改变优化目标函数-使用“Negative Sampleing”,将会使训练样本更新少量模型的weights
    值得注意的是,对频繁词进行二次抽样和应用负抽样不仅减少了训练过程的计算负担,而且还提高了其结果词向量的质量。

Word Pairs and “Phrases” · 单词对和“短语”

作者指出,像“波士顿环球报”(一家报纸)这样的词组与“波士顿”和“环球报”这两个单词有着非常不同的含义。所以“Boston Globe”不论出现在文中哪个位置,将它视为具有自己词向量标示的单个词语是有道理的。
在作者发布的模型结果中,我们了解到模型基于1000亿字的谷歌新闻中训练出来的。“短语”的加入使词汇量减小到300个词语!
如果你对结果词汇感兴趣,你可以在Google's trained Word2Vec model in Pythoninspect_word2vec看到.短语检测方法在 论文中“Learning Phrases”部分提到,代码在。他们这个工具每次传入两个词语的组合,但是你可以运行多次来获得更长的短语。比如一次传入“New_York”,下次再运行的时候将会“New_York_City”看做是“New_York”和“City”的组合。该短语提取工具统计两个单词组合在训练文本中出现的次数,然后统计的参数将会用于个一个等式,以便决定它们是否可以成为一个短语。它更将倾向于不经常出现的单词短语,以避免将“and the”和“this is”作为短语。

Subsampling Frequent Words · 二次抽样高频词

在第一篇教程中,作者已经展示了如何形成训练样本,这儿才重复下。下面例子展示了句子“The quick brown fox jumps over the lazy dog.”的训练样本。使用一个大小为的2窗口,我们将会形成下面的训练样本。



有两个关于高频词类似“the”的问题:

  • 在观察单词组时,我们发现(“fox”,“the”)不会产生关于“fox”的信息。“the”经常出现在每个单词的上下文中。
  • 我们将会有多样本(“the”,....),远超过我们需要训练“the”的样本数量。
    Word2Vec通过“二次采样”方案来解决上述问题。对于出现在训练文中的每个单词,都会有一个从文本删除的概率,这个概率取决于相应单词的词频。
    如果我们窗口大小为10,我们下面是将会去除“the”的特定实例:
  • 当我们在剩余单词中训练时,“the”将不会出现在我们的文本中
  • 我们将会有10个很少包含“the”的训练样本

Sampling Rate · 采样率

word2vec c代码实现了一个计算词汇表的给定单词的概率。wi是一个单词,z(wi)是单词w出现的次数与总单词个数的比值。例如“peanut”在1 billion 单词语料中出现了1000次,那么z('peanut')=1E-6
在代码中有个参数sample来控制subsampling出现的概率,默认值为0.001.sample值越小代表单词保留的概率越小。
P(Wi)是保留该单词的概率:


下面是该公式的曲线:

在上图中我们可以发现,没有一个单:会占整个语料的很大比例,所以x轴的值是非常小的。
另外下面几个关于整个函数有意思的点:
  • P(Wi)=1.0(100%会保留) 当z(wi)<=0.0026。这意味着当单词个数占总单词个数
    的超过0.26%将会被二次采样。
  • P(wi)=0.5 (50% 的概率会保留) 当 z(wi)=0.00746.
  • P(wi)=0.033 (3.3% 的概率会保留) 当z(wi)=1.0.这意味着整个语料库只包含一个单词,这会是非常荒唐的语料库。<( ̄ ﹌  ̄)>

你将会注意到论文中定义的函数与这里有些区别,但是这里版本是C代码中实现的,是比较权威的。哈哈


Negative Sampling · 负采样

在训练神经网络时,每当接受一个训练样本,然后调整所有神经单元权重参数,来使神经网络预测更加准确。换句话说,每个训练样本都将会调整所有神经网络中的参数。 我们词汇表的大小决定了我们skip-gram 神经网络将会有一个非常大的权重参数,并且所有的权重参数会随着数十亿训练样本不断调整。

negative sampling 每次让一个训练样本仅仅更新一小部分的权重参数,从而降低梯度下降过程中的计算量。 如果 vocabulary 大小为1万时, 当输入样本 ( "fox", "quick") 到神经网络时, “ fox” 经过 one-hot 编码,在输出层我们期望对应 “quick” 单词的那个神经元结点输出 1,其余 9999 个都应该输出 0。在这里,这9999个我们期望输出为0的神经元结点所对应的单词我们为 negative word. negative sampling 的想法也很直接 ,将随机选择一小部分的 negative words,比如选 10个 negative words 来更新对应的权重参数。

在论文中作者指出指出对于小规模数据集,建议选择 5-20 个 negative words,对于大规模数据集选择 2-5个 negative words.

如果使用了 negative sampling 仅仅去更新positive word- “quick” 和选择的其他 10 个negative words 的结点对应的权重,共计 11 个输出神经元,相当于每次只更新 300 x 11 = 3300 个权重参数。对于 3百万 的权重来说,相当于只计算了千分之一的权重,这样计算效率就大幅度提高。

Selecting Negative Samples

使用 一元模型分布 (unigram distribution) 来选择 negative words,一个单词被选作 negative sample 的概率跟它出现的频次有关,出现频次越高的单词越容易被选作negative words,经验公式为:

f(w) 代表 每个单词被赋予的一个权重,即 它单词出现的词频,分母 代表所有单词的权重和。公式中3/4完全是基于经验的,论文中提到这个公式的效果要比其它公式更加出色。


Other Resources · 其他资源