背景
从上一章神经网络语言模型(NNLM)我们了解到,他的优点相比传统的统计语言模型,首次引入词向量word embedding的概念,将离散的统计模型转为了高维空间中的连续稠密向量,解决了传统统计语言模型的平滑问题,并且将Ngram的复杂度的指数增长转为了线性,并且N元组共现未必相似问题也得到一定的解决。但是NNLM由于前馈全链接层网络加上look-up table后参数量过于庞大,训练时间很慢, 并且由于模型参数输入的词数固定等缺陷,尽管后续基于RNN提出RNNLM,依然不能很好解决模型参数过于庞大的问题,于是Word2Vec就被提出, 论文《Efficient Estimation of Word Representations in Vector Space》 和论文 《word2vec Parameter Learning Explained》
模型架构
模型分为CBOW(Continuous Bag-of-Words,词袋模型)和Skip-gram。CBOW模型的训练目标输入是某一个特定词的上下文相关的词对应的词向量,而输出的目标就是这当前特定的词的词向量,因为输入和上下文词的顺序无关,因此称为词袋模型。 Skip-Gram模型和CBOW的思路是反着来的,即输入是特定的一个词的词向量,而输出是特定词对应的上下文词向量。具体CBOW和SKIP-GRAM的比较可以见这里cbow 与 skip-gram的比较。
CBOW
如图所示,我们假设window size为5,我们从
w
(
t
−
2
)
,
w
(
t
−
1
)
,
w
(
t
+
1
)
,
w
(
t
+
2
)
w(t-2), w(t-1), w(t+1), w(t+2)
w(t−2),w(t−1),w(t+1),w(t+2)共同预测中心词
w
(
t
)
w(t)
w(t), 这里的从look up table分别获取
w
(
t
−
2
)
,
w
(
t
−
1
)
,
w
(
t
+
1
)
,
w
(
t
+
2
)
w(t-2), w(t-1), w(t+1), w(t+2)
w(t−2),w(t−1),w(t+1),w(t+2)的词向量,进行sum,average操作,这里和NNLM的区别在于之前的隐藏层是对不同位置词有不同的Weight matrix,这里通过求和平均,共享一个weight matrix矩阵,也就是论文里说的(projection layer is shared for all words),词袋模型的名字也由此的来(所有词因为通过求和取平均,他们的位置不影响输出)。通过反向传播优化,每次更新周围4个词向量
我们重新对比CBOW和NNLM,假设NNLM的词典大小
V
V
V,纬度
D
D
D,隐藏层纬度为H, 时间复杂度
Q
=
N
×
D
+
N
×
D
×
H
+
H
×
V
Q = N × D + N × D × H + H × V
Q=N×D+N×D×H+H×V, 对于CBOW没有隐藏层(lookup table映射后求和平均后直接通过projection layer),
Q
=
N
×
D
+
D
×
l
o
g
2
(
V
)
Q = N × D + D × log2(V )
Q=N×D+D×log2(V), 这里的log-linear是由于引入了hierarchical softmax或negative sampling,这两个后续介绍.
Skip-gram
如图所示,Skip-gram和CBOW相反,由中心词去预测周围词的概率,这里不做详细解释,和CBOW基本一致,时间复杂度
Q
=
C
×
(
D
+
D
×
l
o
g
2
(
V
)
)
Q = C × (D + D × log2(V ))
Q=C×(D+D×log2(V)), 其中C为winodw size。通过反向传播优化,每次更新当前的词向量。可见,相比NNLM,word2vec主要是减少了hidden layer,并且引入log-linear classifier(也就是hierarchical softmax),大大减少了训练的计算量。
Why it works
本质就是两个相似的词往往拥有相同的语境,比如good和nice,当我们用上下文预测他们时,为了得到相同的输出,输入通常也比较相似,所以对含义相似的词,数据量足够大的时候,模型可以学习到相似的embedding vector
优缺点
优点
- 有着NNLM拥有的优点
- 相比NNLM,减少了模型参数量,大规模训练成为可能
- 考虑了上下文,效果比NNLM好
缺点
由于每个词的embedding在训练后就固定了,对于一词多义无法解决(比如苹果在不同语境下,既可以表示一种水果也能表示一种手机)
附录
介绍实际word2vec在训练的相关trick。
高频词降采样
对于高频词比如“的”等词,实际上对我们训练帮助不大,因此定义一个采样率
P
(
w
i
)
=
(
z
(
w
i
)
0.001
+
1
)
⋅
0.001
z
(
w
i
)
P(w_i) = (\sqrt{\frac{z(w_i)}{0.001}}+1){\sdot}\frac{0.001}{z(w_i)}
P(wi)=(0.001z(wi)+1)⋅z(wi)0.001
z
(
w
i
)
z(w_i)
z(wi)表示
w
i
w_i
wi这个词出现频率,
P
(
w
i
)
P(w_i)
P(wi)为我们训练是否对他进行采样,当
z
(
w
i
)
=
1
z(w_i)=1
z(wi)=1时,
P
(
w
i
)
P(w_i)
P(wi)=0.033,也就是3.3%的概率保留这个词作为训练数据,用这种方法能减少高频词大量出现在训练样本中
Negative Sampling 负采样
其本质是反向传播训练时只更新一部分权重,降低计算量。具体工作原理:softmax计算后,我们希望下一个预测词的神经元输出是1,其余均为0,这里我抽样N个神经元输出0,那个输出1的保留,进行反向传播更新,这样一次我们只更新N+1个词的词向量,这样大大降低了运算量。实际代码里不是随机抽N个负样本。这里每个词被选中的概率为:
P
(
w
i
)
=
f
(
w
i
)
3
/
4
∑
j
=
0
n
f
(
w
j
)
3
/
4
P(w_i)=\frac{f(w_i)^{3/4}}{\sum_{j=0}^{n}f(w_j)^{3/4}}
P(wi)=∑j=0nf(wj)3/4f(wi)3/4
其中
f
(
w
i
)
f(w_i)
f(wi)为词
w
i
w_i
wi的出现次数
Hierarchical Softmax
不要被名字误解,我个人认为这个和softmax没任何关系。
如图,根据Huffman编码构建一颗二叉树,使其有V个叶子节点,表示V个字。
这里简单说明下霍夫曼树的构建方法,计算出词典中所有词的词频作为节点的权重,首先将权重最小的两个节点合并,父节点的权重为两个叶子节点的值之和,之后再在剩下的节点(之前合并的两个节点不在这里考虑中,用他们合并的父节点代替)里选最小的两个重复以上操作,当直到只有一个节点停止迭代。
这样做的好处是,词频高的词会离根节点近,模型实际计算的时候大大减少运算量。同时根据Huffman二叉树性质可以知道每个中间节点都有两个子节点,是个完全二叉树,因此V个叶子节点有V-1个中间节点,计算复杂度正比于
l
o
g
(
V
)
log(V)
log(V), 即为树的高度。从根节点到要预测的词的路径即为编码,假设该词的编码为011,0表示左边,1表示右边,接下来,预测的某个词的概率的计算公式如下:
P
(
w
o
∣
w
i
)
=
(
1
−
σ
(
v
1
T
h
i
)
)
∗
σ
(
v
2
T
h
i
)
∗
σ
(
v
3
T
h
i
)
P(w_o|w_i) = (1-\sigma(v_1^Th_i))*\sigma(v_2^Th_i)*\sigma(v_3^Th_i)
P(wo∣wi)=(1−σ(v1Thi))∗σ(v2Thi)∗σ(v3Thi)
其中这里的
σ
\sigma
σ为sigmoid函数,
v
1
,
v
2
,
v
3
v_1,v_2,v_3
v1,v2,v3就是要学习的参数,相当于之前projection layer输出层矩阵对应节点的向量,
h
i
h_i
hi为skip-gram中为输入词的embedding,cbow中为多个输入词embeding的求和平均向量。这样学习output layer的weight matrix就变成学习霍夫曼树的各个中间节点的参数
v
i
v_i
vi, 根据当前词霍夫曼编码相应节点连乘就能计算得到当前词的概率,如果计算出所有叶子节点的概率值,数学上可以证明所有词的概率之和也为1, 因此说虽然不是softmax,但依然可以作为概率进行学习。另外,因为V个跟节点的霍夫曼树只有V-1个节点,每个中间节点需要学习一个向量,所以这里要学习V-1个向量,而传统的softmax需要学习V个向量,这里比较输出层要学习的weights少了一个向量,参数的数目少了h(假设h为词向量的纬度)
总结,hierarchical softmax和softmax完全不一样,不要因为含了softmax被误导;hierarchical softmax的参数比softmax要学的参数略微减少,输出层参数从
V
h
Vh
Vh减少到了
(
V
−
1
)
h
(V-1)h
(V−1)h, 时间复杂度大大优化,从
O
(
N
)
O(N)
O(N)降低至
O
(
l
o
g
N
)
O(logN)
O(logN)