Glove和Fasttext

1.Glove

glove是一种使用词与词共现信息的词编码算法,要了解glove,首先需要知道共现频率矩阵,

现在我们的语料库包括下面三份文档资料:

I like deep learning.

I like NLP.

I enjoy flying.

我们设定的窗口大小为1,也就是只看某个单词周围紧邻着的那个单词。此时,将得到一个对称矩阵——共现矩阵。因为在我们的语料库中,I like做为邻居同时出现在窗口中的次数是2,所以下表中I like相交的位置其值就是2

Glove和Fasttext

共现频率矩阵,需要在共现矩阵的基础之上对每一列做归一化,使得其映射在一个概率范围内。

下面是原论文举得例子:

Glove和Fasttext

例如我们提取ice和steam这两列,对应共现频率如上,

我们可以发现,

①当对应行中的单词solid和ice较为相关,但是和steam不太相关的时候,共现频率的比值较大(大于1)

②当对应行中的单词gas和分母的steam较为相关,但是和分子的ice关系较小时,共现频率比值较小(小于1)

③当对应行中的单词和ice与steam同时无关,或同时相关时,共现频率比值趋于1

Glove的核心思维,就是希望得到每一个单词的词向量,并从中任意选取三个单词的词向量经过某种函数作用后,能够呈现出共现频率比值的这一规律性。

即我们的目标是找到一个F,使得:

Glove和Fasttext

其中Pik = P(k | i),k这里相当于已知i出现的情况下,k出现的概率,k可以视为周围词。

下面我们说一下构造这个f的思路:

①上面这个式子考察了i,j,k三个单词两两之间的关系,这里我们可以先考察i与j两个单词的关系,在向量空间中,可以比较容易的想到对这两个向量做差,于是原式可以为:

Glove和Fasttext

②由于等式右边为标量,式子左边f作用于两个向量,于是我们可以将左边的两个向量做内积转为标量。

Glove和Fasttext

③式子左边为减法,右边为除法,将f取做exp将除法与减法联系起来。

Glove和Fasttext

Glove和Fasttext

Glove和Fasttext

④两边取log,有

Glove和Fasttext

⑤我们发现,等式左边对调Vi和Vk并不会影响值,但是右边则会产生一定的影响,为了维持式子的对称性,我们引入两个偏置项bi,bk

Glove和Fasttext

  即

Glove和Fasttext

我们发现,我们由原来的式子推导到现在,目标已经转为利用两个词的词向量以及两个偏置项来去表达二者共现次数的log。

⑥我们使用MSE作为损失函数

Glove和Fasttext

这里的f(Xij)作为代价函数中每一项的加权,

其应该满足以下几点

1.共现次数为0,则f为0

2.f必须为非减函数,即次数越多,相对越重要

3.不能给x过大的太多的权值,如the这一类无意义高频词

综合这三点,我们有

Glove和Fasttext

Glove和Fasttext

最终,glove使用一个词的中心词向量和背景词向量之和作为该词的最终词向量。

2.fastText

fastText是在Word2Vec在skip-gram的基础之上进行改进的,他将每个中心词视为其子词的集合,然后学习子词的词向量,再使用子词的词向量和来代替原有的词向量。这么做的依据,是fastText认为某一个单词的词义,是与其前后缀或某子词有关的。

以 where 这个词为例,设子词为 3 个字符,它的子词包括 "<wh"、"whe"、"her"、"ere"、"re>" 和特殊子词(整词)"<where>",其中 "<" 和 ">" 是为了将作为前后缀的子词区分出来。而且,这里的子词 "her" 与整词 "<her>" 也可被区分。给定一个词 w,我们通常可以把字符长度在 3 到 6 之间的所有子词和特殊子词的并集 Gw 取出。假设词典中任意子词 g 的子词向量为 zg,我们可以把使用负采样的 skip-gram 模型的损失函数

Glove和Fasttext

直接替换为

Glove和Fasttext

其优点在于,对于词典以外的新词词向量可以使用fastText中相应子词向量之和。

在fastText中,对于一个词w,我们将它所有长度在3∼6的子词和特殊子词的并集记为 Glove和Fasttext 。那么词典则是所有词的子词集合的并集

这样的话,在训练过程中,对于一个输入的单词,首先要将其分解为对应的子词,然后在输入的权重矩阵中找到其所有子词对应的向量,然后做和,再和周围词在输出权重矩阵的对应向量相乘,最后做softmax。

补充一个细节,由于fastText中的子串过于庞大,获取所有子串的向量不太现实,解决的方式是将子串用一个hash桶存储,即拉链法,映射到同一个桶的子串使用相同的embedding。