本次课程的主讲人是Richard Socher,第三讲的重点是对word2vec的回顾和深入理解,包括在数据降维中用到的SVD(Singular Value Decomposition,奇异值分解)的原理、实现以及存在的问题。之后会详细介绍本次课程的重点——GloVe(2014,其作者就包括了Stanford cs224 的两位主讲人Richard Socher和Manning教授)。
对词向量的深入探究
-
Finish word2vec
-
What does word2vec capture
-
How could we capture this essence more effectively?
-
How can we analyze word vectors?
复习回顾:word2vec的主要思想
-
遍历整个语料库中的每一个单词
-
word2vec中存在一个窗口(window)的概念,对于每一个窗口中的中心词(window’s center)我们要预测它的窗口内的上下文单词(surrounding words)
在该式中,是输出的上下文单词中确切的某一个(outside words),c是中心词(center word),和是中心词和上下文单词的向量形式表示。
-
接下来对每一个这样的窗口做随机梯度下降(Stochastic Gradient Descent)
Case study
如上图所示这样的一个语句,此时我们选取"deep”作为中心词,我们首先计算第一个外部单词(outside word) “I” 的概率。
其中分子部分是上下文单词"I"的向量表示和中心词"deep"的向量表示做点乘,如果向量和向量越相似,其点乘后的内积越大;分母部分是遍历词汇表中的每一个单词,将它们与中心词点乘后累加求和。这里用softmax对分子分母取指数形式,将计算得到的数值转化为一种概率分布。
同样,我们计算第二个单词"like"的概率,诸如此类。
以上是以“deep”作为中心词,计算上下文单词的出现概率,计算完成后,窗口右移,以"learning"作为中心词计算上下文单词的概率,以此类推。
在训练一开始的时候,对词进行表示的所有向量都是随机的,然后对这些向量进行求导,为了最终能够最大化概率,对每一个窗口进行随机梯度下降。但是每一个窗口最多只有个词,因此 会非常稀疏.
【分析】
在上述式子中,分母要遍历语料库词汇表中每一个单词,将其与中心词进行点乘求和,当词汇表非常大时,需要很多的计算资源。而且很多单词与其他词从未并发出现过。
【解决方法】
实际上,我们只需要对预测出来的窗口中的上下文单词与原本单词进行对比,因此每次更新只更新矩阵的少数列(对和的完全嵌入),或者为每个词向量建立一个哈希映射,在哈希映射中键(key)是词的字符串表示,值(value)是词的向量表示。
You could also implement this as essentially a hash where you have keys and values.The values are the vectors,and the keys are the word strings.
近似:负采样(任务1)
每次梯度更新都需要计算一遍中心词向量和其他词向量的内积,这是一个不小的计算量,我们重新观察下式,会发现分子部分的计算非常简单,即两个上百维向量做点乘,这一部分计算非常快;但是遍历整个语料库所得到的每一个窗口,对每一个词求概率时,在分母部分都需要做一个巨大的求和,并且很多词和其他单词从未并发出现过。
因此负采样的策略产生了,他随机抽取一定数目的随机词(尽量在中心词上下文中没出现过的词),然后最小化中心词和他们出现的概率,最大化中心词和上下文词出现的概率。
因此在这里布置了任务1,用负采样来实现skip-gram。
Main idea: train binary logistic regressions for a true pair(center word and word in its context window) versus a couple of noise pairs(the center word paired with a random word)
主要思想:训练一对真实对的二元逻辑回归(其实也就是一个二分类器,中心词和上下文窗口中的单词)与几对噪声对(中心词与随机词配对)
总体目标函数: ,其中T在这里对应着遍历语料库的每一个窗口
而
-
k就是我们采用的负采样的个数,下标t代表的就是某个窗口。该式中的第一项是中心词和窗体中上下文单词并发出现的对数概率,这里的Sigmoid 函数 ,图像如下,可以看到在趋于正无穷或负无穷时,函数趋近平滑状态,并且该函数输出范围在(0,1)之间,因此通常用于表征事件概率,函数具有非常好的对称性。
对向量之间进行点乘,所得到的内积可以表征词之间的相关性,而上述目标函数就是要最大化中心词与其上下文单词的相关概率,最小化与其他未并发出现词语的相关概率。因此,每次的梯度更新只需要更新对应向量即可,不需要对所有向量进行计算,以此大大减少了计算量。
Word2vec improves objective function by putting similar words nearby in space.
Word2vec 通过把相似的词语放在同一个地方来最大化目标函数。
对word2vec的总结概括
- 遍历整个语料库的每一个单词
- 将每一个单词作为中心词,预测其上下文单词
- 每一次计算可以捕获到一个并发出现的单词
- 为什么不直接捕获词与词之间的并发计数呢?
词共现矩阵
(Yes,We can!)
可以用一个词共现矩阵来实现。
基于统计共现矩阵的方法早在word2vec之前就已经存在,主要分为两种,一种是将窗口视为训练单位,另一种是对整个文档构建一个完全的词并发矩阵。
- 如果在整个文档级别上进行统计,会得到一些综合性主题(general topics),最终导向"潜在语义分析"(Latent Semantic Analysis,LSA)“
- 如果类似于word2vec,在基于窗口级别上统计词性和语义共现,可以同时捕获到句法(POS)和语义信息。
示例:基于窗口的共现矩阵
-
本例中窗口半径为1(更常用的窗体半径是5-10)
-
在如下句子上统计共现次数:
- I like deep learning.
- I like NLP.
- I enjoy flying.
得到词共现矩阵如下:
-
这种朴素共现向量出现的问题:
-
矩阵的大小随词汇表的增大而剧增
-
也因此向量具有非常高的维度,需要占用很大的存储空间
-
随后的分类模型会出现稀疏性问题
-> 模型缺少鲁棒性(robust)
-
-
解决办法:低维向量
-
以一个固定的,低维向量来存储"最"最要信息:一个密集向量
-
通常在25-1000维,类似于word2vec
-
怎么实现降维呢?
——SVD(Singular Value Decomposition)
-
Basically,we’ll have this X hat matrix,which is going to be our best rank k approximation to our original co-occurrence matrix X.And we will have three simple matrices with orthonormal columns.U we often call also left-singular vectors and we have here S the diagonal matrix containing all the singular values usually from largest to smallest.And we have our matrix V here,our orthonormal rows.
这种方法在代码中的表现也同样简单明了:
import numpy as np
import matplotlib.pyplot as plt
la = np.linalg
words = ["I" , "like" , "enjoy" , "deep" , "learning" , "NLP" , "flying" , "."]
X = np.array([
[0,2,1,0,0,0,0,0],
[2,0,0,1,0,1,0,0],
[1,0,0,0,0,0,1,0],
[0,1,0,0,1,0,0,0],
[0,0,0,1,0,0,0,1],
[0,1,0,0,0,0,0,1],
[0,0,1,0,0,0,0,1],
[0,0,0,0,1,1,1,0]
])
U, s, Vh = la.svd(X, full_matrices=False)
for i in range(len(words)):
plt.scatter(U[i, 0], U[i, 1])
plt.text(U[i, 0], U[i, 1], words[i])
plt.show()
在pycharm中执行如下: