这个专题的笔记是我在学习斯坦福大学的公开课程CS224N:Deep Learning For Nature Language Processing时所做的一些课程笔记。这是第二部分,主要内容是Word2Vec模型。
Word2vec
基于迭代的模型
基于SVD的方法实际上考虑的都是单词的全局特征,因此计算代价和效果都不太好,因此我们可以尝试建立一个基于迭代的模型并根据单词在上下文中出现的概率来进行编码。
另一种思路是设计一个参数是词向量的模型,然后针对一个目标进行模型的训练,在每一次的迭代中计算错误率或者loss函数并据此来更新模型的参数,也就是词向量,最后就可以得到一系列结果作为单词的嵌入向量。
常见的方法包括bag-of-words(CBOW)和skip-gram,其中CBOW的目标是根据上下文来预测中心的单词,而skip-gram则是根据中心单词来预测上下文中的各种单词出现的概率。这两种方法统称为word2vec,是Google AI团队在《Distributed Representations of Words and Phrases and their Compositionality》 等多篇论文中提出的词向量训练模型。
而这些模型常用的训练方法有:
层级化(hierarchical)的softmax
负采样negative sampling:判断两个单词是不是一对上下文与目标词,如果是一对,则是正样本,如果不是一对,则是负样本,而采样得到一个上下文词和一个目标词,生成一个正样本,用与正样本相同的上下文词,再在字典中随机选择一个单词,这就是负采样
语言模型Language Model
语言模型可以给一系列单词序列指定一个概率来判断它是不是可以作为一个完整的句子输出,一般完整性强的,语义通顺的句子被赋予的概率会更大,而无法组成句子的一系列单词可能就会计算出非常小的概率,语言模型用公式来表示就是要计算下面的概率:
分布式语义(Distributional semantics):一个词语的意思是由附近的单词决定的,一个单词的上下文就是"附近的单词",可以通过一个定长的滑动窗口来捕捉每个单词对应的上下文和语义。
Bi-gram model认为单词出现的概率取决于它的上一个单词,即:
事实上上面提出的CBOW和Skip-gram也可以看成是一种简单的语言模型,我们通过训练一个语言模型的方式来训练出文档中出现的单词的词向量。
连续词袋模型(CBOW)
连续词袋模型(Continuous Bag of Words Model)是一种根据上下文单词来预测中心单词的模型,对于每一个单词我们需要训练出两个向量u和v分别代表该单词作为中心单词和作为上下文单词的时候的嵌入向量(一种代表输出结果,一种代表输入)
因此可以定义两个矩阵
这里其实隐含了一个假设,那就是单词作为上下文和中心词的时候具有的特征是不一样的,因此要用不同的词向量来表示。
CBOW模型的工作原理
首先根据输入的句子生成一系列one-hot向量,假设要预测的位置是c,上下文的宽度各为m,则生成的一系列向量可以表示为:
计算得到上下文单词的嵌入向量:
求出这些向量的均值:
生成一个分数向量
,当相似向量的点积较大时,会将相似的词推到一起,以获得较高的分数 用softmax函数将分数向量转化成概率分布:
根据概率分布
得到最终的结果y(是一个one-hot向量的形式),也就是最有可能出现在中心位置的单词
因此现在的问题就变成了,我们应该如何学习到两个最关键的矩阵
损失函数与优化方式
我们可以定义如下形式的损失函数并进行优化:
Skip-gram模型
Skip-gram模型是一种给定中心单词来预测上下文中各个位置的不同单词出现概率的模型,模型的工作原理可以用如下几个步骤概括:
生成中心单词的one-hot向量
作为输入 得到输入单词的嵌入向量
将分数向量用softmax转化成对应的概率分布
,则 是预测出的对应位置中出现的单词的概率分布,每个概率向量的维度都和词汇表的大小一样 根据概率分布生成对应的one-hot向量,作为最终的预测结果,这里就是将概率最大的那个维度对应的单词作为结果。
参数的求解和模型的优化
与CBOW类似,可以采用类似的方法来优化模型的参数,首先Skip-gram模型是通过中心单词c来预测上下文单词o的出现概率,这一过程可以表示为: loss.backward()
和optim.step()
来解决 - 不过初学的时候推一推公式还是很有意思的,当然我现在已经忘记光了
负采样Negative Sampling
上面提到的算法中,时间复杂度基本都是
在每一次的迭代中,不是遍历整个词汇表而是进行一些负采样操作,我们可以从一个噪声分布中"采样",其概率与词汇表频率的顺序匹配。
负采样可以理解为单词和短语及其构成的分布式表示,比如在skip-gram模型中,假设一对单词和上下文
这里的集合
而Skip-gram的新损失函数就变成了:
这里的
而对于
全局词向量GloVe
已有的单词表示方法
到现在为止已经介绍过的单词表示方法主要分为两种,一种是基于次数统计和矩阵分解的传统机器学习方法,这类方法可以获取全局的统计信息,并很好的捕捉单词之间的相似性,但是在单词类比之类的任务重表现较差,比较经典的有潜在语义分析(LSA)等等
另一类是上面提到的基于"浅窗口"(shallow window based)的方法,比如CBOW和Skip-gram,通过局部的上下文来进行上下文或者中心单词的预测,这样的方法可以捕捉到复杂的语言模式和上下文信息,但是对全局的统计信息知之甚少,缺少"大局观",这也是这些模型的缺点。
而GloVe则使用一些全局的统计信息,比如共生矩阵,并使用最小二乘损失函数来预测一个单词出现在一段上下文中的概率,并且在单词类比的任务上取得了SOTA的效果。
GloVe算法
首先用
可以表示单词j在单词i的上下文中出现的概率。我们在Skip-gram中,用Softmax来计算单词j出现在i的上下文中的概率:
而训练的过程中用到的损失函数如下所示,又因为上下文的关系在样本中可能会多次出现,因此按照如下方式进行变形:
交叉熵损失的一个显著缺点是它要求分布Q被适当地标准化,因此可以换一种方式,也就是使用基于最小二乘的目标函数来进行优化求解,就可以不用进行标准化了:
但是这样子的目标函数又带来了一个新的问题,那就是
结论
GloVe模型通过只训练共生矩阵中的非零元素充分利用了训练样本的全局信息,并且提供了一个拥有比较有意义的子结构的向量空间,在单词类比的任务中表现优于传统的Word2Vec
词向量的评估
目前已经学习了一系列将单词用词向量来表示的方法,接下来的这一部分主要探讨如何评估生成的词向量的质量的好坏。
内部评估
内部评价(Intrinsic Evaluation)是对生成的一系列词嵌入向量,用一些子任务来验证嵌入向量的性能优劣,并且一般这样的子任务是比较容易完成的,这样可以快速反馈词向量训练的结果。
外部评估
外部评估是用一些实际中的任务来评估当前训练获得的词向量的性能,但是在优化一个表现不佳的外部评估系统的时候我们无法确定是哪个特定的子系统产生的错误,这就激发了对内在评估的需求。