之前写过一篇博文介绍如何使用word2vec,最近老板让我讲一讲word2vec,显然光讲word2vec的使用是不够的,更重要的是介绍原理。这篇文章就写写自己对于word2vec的一些理解吧。
Word2vec是google在2013年开源的一款将词表征为实数值向量的高效工具,一般被认为是一个深度学习模型。Word2vec的赞誉极高,被称为2013年最重要的自然语言处理工具,相信搞NLP的没有不知道word2vec的。在我看来,Word2vec最重要的贡献是提供了一个基础,也就是把词转换为实数值向量,在这个基础上可以玩很多花样。当然,可以站在一个更高的角度来看,这里的词其实并不一定真的就是单词,完全可以是具有一定意义的单元块,比如国外音乐网站就用word2vec来训练用户的听歌记录,这里的单元块就是歌曲编号,如果用户对音乐类型的喜好是一致的,那么训练后就能找到与某个歌曲相似的歌曲,这样就能给用户进行推荐了,相信类似这样的例子还有很多。
下面是word2vec最基本的查找相近词效果:
从上面两幅图可以看出word2vec的效果还是不错。
Word2vec的原理主要涉及到统计语言模型(包括N-gram模型和神经网络语言模型),continuousbag-of-words模型以及continuous skip-gram模型。下面分别进行介绍:
统计语言模型就是用一个机率分布来表示一段语句:
一般的语言模型可以用各个词语的条件概率表示:
每个词的出现概率与其上下文有关(确切的说是在前面出现的词)。
N-gram的意思就是每个词出现只看其前面的n个词,可以对每个词出现的概率进行近似
比如当n=2的时候
其实n=2时模型一般被称为Bigram,n=3是则被称为Trigram,这两者算是最常用的模型。
N-gram的效果还是不错的,否则不会这么多人用,但是其存在一些问题:
-无法建模更远的关系。当n取值较大时计算量会大大增加,故一般只取2,3
-无法建模词之间的相似度。比如对” Thecat is walking in the bedroom.” ”A dog was running in a room.” 这两句话,无法识别出其实dog和cat是类似的,bedroom和room也是类似的,walking和running也是类似的,如果能够识别出这些相似特征,那么2*2*2就可以组合出8句话了,这将大大丰富语料,可惜N-gram做不到。
-未出现的n元组概率为0。对于没有出现过的,肯定就求不出来概率了,不过可以用平滑法(出现次数都增加1,1为基准值)或回退法(用n-1元概率模拟)来处理这种情况。
为了避免N-gram模型中的那些问题,可以考虑用神经网络来构建语言模型。该模型用特征向量来表征每个词各个方面的特征,把词转换为向量后一个词就对应为特征空间中的一个点。同时,每个词的特征维度少于词表的总数,这算是NNLM的一大优势。
NNLM的基础是一个联合概率
其中g(.)就代表一个神经网络。
神经网络的目的是学习得到一个模型
该模型可以进一步分解
-字典集合V中的词i到其向量C(i)的映射函数C,C是一个|V|*m的矩阵
-用C表示词之间的概率函数
神经网络结构如下:
训练的目的是最大化似然函数
输出时采用了softmax函数
接下来用梯度下降的方法求解theta即可
以上就是神经网络语言模型的基本思想。
Continuous Bag-of-Words(CBOW)模型与NNLM类似,不同点在于CBOW去除了最耗时的非线性隐层,让所有词共享隐层,所有词都被映射到同一个位置。
结构如下
从图中能够看到CBOW是通过上下文来预测中间的词,如果窗口大小为k,则模型预测
同时CBOW采用了层次softmax算法,该算法结合了Huffman编码,每个词 w 都可以从树的根结点root沿着唯一一条路径被访问到,其路径也就形成了其编码code。假设 n(w, j)为这条路径上的第 j 个结点,且 L(w)为这条路径的长度, j 从 1 开始编码,即 n(w, 1)=root,n(w, L(w)) = w。对于第 j 个结点,层次 Softmax 定义的Label 为 1 - code[j]。
取一个适当大小的窗口当做语境,输入层读入窗口内的词,将它们的向量(K维,初始随机)加和在一起,形成隐藏层K个节点。输出层是一个巨大的二叉树,叶节点代表语料里所有的词(语料含有V个独立的词,则二叉树有|V|个叶节点)。而这整颗二叉树构建的算法就是Huffman树。这样,对于叶节点的每一个词,就会有一个全局唯一的编码,形如"010011",不妨记左子树为1,右子树为0。接下来,隐层的每一个节点都会跟二叉树的内节点有连边,于是对于二叉树的每一个内节点都会有K条连边,每条边上也会有权值。结构如下
在给定上下文时,对于一个要预测的词(这应该算是一个正样本,该词是预先知道的),这时就让预测词的二进制编码概率最大即可(采用logistic函数计算概率),例如如果一个词是“010001”,我们求解第一位为0的概率,第二位为1的概率等等。而一个词在当前网络中的概率就是从根结点到该词路径上的概率的乘积。于是就能够得到样本差值,接下来用梯度下降的方法求解参数即可。很显然,神经网络就是用正负样本不断训练,求解输出值与真实值误差,然后用梯度下降的方法求解各边权重参数值的。这里采用二叉树的方式是为了降低时间复杂度
除了层次softmax之外,CBOW还有另一种方法negative sampling,也就是随机生成负例来训练神经网络,思想差不多,这里省略。
Skip-gram模型与CBOW正好相反,是通过中间词来预测前后词,一般可以认为位置距离接近的词之间的联系要比位置距离较远的词的联系紧密。
其预测概率
目标为最大化
结构为
值得一提的是,skip-gram中的skip的是指在一个窗口内词两两之间都会计算概率,无论它们之间是否间隔词,这样“白色汽车”和“白色的汽车”会被识别为相同的短语。在skip-gram中也用到层次softmax算法和negative sampling,和CBOW模型中的类似,这里省略。
Word2vec中的参数有不少,我修改了一部分代码,让其在聚类时也能够输出词向量,得到的参数列表如下
其中重要的几个参数如下
–size:向量维数(一般200足够)
–window:上下文窗口大小(介于5-10之间)
–sample:高频词亚采样的阈值
–hs:是否采用层次softmax
–negative:负例数目(用于negativesampling)
–min-count:被截断的低频词阈值
–alpha:开始的 learning rate
–cbow:使用CBOW算法(0为不使用)
前面已经提到使用Word2vec得到的词向量是一个基础,在上面可以玩很多花样,下面介绍自己做过的几个。
这里是查找同义词,也就是要比词聚类中同一类中的词更接近。比如下面这几组词:
l 中国科学院 中科院
l 院所 科研单位 科研机构
l 院士 中科院院士
l 科研项目 科研工作 科研
l 两会 全国两会
l 三公 三公经费
l 中央经济工作会议 经济工作会议
l 高考加分政策 高考加分
l 公车改革 车改
l ……
可以看到大部分是简称,不过也算是同义词了。具体方法是对词先进行聚类(用word2vec自带的即可),然后进行层次聚类(更细粒度的聚类),最后就能找到意思最为接近的词对了,同义词基本都在其中。
对文本进行聚类时可以考虑使用词向量的特征,只需要考虑如何用词来表征文本即可,最容易想到的就是用关键词来代替文本,依据关键词聚类的结果就能够得到文本的聚类结果。关键词提取用TF-IDF,然后用word2vec训练得到关键词向量,再用k-means聚类,最后文本就能够以关键词的类别进行分类了。下面就是同一个类别中的文本
对文章进行指定类别的分类也可以考虑使用词向量,首先需要有一批标记好的数据
这些词是人工标记出来的,其中包含了该词属于各个类别的概率。在这个基础上,结合词向量的特征,可以求出全体词属于各个类别的概率。具体方法是对每个词求出其在样本词表中最接近的K个词(比如十个),统计这K个词属于各个类别的概率,然后就能够得到这个词的类别信息了。下图就是以微信为例的结果
接下来,文本就可以按照其关键词的类别信息进行类别的投递了。具体参看这里:http://blog.csdn.net/zhaoxinfan/article/details/17170049
以上就是我对word2vec的一些思考,希望老板会满意吧。本文中参考了其他一些人的资料,例如有道的那篇word2vec文章,word2vec傻瓜剖析等等,很感谢他们,这里不再一一列出了。这应该算是我关于word2vec写的最后一篇文章,也可能是与NLP相关的最后一篇文章了。
最后再次感谢晓阳童鞋去年向我推荐word2vec这个工具,如今他已经是百度自然语言处理部门的研发工程师了,祝他在NLP领域取得更大的成绩。