在之前的几次笔记中,我们已经学习过几种语言模型了,今天要看的Word Embedding在传统的神经网络语言模型中也提及过,今天我们再系统地看一下Word Embedding中一个重要方法Word2vec,以及Word2vec包含的两个模型的基本原理及训练过程。
在NLP中,文本的表征是一项必不可少的工作,因为文本是一种非结构化的数据信息,是不可以直接被计算的。文本表征就是用一堆结构化的数据(比如数组、向量)来表征某个词语或者某段文本,这样原本非结构化的信息就可以被转化为结构化的信息,计算机也就能计算处理了。文本表征的方法有很多,下面简单回顾一下常用的几种,以便我们理解Word-Embedding的作用。
这个我们之前在语言模型(二)—— 神经网络语言模型(NNLM)中已经介绍过了,这里再简单介绍一下。
假设我们有一个词表:
[苹果,茄子,香蕉,蘑菇,菠菜]
那苹果
和香蕉
的one-hot编码就可以表示为:
苹果:[1,0,0,0,0]
香蕉:[0,0,1,0,0]
可以看得出来,这是一种离散的表示方法,就是在词表中找位置,即该词语在词表中的位置映射到特征向量中的位置的值为1,其他位置都为0。one-hot编码有两大主要缺点:
词袋模型,也称为计数向量表示。基本过程就是通过语料构建词袋,再将语料通过词计数的方式表达出来。举个例子:
句子A:Jane wants to go to Shenzhen
句子B:Bob wants to go to Shanghai
构建词表:[Jane, wants, to, go, Shenzhen, Bob, Shanghai]
句子A表示:[1,1,2,1,1,0,0]
句子B表示:[0,1,2,1,0,1,1]
词袋模型的不足在于:
TF-IDF与N-gram也算是文本表征的方式,之前的笔记TF-IDF的原理及代码实现和语言模型(一)—— 统计语言模型n-gram语言模型已经有过详细说明,这里不再复述。
词嵌入模型基于的基本假设是出现在相似的上下文中的词含义相似,以此为依据将词从高维稀疏的独热向量映射到低维稠密的连续向量,从而实现对词的语义建模。比如,在一个大的语料库中,词语“博客”
的One-hot编码是[0,0,0,0,0,0,0,1,0,……,0,0,0,0,0,0,0]
,维度是词表的大小(假设为20000),用一个五维的词向量来表达可能是[0.286,0.791,-0.177,0.109,0.271]
。这样做不仅可以降维,还可以表达词与词之间的相似程度,因为语义相似的词在词嵌入向量空间里的距离更近。简单的可视化理解如下图:
那么怎么得到Word-Embedding的词向量呢?在语言模型(二)—— 神经网络语言模型(NNLM)中我们已经有所了解,那就是通过模型训练得出来的,下面我们一起来看Word2vec是怎么得到我们想要的词向量的。
Word2vec的思想是用一个词的上下文来表征该词的意思,即得到词的向量化表示。这个词向量是训练神经网络的副产物。Word2vec包含两种模型:CBOW模型和Skip-gram模型,CBOW模型根据周围词来预测中心词,Skip-gram模型则是根据中心词来预测周围词。基本结构对比如下:
下面我们分别看一下这两个模型的工作原理。
Skip-gram想要做的事情是根据中心词预测周围词,可用下图来表示:
即我们会给定一个滑动的窗口,求窗口内中心词的周围词,例如上图中窗口大小就是2,就中心词往前往后各数两个词作为周围词。这是宏观上的一个过程,那么整个过程中,我们的目标又是什么呢?就是要对句子中的每一个词都给一个窗口,并求窗口内中心词出现时每一个周围词出现的概率。似然函数就是这些概率的联合概率,目标函数就是对似然函数取对数的负数平均。似然函数和目标函数可以表示为:
那么我们整个问题的落脚点就是如何计算log后面的那个概率值了。那这个概率值又是如何计算的呢?答案是利用中心词和周围词这两个词的词向量做点积,求他们夹角的余弦值,再用这个值做softmax归一化为概率值,这就得到我们想要的概率值了:
uo代表要算的周围词,vc代表中心词,uw是指词表里的任意词,也就是词表中所有的词。
回到我们的目标函数上来,我们知道了需要对每一个中心词所在的滑窗内的周围词进行训练和预测,例如我们有这么一句话:我喜欢吃香蕉
。当前时刻的中心词假设是喜欢
,window_size是2,即我
、吃
、香蕉
都是周围词,我们要做的就是训练模型让模型能预测出这几个词出来,如下图所示:
下面我们取其中由‘喜欢’
预测‘我’
这一步来说明网络是如何训练的,词向量又是怎么得到的。
这是一个简单的神经网络,输入是中心词‘喜欢’
的one-hot编码x,x是一个维度为V(词表大小)的向量,输入x后乘以一个词矩阵W(这是我们模型要训练的参数,刚开始一般随机初始化,维度V x N),经过简单的线性变换后得到隐藏层向量h(维度为N,N是超参数,就是词向量的维度)。隐藏层到输出层的参数是矩阵W‘(维度N x V),最后输出前再通过softmax将各个得分值归一化为一个概率向量。假设我们想要由‘喜欢’预测‘我’
,而'我’
这个词在词表中的索引是88,那我们训练的目标就是要输出向量y中索引是88的概率值最大,如果不是,我们就得不断地反向传播、更新参数再一轮轮地进行训练,最后使得我们要的那个地方的值最大,这就是我们的训练过程。可以看出来,这其实就是一个简单的神经网络的训练,那我们的词向量怎么得来呢?其实One-hot编码乘以矩阵W就是我们要求的中心词的词向量,W则是词表中所有词的词向量拼接起来的词表征矩阵,我们更新训练参数W的过程就是在不断的更新词向量。因为One-hot编码乘以矩阵W,本质上就是取了W的某一行,而这一行,就是我们想要的词向量了。如下图说明:
这里有一点需要注意,在预测不同的周围词的时候,W是共享的。
CBOW,Continuous Bag of Words,也有人翻译成连续词袋模型。它是一个由周围词预测中心词的模型,模型结构如下图所示:
模型的训练过程与Skip-gram类似,只不过输入输出正好相反,目标函数也有所不同。CBOW输入是上下文词的one-hot编码,经过参数为W的线性单元后再加权求平均得到隐藏层的中间向量,(注意:由于周围词有很多,每一个周围词乘以W最终都会得到一个h(k),最终的隐藏层向量便是这些h(k)加权求平均之后的结果,这是和skip-gram不一样的一个点,也正是因为这个点,CBOW得到的词向量会更容易受周围词的影响),隐藏层到输出层输出后再求loss、进行反省传播、梯度更新、参数更新。训练过程就基本与Skip-gram一样了,这里便不再详细说明了。(有好奇心的话可以点参考文章中的任意一篇,基本都会有说明。)
在上面的学习中我们可以发现,利用softmax求概率值时,每一次的训练我们都需要将词表里的每一个词都计算一遍,这样遍历整个词表的操作会在大语料库计算时变得异常困难。为了降低计算复杂度,两种优化方法被提了出来,那就是层次softmax和负采样。
层次softmax(Hierarchical Softmax)是一种对输出层进行优化的策略,输出层从原始模型的利用softmax计算概率值改为了利用Huffman树计算概率值。我们要将语料库中的词以及词出现的频率构造成一棵哈夫曼树,默认左边(编码为0)是负类,右边(编码为1)是正类,哈夫曼树的叶子节点就是语料库中的所有的词 ,词频越高的词,距离根节点就越近。从根节点出发,到达指定叶子节点的路径是唯一的。softmax概率计算只需要沿着树形结构进行就可以。如下图所示,可以沿着哈夫曼树从根节点一直走到叶子节点的词w2:
从根节点走到w2叶子节点的路径长度L=4,到每一个节点往左走还是往右走就是一次二分类的过程,用的是sigmoid函数进行的二分类,在上述过程中一共进行了3次这样的二分类过程,走到左边就是负类,走到右边就是正类,整个过程用哈夫曼编码表示就是001,由于二分类的时候选择的是Sigmoid函数。那么,一个结点被分为正类的概率就是:
被分为负类的概率就是:
所以走到w2的概率便是霍夫曼编码001对应的三个概率值的乘积。以CBOW为例,更抽象的说明是,对于Word2Vec中基于层次Softmax的CBOW模型,我们需要最终优化的目标函数是 :
其中Context(w)就是上下文词,p(w|Context(w))就是各个节点二分类走向时的概率值连乘:
其中:
或者写成一个整体的公式:
则目标函数:
符号说明:
根据得到的目标函数及数据标签,再进行反向传播梯度更新,我们就能慢慢训练出我们想要的模型,顺便得到我们想要得到的参数。
在整个层次softmax过程中,我们不再采用原本输出层计算一次softmax的方式,而是通过哈夫曼树上的某一特定路径计算路径上所有概率值的乘积,这样我们就只需要计算各个节点上的二分类概率就好了,计算的复杂度从O(V)降到了O(log(V)),加速了模型训练的速度。
负采样(Negative Sampling),简单来说,就是减少负样本的采样以减少计算量。以CBOW中周围词预测中心词为例,最后要预测的那个中心词就是正样本,词表中其他所有词都是负样本,负采样要做的事就是减少对负样本的采样,这样其实也就是最大化了正样本的概率,同时最小化了负样本的概率。那从样本量很大的负样本群中挑选出一些负样本出来,就需要一个规则,这个规则的基本思想就是带权采样:高频词被采样概率大,低频词被采样的概率小。
具体的负采样做法就直接从什么是Word2Vec中截图说明了:
首先看一下优点和不足:
优点:
不足:
其他总结:
加油,跑起来,便有了风。
参考文章:
NLP中的文本表示方法
通俗理解word2vec
全面理解word2vec
word2vec是如何得到词向量的?
word2vec 中的数学原理详解
什么是Word2Vec
一篇浅显易懂的word2vec原理讲解
深入浅出Word2Vec原理解析
Word Embedding&word2vec