阅读大概需要5分钟 跟随小博主,每天进步一丢丢
作者:gan 链接:https://zhuanlan.zhihu.com/p/36312907
背景介绍和一些直观的理解
word2vec 是2012年被被Google提出来的将文本生成词向量模型,其中包括了两个模型,continous bag of words(CBOW)和Skip Gram。两个模型分别从两个角度来建立词的预测模型,CBOW是通过一个或多个单词的上下文来进行这个词语的预测,而Skip Gram模型是通过一个或多个单词来进行上下文的预测。
首先我们需要理解的一个问题,为什么我们需要对词进行编码,也就是所谓的词向量化?我们知道任何数学模型,其输入都需要是数值型的,而在自然语言处理中,我们面对的是文字,而文字是无法直接被数学模型所直接利用的。所以我们需要将文字进行编码,而编码就是给每一个字符一个向量来进行表示。在word2vec出来之前,我们常用的主要是one hot encoding的方法,也就是对于每一个单词,我们用在一个位置为1,其余位置为0的向量进行表示。而向量的维度就是我们单词量的大小。而向量的每一个位置,只能用来表示唯一的一个单词。举个例子,假设我们的有词库只有10个单词,分别是:今,天,是,你,我,他,买,水,果,家。这里我们分别用one hot encoding的方法来表示每一个词,那么有下面的结果:
可以看到对于每一个单词,我们用唯一的一个向量对它进行了表示。那么很显然这种表示方法至少有下面的一些缺陷
所以,词向量的提出目的就是解决上面提到的这些问题。而词向量主要有以下一些特点
。这个是很漂亮的一个近似关系,相当于说v1-v2近似的等于首都这种关系,也正是受到word2vec的启发,在知识图谱表示学习中,衍生了一些名为Trans的编码算法
CBOW模型的介绍
前面也说了,CBOW模型是用于一个单词的上下文来进行单词的预测。换句话说,就是看了一个或多个单词的上下文,我们希望能对词库中所有的单词有个概率的预测,而我们想要预测的一个或多个单词,它的概率要尽可能的大。这不正好就掉入了极大释然估计的管辖范围了吗?如果我么有一大堆的上下文和要对应要预测的一个或多个单词,既然我们的模型对于每一个或多个单词都有一个概率的估计,那么我们根据我们已有的样本,把它们的概率全部乘起来,然后通过调整模型的参数最大化这个概率。
一个上下文预测一个单词的情况
我们先来理解这种最简单的恶情况,这个理解清楚了,推广到其它复杂的情况其实是很直接和水到渠成的事情了。我们以两个简单的句子来作为例子:
一般中文中训练词向量时,都会将句子进行分词,上面我用空格将词进行了分割,这里不对分词进行介绍。在CBOW模型中,有一个窗口参数,具体意思就是上下文的定义在距离这个单词左右不超过窗口的距离。这里我们窗口设置为2。那么按照这个规则,我们可以生成下面的训练样本,第一个位置为上下文,第二单词为中心词汇
在这次例子中,我们的单词总量一共是九个(简单器件就假设这为我们全部的单词),分别为”他”,”今天”,”很”,”开心”,”她”,”好像”,”不”,”太”,”高兴”,并且有下面的one hot encoding。
假设我们最后需要的词向量为维度为3的向量,那么我们可以构建如下图所示的全链接的三层的神经网络(9×3×9),最后一层嵌套一个softmax函数进行每个单词概率的输出。
从输入层到隐藏层的变换,我们可以用一个9×3的矩阵来表示,初始化为
从隐藏层到输出层,我们可以用一个3×9的矩阵来表示,初始化为
有了上面的这些符号,那么我们来看我们第一个样本(今天,他)经过我们的模型变换会得到什么样的结果。因为今天=
,那么从输入层到隐藏层,进行矩阵乘法
而
就是“今天”在CBOW下的编码,当然因为这里只是初始化的值,后面模型会随着样本的训练而调整这个数值,从而得到最后“今天”真正的编码。
从隐藏层到输出层,直接继续进行矩阵的乘法,那么有
在进行softmax的变化,我们得到了最后对于每个单词的预测概率均为19,而我们的训练样本是希望“他”对应的概率要尽量的高,也就是”他”的概率要为1,其它的单词概率为0,这样模型的输出和真实的样本存在了偏差,那们我们就可以直接利用这个误差来进行反向传递,调整我们模型的参数
,从而达到了学习调优的目的。
如果我们再回头看上面的计算流程,其实可以这样理解上面的矩阵
。对于每一个单词v,我们给其赋予两个编码,分别记为
,此处我们都默认向量都是列向量,那么
构成了矩阵
中单词 v 对应的那一行,
对应了矩阵
中单词 v 对应的那一列。而通过单词 v 对其它单词任意单词 s 预测的概率通过下面的公式求得
其中
为两向量的内积,现在我们有一系列的观测样本,
,那么基于上面的分析,我们可以构建基于这些样本的释然函数,有
取对数后有
所以最后我们其实就是在最大化释然函数。为什么说计算上面的释然函数很复杂呢?大家可以看到对数里面的求和项,其实需要对所有单词进行一次遍历,也就是说如果我们词库有1万个单词,那么每一步迭代就需要计算一万次,如果词库有一百万,一千万甚至是上亿的单词量呢?可想而知道,这个计算量是相当当大的。所以有一系列的方法来逼近这个计算,后面我们也会介绍hierarchical softmax和negative sampling的方法,他们是为解决这个计算效率问题的。
多个上下文预测一个单词的情况
前面说了那么个多一个上下文预测一个单词的情况,接下来我们再讲讲怎么扩展到多个上下文预测一个单词,毕竟从直观的角度来讲,多个上下文预测中心词汇绝对要比一个上下文预测中心词汇要靠谱一些。
首先对于任意的单词v,其上下文的单词集合记为 C ,这里上下文是距离中心单词v一定距离的所有单词的集合,而模型基于上下文对v的概率预测我们记为
,为了求这个概率,我们可以这样做一个转换,对于每一个单词
,我们先求得其在隐藏层的向量
,然后计算所有上下文单词隐藏层向量的的平均值,
,对任意单词 v 的预测概率,我们有下面的结果
所以,如果我们有一系列的训练样本
,基于CBOW模型,我们可以得到下面的额释然函数
Skip gram 模型
Skip gram 模型和CBOW完全是相反的出发角度,Skip gram 模型是通过中心单词预测上下文,而Google提出的Word2Vec的论文中,也推荐使用这个方法来进行词向量的学习。同样我们也先理解一个中心单词预测一个上下文的情况,然后扩展到一个单词预测多个上下文的情况。
一个单词预测一个上下文
这是最简单的情况,在公式上面其实和CBOW模型一模一样,唯一的区别就是训练样本从以前的(上下文单词,中心词汇)变成了(中心词汇,上下文单词)。同样我们沿用之前的一些符号,而且也是一样的有简单的三层神经网络。假设我们有训练样本
,那么基于上面的分析,我们可以构建基于这些样本的释然函数,有
取对数后有
一个单词预测多个上下文的情况
同样沿用之前的一些符号,记中心单词为 v ,上下文单集合为 C , 这次我们要预测的是上下文的概率
,为了转换成一个单词预测一个上下文的情况,我们可以做独立的假设,也就是有了下面的额公式
上面第一个等式就是上下文的预测条件概率独立的假设。同样基于一些列的样本,
,我们可以写出其释然函数
一些思考
前面我们也提到了,上面两种方法学习出来的编码有一些很好的特征,其中一个特征就是词性和语意相同的词,他们的词向量在词向量空间中的距离比较近。这个通过Skip Gram模型来看,很好理解,比如有两个词,
,他们的上下文都为C,而模型的第一步都是查找其隐藏层的编码
,后面计算
的过程完全一样,那么理论上来讲,在最优的情况下
会最终一样。如果他们的上下文不完全一样,分别为
, 而两者之间有大部分词汇相似,那么魔性最优的情况一定是
的值比较接近,那样
和
才会在才在大多数情况下一致。
此外论文中推荐的额是使用Skip Gram模型,个人的理解估计是Skip Gram模型比较直接,而且实现起来架构几乎不变,只需要把目标函数变为乘积的形式就行了(独立的假设)。而CBOW在多个上下文预测一个中心词的时候需要先对上下文的所有编码进行均值的计算,这一点没有Skip Gram模型那么直接。其次可能是Skip Gram模型的结果在一些数据集上表现更好,解释性更强的缘故。
词向量编码是近几年很流行的方法,而现在任意的NLP的问题都会将文本进行词向量编码后再进行后续的建模和计算,往往效果都远好于直接用one hot编码。而受词向量编码思想的影响,网络编码也在知识图谱的表示和推断方面衍生出了一些列的思想和方法。
无论如何,希望能对正在入门NLP和学习word2vec的你有些帮助。
reference
Distributed Representations of Words and Phrases and their Compositionality
word2vec Parameter Learning Explained
Word2Vec Tutorial - The Skip-Gram Model · Chris McCormick