CS224N学习笔记(三)—— 高级词向量表示

一、GloVe模型

基于统计的词向量模型以基于SVD分解技术的LSA模型为代表,通过构建一个共现矩阵得到隐层的语义向量,充分利用了全局的统计信息。然而这类模型得到的语义向量往往很难把握词与词之间的线性关系(例如著名的King、Queen、Man、Woman等式)。
基于预测的词向量模型则以基于神经网络的Skip-gram模型为代表,通过预测一个词出现在上下文里的概率得到embedding词向量。这类模型的缺陷在于其对统计信息的利用不充分,训练时间与语料大小息息相关。不过,其得到的词向量能够较好地把握词与词之间的线性关系,因此在很多任务上的表现都要略优于SVD模型。

既然两种模型各有优劣,那么能不能二者各取其长,构造一个更强大的词向量模型呢?

在GloVe的原始论文里,作者首先分析了Skip-gram模型能够挖掘出词与词之间线性关系的背后成因,然后通过在共现矩阵上构造相似的条件,得到一个基于全局信息的词向量模型——GloVe模型。

1.1 统计共现矩阵

共出矩阵其实很容易理解,假设现在有共现矩阵为 X,则 X_i,j 的意义就是在整个语料库中,单词 i 和单词 j 共同出现在一个窗口中的次数。

例如有语料库:i love you but you love him i am sad

这个小小的语料库只有1个句子,涉及到7个单词:i、love、you、but、him、am、sad。
如果我们采用一个窗口宽度为5(左右长度都为2)的统计窗口,那么就有以下窗口内容:

以窗口5为例说明如何构造共现矩阵:
中心词为love,语境词为but、you、him、i,则:

使用窗口将整个语料库遍历一遍,即可得到共现矩阵X。

1.2 使用GloVe模型的原理

如果想利用全局的统计信息的话,那么必然需要将其纳入到词向量的训练过程中,最直接的方法当然是构建包含全局统计信息的损失函数。那么,该如何构建呢?

首先我们考虑共现矩阵的信息能不能用另外的方式来表示,使得我们可以通过网络学习。

如上面的共现矩阵表示形式,表示了词 k 和 词 i 所在的上下文中出现的次数, 表示以词i为中心的上下文的所有词,那么我们就可以得到:

单词k出现在单词i语境中的概率

使用同样的计算过程,我们可以得到单词 k 出现在单词 j语境中的概率。通过将两个概率相除,便可以得到如下结果:



通过研究最后一行的可以看出,这个比值很好地反应了词之间的关系:

也就是说,只要我们使用网络,让其学习这个概率,那么最后学习得到的词向量也就包含了共现矩阵的全局统计信息。

所以,现在的问题也就转化成了如何用网络或者说设计损失函数学习这一规律。

由这些信息直接构建损失函数有点困难,那么干脆我们由果索因,如果我们有这么一个网络可以做到我们所设想的事情,那么它比如可以写出如下的式子:

g函数就是我们的网络,也就是说,我们最后学到网络必然应该使得上式尽可能成立。那么,最自然的想法就是用差值来衡量两者的相近程度:

但这样的包含3个单词的损失函数是极难训练的,所以比如需要对g函数做一定的优化。

首先考虑的是 , 直接的关系,可以想象由于 和 之间的差异才会使得上述规律存在,那么网络在学习用 、 和 作为输入得到 时,必然会学习 , 之间的差异,那么我们直接先用式子表示出,之间的差异不就可以减少网络学习的难度了吗?

由于词向量具有线性关系,也就是说向量空间是内在的线性结构,所以表示 , 之间的差异最自然有效的方法就是做差。(PS:其实我觉得这边做差其实也就是为了简单,因为神经网络是一个很强的非线性模型,所以其完全可以在学习过程中修正只是做差所带来的差异。也就是说,我们这边做差只是帮网络简化了其学习过程,否则它可能还要试试更多的四则运算从而才能找到最后的结果。与其这样,不如我们直接就给出一个相对比较正确的差异表示方法,从而节省一些没必要的尝试过程)

又因为考虑到 是一个标量,而 、和 都是向量,那么从向量到标量最直接的方法也就是点乘:

这样我们也就表示出来g函数,但是仔细一看,这个损失函数还是很难训练。那么接着考虑,我们可以看出 是一个除法结构,那么作为等式的另一边,必然也应该可以表示成这样的除法结构。于是考虑通过引入exp函数做到这样的操作:

然后就发现找到简化方法了:只需要让上式分子对应相等,分母对应相等。

通过观察可以发现,分子分母的形式是相似的,也就是说我们完全可以通过统一的形式来学习:

注意:这边下标表示替换了一下,与上面的表示方法并不相同,不要对号入座

通过对两边去对数,我们可以将损失函数简化成:

但仔细深究就会发现这个损失函数是有问题的,由上述推导可以得到:

对于这样的向量乘法来说,互换下标不会改变其最后的结果,但P互换则不相等。我们将展开可以得到:

我们发现前一项刚好下标互换不会改变结果,那么我们可以学习这一项:

于是损失函数就变成了:

该损失函数的一个主要缺点为它认为所有的共现词权重相等,即使很少出现或没有出现的词,所以为了克服这一缺点,使用了加权最小二乘回归模型。也就是说基于出现频率越高的词对其权重应该越大的原则,在损失函数中添加权重项,于是代价函数进一步完善:

具体权重函数应该是怎么样的呢?
首先应该是非减的,其次当词频过高时,权重不应过分增大,作者通过实验确定权重函数为:


二、fastText 模型

写在前面的话:fastText的分类模型和词向量训练模型是不一样的,网上很多博客把分类模型作为词向量训练模型来讲(PS:本人就被误导得很惨,幸好及时发现)

2.1 基本原理

fastText的词向量训练模型并不复杂,就是在原来的word2vec上加入的子词信息,理解了子词,基本上fastText的词向量训练模型就掌握了。(子词其实在后面的词向量模型和NLP预训练模型中都有用到)

什么是子词呢?例如对于where这个词,如果我们对这一个词使用n-gram模型,那么若n为3时,我们可以得到(fasttext模型中会对一次词添加上<>符号,也就是说原来的where这个词在fastText的表示中会变成的形式)。另外,其实还会再加上整个词作为一个特殊的子词。也就是说,在训练词向量的时候,每一个词都会变成一个子词集合加入训练,而不是原来单词的一个词。最后在表示一个词的词向量时,通过将子词向量直接加和即可得到词向量。

其训练过程基本和之前的word2vec一致,虽然同样可以采用cbow和skip-gram两种方式,但官方提到在实践过程中skip-gram模型对于子词信息的处理比cbow更好:

在对fine进行词向量训练时

但是对每个词都加入其子词信息会导致所需资源过多,为了有效地减小子词规模,fastText使用hash映射的方法,这也是一种常用的trick,这里就不展开介绍了,有兴趣可以参考:Hash Trick

2.2 子词

fastText的词向量训练模型和传统word2vec模型最大的不同就是在子词的引入上,那么子词信息的引入可以带来什么优势呢?

首先,自然是对词的结构的学习。考虑到词根、词形等特殊结构,如果和传统的word2vec一样只将词作为一个整体来学习,那么就很容易丢失掉这些信息,这是相当可惜的。另外,由于是通过对一个词使用n-gram模型得到子词之后再得到的词向量,所以若在实际使用中出现一个从未出现过的词,便可通过这个新词的子词组合来获得词向量。


参考:

  1. CS224n笔记3 高级词向量表示
  2. http://www.ijiandao.com/2b/baijia/89997.html
  3. https://blog.csdn.net/sinat_26917383/article/details/54847240
  4. https://www.jianshu.com/p/2acc49549af6
  5. glove 学习笔记
  6. word2vec以及GloVe总结
  7. https://www.cnblogs.com/iloveai/p/cs224d-lecture3-note.html
  8. https://fasttext.cc/docs/en/unsupervised-tutorial.html
  9. 论文:Enriching Word Vectors with Subword Information

你可能感兴趣的:(CS224N学习笔记(三)—— 高级词向量表示)