讲的很好:
苏剑林博客-词向量与embedding
看完这个再看word2vec就容易理解很多。尤其是前面one-hot输入的地方。
提问:word2vec和后验概率有什么关系?
cbow与skip-gram
一、word2vec
回顾:skip-grams
skip-grams和CBOW都属于word2vec的方法,word2vec主要讲了skip-grams,其主要步骤是遍历整个语料库,利用每个窗口的中心词来预测上下文的单词,然后对每个这样的窗口利用SGD来进行参数的更新。
- 第2课 word2vec小总结
- 输入层是一个代表单词的onehot编码。所以和每句话的长度无关,输入层的节点是和语料库大小有关,就是词袋模型。
- 第一步到第二步其实就是 把V维的词向量变成d维的。
- w和w’最开始是随机初始化词向量得到的,w是中心词矩阵,w’是上下文矩阵,然后通过神经网络不断优化。这个模型的参数就是词向量,没有其他权重参数,参数个数是2dv。第2层就是两个矩阵相乘,理论依据是余弦相似度。
- 一个词有两个词向量,是因为同一个词即可以是中心词(作为中心词时,取值来自中心向量矩阵c)和可以是上下文词(作为其他中心词的上下文时,取值来自文本向量矩阵w)。
- softmax得到的是神经网络的输出值,和真实的groundtrue做交叉熵作为损失函数。交叉熵计算的时候要计算整个语料库的词,所以标准的skipgram是计算非常复杂的,需要优化。
- 继续skip-grams
比如有一句话: I like deep learning and nlp.
选择窗口m=2,则:
1.首先选择到中心词deep :
则用中心词deep来预测I的概率如下:
p
(
I
∣
d
e
e
p
)
=
e
x
p
(
u
I
∗
v
d
e
e
p
)
∑
w
=
1
v
e
x
p
(
u
w
∗
v
d
e
e
p
)
p(I|deep)=\frac{exp(u_{I}*v_{deep})}{\sum_{w=1}^{v}exp(u_{w}*v_{deep})}
p(I∣deep)=∑w=1vexp(uw∗vdeep)exp(uI∗vdeep)
用中心词deep来预测like的概率如下:
p
(
l
i
k
e
∣
d
e
e
p
)
=
e
x
p
(
u
l
i
k
e
∗
v
d
e
e
p
)
∑
w
=
1
v
e
x
p
(
u
w
∗
v
d
e
e
p
)
p(like|deep)=\frac{exp(u_{like}*v_{deep})}{\sum_{w=1}^{v}exp(u_{w}*v_{deep})}
p(like∣deep)=∑w=1vexp(uw∗vdeep)exp(ulike∗vdeep)
用中心词deep来预测learning的概率如下:
p
(
l
e
a
r
n
i
n
g
∣
d
e
e
p
)
=
e
x
p
(
u
l
e
a
r
n
i
n
g
∗
v
d
e
e
p
)
∑
w
=
1
v
e
x
p
(
u
w
∗
v
d
e
e
p
)
p(learning|deep)=\frac{exp(u_{learning}*v_{deep})}{\sum_{w=1}^{v}exp(u_{w}*v_{deep})}
p(learning∣deep)=∑w=1vexp(uw∗vdeep)exp(ulearning∗vdeep)
用中心词deep来预测and的概率如下:
p
(
a
n
d
∣
d
e
e
p
)
=
e
x
p
(
u
a
n
d
∗
v
d
e
e
p
)
∑
w
=
1
v
e
x
p
(
u
w
∗
v
d
e
e
p
)
p(and|deep)=\frac{exp(u_{and}*v_{deep})}{\sum_{w=1}^{v}exp(u_{w}*v_{deep})}
p(and∣deep)=∑w=1vexp(uw∗vdeep)exp(uand∗vdeep)
2.窗口向右滑动1个,选择到中心词learning :
则用中心词learning来预测like、deep、and和nlp四个上下文词。
3.存在的问题1—梯度更新存在稀疏性
对于每一个窗口而言,我们只有2m+1个单词(其中m表示窗口的半径),因此我们计算出来的梯度向量是十分稀疏的。(假设有20000个词,每个词100维,则有20000x100个参数需要去优化,因为参数就是词向量,但是每次移动窗口,如上面的例子,只需要更新2x2+1=5个向量,所以梯度很稀疏),大量的梯度更新很快会导致内存的耗尽。
所以相比稀疏矩阵的运算,只需要更新特定的列就可以了,如对于第二个窗口,只需更新like,deep,and和nlp。
或者还有一个解决方法是提供一个单词到词向量的哈希映射。
4.存在的问题2—词表V的量级非常大
在求每一个P时,均需要计算一遍所有的词对于中心词的概率的求和,即下面式子的分母部分,计算量很大,但是事实很多次根本不会出现在中心词附近,如“斑马”不会出现在“深度学习”附近。
要求用negative sampling实现skip-gram。这是一种采样子集简化运算的方法。具体做法是,对每个正例(中央词语及上下文中的一个词语)采样几个负例(中央词语和其他随机词语,仅随机化取出五个、十个或者其他数目的随机词,这些从语料库其余部分取出的随机词是不同时出现的,然后最小化他们与中心词的的概率),训练binary logistic regression(也就是二分类器)。
其中σ(x)是sigmoid函数,t是某个窗口,k是采样个数。
公式中第一项表示我们希望能同时出现的两个词的概率最大化。第二项的sigmoid函数中取了负号,所以其作用是最小化负采样得到的词与中心词共同出现的概率。
第二项的j∼p(w)j∼p(w)表示每个样本j以p(w)的概率进行采样。而这个p(w)可以根据需要自定义,但是一般是采用unigram分布,即根据某个词出现的频率进行抽样。
unigram 一元分词,把句子分成一个一个的汉字
bigram 二元分词,把句子从头到尾每两个字组成一个词语
trigram 三元分词,把句子从头到尾每三个字组成一个词语.
你可能会想万一随机抽样得到的词与第一项中的上下文词汇重复了怎么办?首先这个概率很低,因为词库非常的大;另外即使重复也没关系,因为重复的概率很小,所以影响不是很大。k一般取10左右。
内积可以代表相关性。那么这个目标函数就是要最大化中央词与上下文的相关概率,最小化与其他词语的概率。
5.其他方法
早在word2vec之前,就已经出现了很多得到词向量的方法,这些方法是基于统计共现矩阵的方法。如果在窗口级别上统计词性和语义共现,可以得到相似的词。如果在文档级别上统计,则会得到相似的文档(潜在语义分析LSA)。不考虑语法等信息,只考虑词的共现性。
基于窗口的共现矩阵
比如窗口半径为1,在如下句子上统计共现矩阵:
I like deep learning.
I like NLP.
I enjoy flying.
会得到:
这个矩阵存在的问题是:随着词汇的增长,存储矩阵需要的空间将会变得很大;这个矩阵十分稀疏,不利于模型的稳健构建。所以,我们需要寻找一个方法把这个矩阵降低维度。
方法一:对矩阵X进行降维
对矩阵进行奇异值分解(SVD)
python代码:
一些关于矩阵X的改进
the、he、has等这些单词出现的频率太高了,但他们几乎出现在每个单词的上下文中的时候,它本身也就无法给出一些更有用的信息了。解决方法是有两个,一是对单词同时出现的次数设定一个上限,min(X,t),t~100;或者干脆无视这些单词。
给那些距离中心词更近的单词更多的权重
利用皮尔森相关系数来替代计数,用0来替代负数。
结合词频和word2vec的GloVe模型
目标函数:
J
(
Θ
)
=
1
2
∑
∑
i
,
j
=
1
W
f
(
P
i
j
)
(
u
i
T
v
j
−
l
o
g
P
i
j
)
2
J\left ( \Theta \right )=\frac{1}{2}\sum \sum_{i,j=1}^{W}f(P_{ij})(u_{i}^{T}v_{j}-logP_{ij})^{2}
J(Θ)=21∑i,j=1∑Wf(Pij)(uiTvj−logPij)2
其中:
θ:所有参数
W:遍历每个可能共现的词对,每次优化一个计数。
PijPij:是两个词的共现频次(类似“SVD 共现词频”),也就是两个词同时出现的次数(在拿到数据的时候就可以统计出来了)。
f:是一个max函数,如下所示:从图中可以看出,频次Pij越高,f(Pij)的值一开始也会越大,达到xmax之后,即使频次再高,f(Pij)值也不会再增加了,这在一定程度上对共现频次太高的词起到了抑制作用,控制出现次数比较多的单词对的权重。
我们希望最小化内积(类似“word2vec”)和词对出现次数的对数的距离。
方法的特点:
- 训练起来很快
- 可以扩展成更大的语料库
- 在小的语料库和小的向量的情况下,表现也很好
θ包含了v和u两部分向量,也就是每个词都有两个词向量的,那么最后究竟要选哪一个作为最终的词向量呢?最佳方案是将它们相加作为最终的词向量: 最好的X=U+V。