学习笔记412—词向量【Word2Vec】

发布时间 2023-08-21 16:20:40作者: 何弈

Word2Vec

Word2Vec 是 google 在2013年提出的词向量模型,通过 Word2Vec 可以用数值向量表示单词,且在向量空间中可以很好地衡量两个单词的相似性。

简述

我们知道,在使用神经网络处理数据的时候,神经网络只能处理数字向量或者矩阵,他不可能理解文本、图像本身。那么,图像是用像素表示的,这个在最早显示图像的时候就已经和神经网络的使用不谋而合,但是文本是人类自然产生的,没有办法直接映射成数据。

当然了,也可以简单的映射,one-hot编码就可以了,这也是神经网络在处理数据时,遇到非数字信息的特征常用的方案,比如男女映射成0/1.但是简单的用one-hot编码肯定存在很大的问题,其一就是当词汇表的容量变得相当大时,词向量空间也会变得十分巨大;此外就是这样的映射数据本身之间没有联系。

比如,man,boy之间应该是很相似的,也就是说,在映射到的矩阵中的数值应该是十分相似的才行,这样就有了Word2Vec.

 

 其实就是对神经网络的一个很简单的应用。我们首先对输入进行编码,即人为随机地给词汇表做一个映射矩阵,让每一个词汇对应一个向量,当然了,不一定像上图一样用one-hot,你可以使用任何策略,N维你也可以随意设置,一般是50-300维度。

他的重点在于,我在训练网络的时候,不仅仅更新我网络的权重矩阵,我还要更新输入的这个映射矩阵,目的就是为了让我的映射矩阵逐渐地变成计算机能够理解的那个分布,举个例子:

 

 训练完后,可以看到man和boy之间是有很多区域分布相同或者相似的,因此man和boy这两个词在词向量空间中的距离其实是比较近的;相反的,二者与water之间几乎看不到什么联系,也就是说二者与water之间的距离是非常遥远的。

 

数据集构建与训练策略

首先就是数据来源。但是我们做这个训练是不需要有标签的,是一个无监督的过程,因此任何文本都可以拿过来做数据集。具体怎么构建呢?举个例子:

 

 拿到一句话,给定一个窗口,然后我们选择前两个词作为输入,第三个词作为输出,也就是正确结果,label。换句话说,就是我们要根据前两个词对第三个词做一个预测。随后,滑动这个窗口,滑动一次我们就又得到一条训练数据,以此类推,就可以得到一个就很大的数据集。

当然了,这个窗口大小也不一定是3个,可以是5个,7个,一般都是奇数(大概是实验结论),但好像用的比较多的是3个的窗口,可能因为一句话也就5个字甚至不足五个字的数据相对来说还是没那么少的,为了利用上这些数据,所以窗口不应该特别大。

而现在最常用的训练方案有两个:CBOW和Skip-gram

 

 其实二者的区别一目了然,就是一组互逆的方案,CBOW是挖掉中心的一个词,叫模型根据上下文去预测中心词;反之,Skip-Gram是根据中心词去预测其上下文的词。

 在实际使用中,选择两种方案没有本质区别,结果基本一样。

 

优化方法

为什么要讲优化方法呢?很简单,我们仔细再看一眼数据的输入和输出,我们输入了一组单词,输出了一个单词,注意,输出了一个单词,虽然我们的本质是预测,但其实就相当于“这组单词是属于输出的这个单词”的,也就是说,这完全就是一个分类问题,如果你的词汇表有5w个,那么这就是一个5w分类,这显然是一个很疯狂的事情,Softmax压力巨大。因此,我们需要简化这部分计算。

1、层级的Softmax

 

 

 但是迪哥没有讲这个方案,大概是因为使用比较少?或者是很复杂?

2、负样本采样

这个的前提是,你的训练策略又要改变,因为他需要你把一个N分类问题转化为2分类问题,具体操作是:

我们输入这个单词和这个单词上下文的单词,具体点就是我们输入两个相邻的单词,然后判断其是否相邻就行了。

这样的话,问题就又来了——我们构建的数据集肯定全是相邻的单词对不对?那么我们的label肯定全是1,那么模型就会被学成一个只会蒙1的傻子,因此我们需要为其注入负样本。

具体操作也很简单,给定一个单词,然后随机为其配对几组其他的单词即可,当然了,配对之后的单词不应该存在于原来你构建好的正例样本中。

但是有一个点我其实蛮疑惑的,就是说这个负样本的数量应该是多少呢?直觉上,我们肯定是希望正负样本平衡1:1最好,但是迪哥说实验经验是,5个/词比较好。

总体来说,这个要比层级的Softmax更加简单一些。

 

 总体说来,Word2Vec的模型更加简单,训练速度快,训练中也会考虑单词的上下文关系。

缺点是,上下文窗口较小,没有考虑全局单词共现的信息,而且每个单词的词向量都是固定的,对一词多义的现象没办法解决。【当然了,简单粗暴的one-hot在这些缺点之上,还有更多缺陷】

 

GloVe

简单理解一下这个和Word2Vec齐名的模型。Global Vectors for Word Representation

打开扫了一眼原始的论文,其实主要的亮点在于两个:

1、用两个词同时出现的条件概率的比值去衡量两个词的相关性,而不是直接用两个词的词向量或者其他的概率形式去比较词与词之间的关系。

打个比方:

 

 我们计算一组条件概率的比值,原文是直接用词频(也就是词语在语料库中出现的次数)来统计的,用第一个条件概率举例子就是,分母是ice这个单词出现的所有次数;分子是在ice出现的时候,其上下文词语中有多少个k的次数,得到的就是在ice条件下出现k的概率。

那么,二者之比就是一个三个词语之间的关系,如果这个比值比较大,那么就说明k与分母的中心词更加相关(如ice就是solid);相反的,比值太小,就说明k与分子的中心词更加相关(比如steam就是gas);与此同时,比值接近于1,要么就是二者都比较相关,要么就是二者都不相关。

这样做的主要目的是,不同的单词出现的词频是不同的,因此计算出来的条件概率会跨越好几个数量级,就算直接用数量计算,几个数量级之间的数据也是很难有可比性的,因此作者认为这种比值更能反映词语之间的联系。

具体将这个方法应用到网络里,还需要进一步的推演,让他变成网络可以使用的公式才可以,具体内容看论文吧还是:https://aclanthology.org/D14-1162.pdf

 

2、对词频十分小的词,我们调整其对网络的影响。

看一眼损失函数:

 

 前面这个f就是用来做这件事的:

 

 即,我们规定一个需要被调整的最大词频,其实本质上就是一个阈值,对于出现频率比这个阈值高的词我们不做任何调整,权重就是1,;否则,让权重变小,词频越低,其对网络的影响能力越小。因为词频小的词往往都是生僻词,小的过分的,很有可能是训练数据中错误的词,因此作者认为这些词属于噪声需要被清理掉。

原文作者还把这个图画出来了,水了10行内容(笑哭):

 

 

 

参考资料:

1、迪哥的视频:https://www.bilibili.com/video/BV1MS4y147js?p=5&spm_id_from=pageDriver&vd_source=920f8a63e92d345556c1e229d6ce363f

2、知乎:https://www.bilibili.com/video/BV1MS4y147js?p=5&spm_id_from=pageDriver&vd_source=920f8a63e92d345556c1e229d6ce363f

3、GloVe:https://www.bilibili.com/video/BV1Nt4y137iS/?spm_id_from=333.337.search-card.all.click&vd_source=920f8a63e92d345556c1e229d6ce363f

4、https://www.cnblogs.com/loveandninenine/p/17168191.html