斯坦福自然语言处理_第三讲(Part 1)


本次课程的主讲人是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)

      p(oc)=exp(uoTvc)w=1Vexp(uwTvc)p(o|c) = \displaystyle \frac{exp({u_{o}}^Tv_{c})}{\sum_{w=1}^V exp({u_{w}}^Tv_{c})}

      在该式中,oo是输出的上下文单词中确切的某一个(outside words),c是中心词(center word),vcv_{c}uou_{o}是中心词和上下文单词的向量形式表示。

    • 接下来对每一个这样的窗口做随机梯度下降(Stochastic Gradient Descent)

    Case study

    Alt

    如上图所示这样的一个语句,此时我们选取"deep”作为中心词,我们首先计算第一个外部单词(outside word) “I” 的概率。

    p(Ideep)=exp(uITvdeep)w=1Vexp(uwTvc)p(I|deep)=\displaystyle\frac{exp(u_{I}^{T}v_{deep})}{\sum_{w=1}^{V}exp({u_{w}}^Tv_{c})}

    其中分子部分是上下文单词"I"的向量表示uIu_{I}和中心词"deep"的向量表示vdeepv_{deep}做点乘,如果向量uu和向量vv越相似,其点乘后的内积越大;分母部分是遍历词汇表中的每一个单词,将它们与中心词点乘后累加求和。这里用softmax对分子分母取指数形式,将计算得到的数值转化为一种概率分布。

    同样,我们计算第二个单词"like"的概率,诸如此类。

    以上是以“deep”作为中心词,计算上下文单词的出现概率,计算完成后,窗口右移,以"learning"作为中心词计算上下文单词的概率,以此类推。

    在训练一开始的时候,对词进行表示的所有向量都是随机的,然后对这些向量进行求导,为了最终能够最大化概率,对每一个窗口进行随机梯度下降。但是每一个窗口最多只有2m+12m+1个词,因此θJt(θ)∇θJt(θ) 会非常稀疏.

    【分析】

    在上述式子中,分母要遍历语料库词汇表中每一个单词,将其与中心词进行点乘求和,当词汇表非常大时,需要很多的计算资源。而且很多单词与其他词从未并发出现过。

    【解决方法】

    实际上,我们只需要对预测出来的窗口中的上下文单词与原本单词进行对比,因此每次更新只更新WW矩阵的少数列(对uuvv的完全嵌入),或者为每个词向量建立一个哈希映射,在哈希映射中键(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)

    每次梯度更新都需要计算一遍中心词向量和其他词向量的内积,这是一个不小的计算量,我们重新观察下式,会发现分子部分的计算非常简单,即两个上百维向量做点乘,这一部分计算非常快;但是遍历整个语料库所得到的每一个窗口,对每一个词求概率时,在分母部分都需要做一个巨大的求和,并且很多词和其他单词从未并发出现过。

    p(oc)=exp(uoTvc)w=1Vexp(uwTvc)p(o|c) = \displaystyle \frac{exp({u_{o}}^Tv_{c})}{\sum_{w=1}^V exp({u_{w}}^Tv_{c})}

    因此负采样的策略产生了,他随机抽取一定数目的随机词(尽量在中心词上下文中没出现过的词),然后最小化中心词和他们出现的概率,最大化中心词和上下文词出现的概率。

    因此在这里布置了任务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)

    主要思想:训练一对真实对的二元逻辑回归(其实也就是一个二分类器,中心词和上下文窗口中的单词)与几对噪声对(中心词与随机词配对)

    总体目标函数: J(θ)=1Tt=1TJt(θ)J(\theta)=\displaystyle\frac{1}{T}\sum_{t=1}^{T}J_{t}(\theta) ,其中T在这里对应着遍历语料库的每一个窗口

    Jt(θ)=log σ(uoTvc)+i=1kEjP(w)[logσ(ujTvc)]J_{t}(\theta)=log \:\sigma(u_{o}^Tv_{c})+\displaystyle\sum_{i=1}^{k}\mathbb{E}_{j \sim P(w)}[log \sigma(-u_{j}^Tv_c)]

​ k就是我们采用的负采样的个数,下标t代表的就是某个窗口。该式中的第一项是中心词和窗体中上下文单词并发出现的对数概率,这里的Sigmoid 函数 σ(x)=11+ex\sigma(x)=\displaystyle\frac{1}{1+e^{-x}} ,图像如下,可以看到在趋于正无穷或负无穷时,函数趋近平滑状态,并且该函数输出范围在(0,1)之间,因此通常用于表征事件概率,函数具有非常好的对称性。

Alt

​ 对向量之间进行点乘,所得到的内积可以表征词之间的相关性,而上述目标函数就是要最大化中心词与其上下文单词的相关概率,最小化与其他未并发出现词语的相关概率。因此,每次的梯度更新只需要更新对应向量即可,不需要对所有向量进行计算,以此大大减少了计算量。

Word2vec improves objective function by putting similar words nearby in space.

Word2vec 通过把相似的词语放在同一个地方来最大化目标函数。

Alt

对word2vec的总结概括

  • 遍历整个语料库的每一个单词
  • 将每一个单词作为中心词,预测其上下文单词
  • 每一次计算可以捕获到一个并发出现的单词
    • 为什么不直接捕获词与词之间的并发计数呢?

词共现矩阵

(Yes,We can!)

可以用一个词共现矩阵XX来实现。

基于统计共现矩阵的方法早在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中执行如下:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章