最近博客开的分支有点多,PRML、RL、TensorFlow,现在又开一个NLP,有点忙不过来了。主要是组内最近开了RL和NLP两个方向,而我都需要跟进,当然NLP不是我的主要方向,因此写博客我也就写得简略一些。
学习的主要的参考材料是Stanford的公开课程。
Word vectors的主要思想,是用在文档中某个词附近出现的词来表示这个词(也就是说,如果两个词,它们在语料中附近出现的词都差不多,那么它们的语义应该也差不多)。
我们设置一个window size,然后就可以用cooccurrence matrix来用一个词周围出现的词来表示它。所谓的window size,即对于当前这个词,前后多少个词属于在它的周围。
给定一个较小的语料库:
I like deep learning.
I like NLP.
I enjoy flying.
设定window size为1,即只考虑前后一个单词。
可以得到cooccurrence matrix:
counts I like enjoy deep learning NLP flying . I 0 2 1 0 0 0 0 0 like 2 0 0 1 0 1 0 0 enjoy 1 0 0 0 0 0 1 0 deep 0 1 0 0 1 0 0 0 learning 0 0 0 1 0 0 0 1 NLP 0 1 0 0 0 0 0 1 flying 0 0 1 0 0 0 0 1 . 0 0 0 0 1 1 1 0
得到了cooccurrence matrix其实我们就已经得到了最初的vector,每一个单词都可以用cooccurrence matrix中的一行向量来表示。但是,cooccurrence matrix是一个稀疏矩阵,不仅占用的空间大,而且所表示的特征不明显。因此我们考虑降维,直接可以想到的是奇异值分解SVD(关于SVD的计算过程不在这里细讲,可以参考相关书籍,我可能会在之后写一个博客讲吧)。
当然,前面两节得到的vector还不是我们真正要讲的。这一节才真正开始讲我们的word2vec。SVD方法很好,但主要的问题是,每当我们新增一个词,或者有新的语料,SVD都需要重新跑一遍,而对于一个n*m的矩阵,跑一遍SVD的时间复杂度是O(mn2)的(n
这里就直接给出我们的目标方程,给定一个中心词,我们希望最大化它上下文中出现的词的概率:
在求解这个问题之前,我们先了解一下涉及到的一些简单的数学。
对于最小化问题,我们可以使用梯度下降的方式求极值,得到一个局部最优解,如果最小化的目标函数是凸的,那得到的局部最优解就是全局最优解。
我们以一元的函数为例,一元函数的梯度就是导数。设 f(x)=x4−3x3+2 ,它的导数为 f′(x)=4x3−9x2 。我们用伪代码来表明梯度下降的计算过程。
x0=0,x1=6,θ=0.00001,ε=0.01
while(|x1−x0|>θ)
x0=x1
x1=x0−ε×f′(x0)
printx1,f(x1)
其中, θ 是求解的精度, ε 是每一步调整的大小。梯度下降就是先任意取一个初始的x,然后沿着梯度方向调整,直到最终取到极值(因为极值的地方函数值变化小,所以可以用 θ 来判断)。为什么采用梯度方向,是因为梯度方向函数的变化最大,越容易接近极值点。
∂xTa∂x=∂aTx∂x=∂∑ixiai∂x=[d∑ixiaidxj]=[a1a2⋯ad]=a
dydx=dydududx
当然,word2vec到这里还没有完,我的博客主要按照课程的进度写,下一篇将继续讲word2vec。