本文介绍两种词向量:它们分别是2014年由Stanford团队发表的GloVe和2017年由Facebook团队发表的fastText。
GloVe
GloVe使用了词与词之间的共现(co-occurrence)信息。我们定义XX为共现词频矩阵,其中元素xijxij为词jj出现在词ii的环境(context)的次数。这里的“环境”有多种可能的定义。举个例子,在一段文本序列中,如果词jj出现在词ii左边或者右边不超过10个词的距离,我们可以认为词jj出现在词ii的环境一次。令xi=∑kxikxi=∑kxik为任意词出现在词ii的环境的次数。那么,
Pij=ℙ(j∣i)=xijxiPij=P(j∣i)=xijxi
为词jj出现在词ii的环境的概率。这一概率也称词ii和词jj的共现概率。
共现概率比值
GloVe论文里展示了以下一组词对的共现概率与比值:
- ℙ(k∣ice)P(k∣ice):0.00019(kk= solid),0.000066(kk= gas),0.003(kk= water),0.000017(kk= fashion)
- ℙ(k∣steam)P(k∣steam):0.000022(kk= solid),0.00078(kk= gas),0.0022(kk= water),0.000018(kk= fashion)
- ℙ(k∣ice)/ℙ(k∣steam)P(k∣ice)/P(k∣steam):8.9(kk= solid),0.085(kk= gas),1.36(kk= water),0.96(kk= fashion)
我们通过上表可以观察到以下现象:
- 对于与ice相关而与steam不相关的词kk,例如k=k=solid,我们期望共现概率比值Pik/PjkPik/Pjk较大,例如上面最后一栏的8.9。
- 对于与ice不相关而与steam相关的词kk,例如k=k=gas,我们期望共现概率比值Pik/PjkPik/Pjk较小,例如上面最后一栏的0.085。
- 对于与ice和steam都相关的词kk,例如k=k=water,我们期望共现概率比值Pik/PjkPik/Pjk接近1,例如上面最后一栏的1.36。
- 对于与ice和steam都不相关的词kk,例如k=k=fashion,我们期望共现概率比值Pik/PjkPik/Pjk接近1,例如上面最后一栏的0.96。
由此可见,共现概率比值能比较直观地表达词之间的关系。GloVe试图用有关词向量的函数来表达共现概率比值。
用词向量表达共现概率比值
GloVe的核心在于使用词向量表达共现概率比值。而任意一个这样的比值需要三个词ii、jj和kk的词向量。对于共现概率Pij=ℙ(j∣i)Pij=P(j∣i),我们称词ii和词jj分别为中心词和背景词。我们使用vv和ṽ v~分别表示中心词和背景词的词向量。
我们可以用有关词向量的函数ff来表达共现概率比值:
f(vi,vj,ṽ k)=PikPjkf(vi,vj,v~k)=PikPjk
需要注意的是,函数ff可能的设计并不唯一。首先,我们用向量之差来表达共现概率的比值,并将上式改写成
f(vi−vj,ṽ k)=PikPjkf(vi−vj,v~k)=PikPjk
由于共现概率比值是一个标量,我们可以使用向量之间的内积把函数ff的自变量进一步改写。我们可以得到
f((vi−vj)⊤ṽ k)=PikPjkf((vi−vj)⊤v~k)=PikPjk
由于任意一对词共现的对称性,我们希望以下两个性质可以同时被满足:
- 任意词作为中心词和背景词的词向量应该相等:对任意词ii,vi=ṽ ivi=v~i
- 词与词之间共现次数矩阵XX应该对称:对任意词ii和jj,xij=xjixij=xji
为了满足以上两个性质,一方面,我们令
f((vi−vj)⊤ṽ k)=f(v⊤iṽ k)f(v⊤jṽ k)f((vi−vj)⊤v~k)=f(vi⊤v~k)f(vj⊤v~k)
并得到f(x)=exp(x)f(x)=exp(x)。以上两式的右边联立,
exp(v⊤iṽ k)=Pik=xikxiexp(vi⊤v~k)=Pik=xikxi
由上式可得
v⊤iṽ k=log(xik)−log(xi)vi⊤v~k=log(xik)−log(xi)
另一方面,我们可以把上式中log(xi)log(xi)替换成两个偏移项之和bi+bkbi+bk,得到
v⊤iṽ k=log(xik)−bi−bkvi⊤v~k=log(xik)−bi−bk
将索引ii和kk互换,我们可验证对称性的两个性质可以同时被上式满足。
因此,对于任意一对词ii和jj,用它们词向量表达共现概率比值最终可以被简化为表达它们共现词频的对数:
v⊤iṽ j+bi+bj=log(xij)vi⊤v~j+bi+bj=log(xij)
损失函数
上式中的共现词频是直接在训练数据上统计得到的,为了学习词向量和相应的偏移项,我们希望上式中的左边与右边越接近越好。给定词典大小VV和权重函数f(xij)f(xij),我们定义损失函数为
∑i,j=1Vf(xij)(v⊤iṽ j+bi+bj−log(xij))2∑i,j=1Vf(xij)(vi⊤v~j+bi+bj−log(xij))2
对于权重函数f(x)f(x),一个建议的选择是,当x<cx<c(例如c=100c=100),令f(x)=(x/c)αf(x)=(x/c)α(例如α=0.75α=0.75),反之令f(x)=1f(x)=1。需要注意的是,损失函数的计算复杂度与共现词频矩阵XX中非零元素的数目呈线性关系。我们可以从XX中随机采样小批量非零元素,使用随机梯度下降迭代词向量和偏移项。
需要注意的是,对于任意一对i,ji,j,损失函数中存在以下两项之和
f(xij)(v⊤iṽ j+bi+bj−log(xij))2+f(xji)(v⊤jṽ i+bj+bi−log(xji))2f(xij)(vi⊤v~j+bi+bj−log(xij))2+f(xji)(vj⊤v~i+bj+bi−log(xji))2
由于xij=xjixij=xji,对调vv和ṽ v~并不改变损失函数中这两项之和的值。也就是说,在损失函数所有项上对调vv和ṽ v~也不改变整个损失函数的值。因此,任意词的中心词向量和背景词向量是等价的。只是由于初始化值的不同,同一个词最终学习到的两组词向量可能不同。当所有词向量学习得到后,GloVe使用一个词的中心词向量与背景词向量之和作为该词的最终词向量。
fastText
fastText在使用负采样的跳字模型基础上,将每个中心词视为子词(subword)的集合,并学习子词的词向量。
以where这个词为例,设子词为3个字符,它的子词包括“<wh”、“whe”、“her”、“ere”、“re>”和特殊子词(整词)“<where>”。其中的“<”和“>”是为了将作为前后缀的子词区分出来。而且,这里的子词“her”与整词“<her>”也可被区分。给定一个词ww,我们通常可以把字符长度在3到6之间的所有子词和特殊子词的并集wGw取出。假设词典中任意子词gg的子词向量为zgzg,我们可以把使用负采样的跳字模型的损失函数
−logℙ(wo∣wc)=−log11+exp(−u⊤ovc)−∑k=1,wk∼ℙ(w)Klog11+exp(u⊤ikvc)−logP(wo∣wc)=−log11+exp(−uo⊤vc)−∑k=1,wk∼P(w)Klog11+exp(uik⊤vc)
直接替换成
−logℙ(wo∣wc)=−log11+exp(−u⊤o∑g∈wczg)−∑k=1,wk∼ℙ(w)Klog11+exp(u⊤ik∑g∈wczg)−logP(wo∣wc)=−log11+exp(−uo⊤∑g∈Gwczg)−∑k=1,wk∼P(w)Klog11+exp(uik⊤∑g∈Gwczg)
我们可以看到,原中心词向量被替换成了中心词的子词向量的和。与整词学习(word2vec和GloVe)不同,词典以外的新词的词向量可以使用fastText中相应的子词向量之和。
fastText对于一些语言较重要,例如阿拉伯语、德语和俄语。例如,德语中有很多复合词,例如乒乓球(英文table tennis)在德语中叫“Tischtennis”。fastText可以通过子词表达两个词的相关性,例如“Tischtennis”和“Tennis”。
结论
- GloVe用词向量表达共现词频的对数。
- fastText用子词向量之和表达整词。
参考文章:
1. http://zh.d2l.ai/chapter_natural-language-processing/glove.html
2. http://zh.d2l.ai/chapter_natural-language-processing/fasttext.html