The Skip-Gram Model
本篇专注于skip-gram算法的神经网络结构,跳过了常见的介绍和word2vec的抽象概念,更加关注细节。
文章目录
1.The Model 模型
训练一个简单的神经网络,用一个隐含层来执行特定的任务,但重点不在于这个任务,而在于隐含层的权重,它们就是我们想要的到的“词向量”。
在无监督学习中也用到这种技巧。训练之后,去掉输出层,只使用隐含层。
2.The Fake Task 假任务
我们训练神经网络执行下面的任务。
输入:一个中心词
输出:词汇表中每个单词成为中心词的邻近单词的概率
注:邻近的概念由一个参数m决定,表示窗口大小即半径。当说窗口大小为5时,包含中心词前5个及后5个单词,一共10个
输出的概率将与在中心词周围找到每个单词的可能性有关。比如输入苏维埃,那么联盟和俄罗斯等词的输出概率将远高于西瓜和袋鼠之类的词。
下面的例子中,令窗口大小为2,蓝色部分为中心词。用训练文档生成单词对。网络会从每个配对出现的次数中学习统计信息。
3.More Details 更多细节
首先,我们要从训练文档中构建一个词汇表——假设这个表中有10000个独特单词。这样做的原因是,神经网络的输入不能时一个字符串,所以要先对单词进行编码。
我们使用独热码,这样一来,输入有10000维,在中心词对应位置放1,其他位置放0。
输出也是一个10000维的向量,每个分量表示词汇表中每个单词出现在中心词附近的概率。
这个神经网络中,隐含层没有激活功能,但输出神经元使用softmax。
3.1 The Hidden Layer 隐含层
在上图中,我们使用了300个神经元,实际上,这是一个超参数,可以根据情况进行设置。因此隐含层的权重矩阵有10000行300列。
这个权重矩阵的行向量就对应每个单词的词向量。
因此,我们的目标实际上知识学习这个隐含层权重矩阵,然后扔掉输出层。
当使用一个独热码与矩阵相乘时,实际上只是有效选择单词对应的那一行词向量。这就意味着隐含层只是作为查找表运行。
3.2 The Output Layer 输出层
通过隐含层后,中心词ants的词向量(1x300)到达输出层。输出层是一个softmax回归分类器。softmax回归的要点是,每个输出神经元(共10000个)将产生一个介于0到1之间的输出,所有输出之和相加为1。
每个输出神经元都有一个权重向量,将它与词向量相乘,再通过函数exp(x)得到结果y。为了使输出结果之和为1,再求y与所有y值之和的比值,得到输出结果。
注:神经网络的权重矩阵不知道输出相对于中心词的偏移量。也就是说,附近所有单词的概率是相同的概念,不包含单词的位置信息。
4.Other Problems 一些调整
对于词义相近的单词,可能会拥有相似的上下文,也就拥有了相似的词向量。
但是,skip-gram网络包含大量权重,为了使训练成为可能,word2vec的作者引入了一些调整。
- 对频繁出现的单词进行二次采样,以减少训练示例的数量。
- 使用一种被称为“负采样”的技术调整优化目标,使得每个训练样本只更新模型权重的一小部分。
这样一来不仅减少了训练过程的计算负担,还提高了生成的词向量的质量。
4.1 Subsampling Frequent Words 二次采样频繁词
对于2中的例子,我们发现,像“the”这样的频繁词,并不能提示我们中心词的意思,它实际上出现在很多词语之前;我们会得到比我们需要的更多的样本来得到the的词向量。
Word2Vec采用了二次采样,即我们有可能能有效地删除在训练文本中遇到的每个单词。这种可能性取决于这个单词的频率。
4.1.1 Sampling rate 采样率
word2vec的C代码提供了一个用来计算词汇表中保留给定单词的概率的公式。
w i w_i wi表示单词, z ( w i ) z(w_i) z(wi)表示这个单词在语料库中出现的频率。
参数sample控制二次采样发生的频率,默认值是0.001。更小的sample意味着单词们更不易被留下。
P
(
w
i
)
P(w_i)
P(wi)指保留单词的概率:
P
(
w
i
)
=
(
z
(
w
i
)
s
a
m
p
l
e
+
1
)
⋅
s
a
m
p
l
e
z
(
w
i
)
P(w_i)=(\sqrt{\frac{z(w_i)}{sample}}+1)·\frac{sample}{z(w_i)}
P(wi)=(samplez(wi)+1)⋅z(wi)sample
这个函数的图像如图所示:
我们关注一些特殊点:
- P ( w i ) = 1.0 P(w_i)=1.0 P(wi)=1.0时, z ( w i ) < = 0.0026 z(w_i)<=0.0026 z(wi)<=0.0026,此时一定不会被删除。也就是说频率高于0.26%的单词会被二次采样。
- P ( w i ) = 0.5 P(w_i)=0.5 P(wi)=0.5时, z ( w i ) = 0.00746 z(w_i)=0.00746 z(wi)=0.00746.
- P ( w i ) = 0.033 P(w_i)=0.033 P(wi)=0.033时, z ( w i ) = 1.0 z(w_i)=1.0 z(wi)=1.0,这意味着语料库中只有同一个单词,这显然很荒谬。
4.2 Negative Sampling 负采样
负采样对于每次的训练样本只改变一部分的权重,加速了模型优化速度。同时,由于词义只与它周围的词有关,那么一次更新所有权重显然不合理,因此可以得到更高质量的词向量。
在对(fox,quiak)进行训练时,由于独热码,我们希望quick对应的输出神经元输出一个1,而其他神经元输出0。我们把希望输出0的神经元对应的词称为negative词,输出1的称为positive词。
负采样中,我们会随机选择少量negative词(假设个数为5),更新它们对应的权重。还会更新positive词的权重。
注:对于较小数据集,选择5-20个negative词效果较好;对于大型数据集,只需选择2-5个
我们模型的输出层有一个300x10000的权重矩阵。若采样负采样,则只需更新1个positive词和5个negative词的权重,总共6个输出神经元,6*300=1800个权重。这样就大大减轻了计算压力。
在隐含层中,只更新输入词的权重(无论是否负采样都是这样)。
4.2.1 Selecting Ngative Samples 选择负词
负样本使用一元模型分布来进行选择,也就是更频繁的词更可能被选为负样本。
被选择的概率是某个词在语料库中出现的次数和所有词出现的次数之和的比值。公式如下:
P
(
w
i
)
=
f
(
w
i
)
∑
j
=
0
n
(
f
(
w
i
)
)
P(w_i)=\frac{f(w_i)}{\sum_{j=0}^n(f(w_i))}
P(wi)=∑j=0n(f(wi))f(wi)
word2vec的作者在论文中表示,他们尝试了多种对该等式的变体,其中表现最好的是将词数提高到3/4次方。
P
(
w
i
)
=
f
(
w
i
)
3
/
4
∑
j
=
0
n
(
f
(
w
i
)
3
/
4
)
P(w_i)=\frac{f(w_i)^{3/4}}{\sum_{j=0}^n(f(w_i)^{3/4})}
P(wi)=∑j=0n(f(wi)3/4)f(wi)3/4
尝试一些样本值,我们会发现,下面的等式更倾向于增加出现频率较低的词的概率并降低出现频率较高的词的概率。
在代码实现中,有一个包含100M个元素的大数组,被称为unigram表。用词汇表中每个单词的索引多次填充这个数组,每个词的索引在表中出现的次数由 P ( w i ) ∗ t a b l e _ s i z e P(w_i)*table\_size P(wi)∗table_size给出。在选择负样本时,只需随机生成0到100M间的整数,得到表中记录的索引。这是因为更高频率出现的词在大数组中出现的概率也更高。