Word2Vec学习笔记之基础篇
概述
自然语言处理属于深度学习中的一个分支,但是相对其他分支发展一直比较缓慢,在2013年末,Google发布的word2vec工具引起了一帮人的热捧,都认为这是深度学习在自然语言领域一项了不起的应用,word2vec本身并不是特别的难,只是简单三层神经网络,但是在某种程度上说他的应用是十分有前景的。
Word2Vec(word to vector)是一种把词表征转化成实数值向量来区分其之间的差别的一种深度学习算法,对于训练好的模型,我们可以刻画出任意两个词语之间的相似度,用向量距离的形式。
学习材料:
背景知识
词向量
在自然语言相关的任务中,要将自然语言交给计算机处理,计算机可不认识人类的语言,所以要先将自然语言转换成计算机能懂的东西,又要在一定程度上区分出不同词语的区别,人们就想到了用向量来表示不同的词语
one-hot representation 向量表示法
人们首先想到了一种比较简单的向量表示方法是one-hot representation, 就是用一个很长的向量来表示一个词,向量的长度为词典的大小或者说不同词语的数量,比如说
现在有4个词语 苹果
, 香蕉
, 水果
, 卡车
, 用one-hot representation表示法可以这样表示:
苹果: [1,0,0,0]
香蕉: [0,1,0,0]
水果:[0,0,1,0]
卡车:[0,0,0,1]
这种表示方式非常的简洁,也就是给每个词分配一个唯一的ID,如果要编程的话,用Hash表给每个词分配一个编号就可以了,这种方式已经能在NLP的绝大多数问题上完成需要的任务了。
但是这种词表示方式有两个缺点:
容易受维数灾难的困扰,也就是当向量的长度过长,会导致计算变得困难(具体本人也不熟悉)
不能很好的刻画词与词之间的相似性(词汇鸿沟): 任意两个词之间都是孤立的,光从向量上看不出两个词之间有关系,就像上面的例子,我们并不能看出苹果和香蕉,以及水果和卡车之间有啥关系
所以在这种表示方法的基础上,人们有想到了另一种表示法,也是Word2Vec中运用的向量表示法Distributed Representation
Distributed Representation 向量表示法
这种向量表示方法也很简单,就是直接用一个普通的向量表示一个词,这种向量一般长这样[0.795, -0.568, 0.156, 0.455, ...]
, 这种向量表示法的向量维度不是由词典大小决定的,一般由我们自己选定,一般50维和100维比较常见,这样的话维度不会太高,所以我们学习的Word2Vec本质上就是将one-hot representation向量表示转化成distributed representation 向量表示法.
经过训练的词语被转化成这种形式后,一般其向量具有空间上的意义,也就是将这些向量放在一起形成一个词向量空间,而每个向量都其中的一个点,这个空间是多维的,所以想象起来可能比较困难,但是我们其实不关心他们所在的具体位置,只要知道如何计算其中两个向量的"距离"就行了,因为所谓两个词的"距离",表示的就是这两个词之间的语法,语义之间的相似性。
从这里就能看出来Word2Vec的最终目的就是通过将词转换成向量,在通过向量的"距离"来观察两个词之间的相似度
那么接下来我们看看要如何去做,这里暂时不会涉及到具体的算法知识,只是大概的过程描述
相似词假说
分布式假说
一个词由周围词来推断,相似的词会出现在相似的语境中,
分布模型
相似词在相似的上下文中, 例如今天天空中有很多星星,今天天空中有太阳,这两个句子中的太阳和星星就具有相似的上下文,具有纵向相似性.
从这两个似乎很有道理的假说中就能推出我们要在意的两个语言模型-CBOW和Skip-Gram模型,他们都是Word2Vec工具中用到的模型
Word2Vec 是代码项目的名字,只是计算 word embedding 的一个工具,是 CBOW 和 Skip-Gram 这两个模型开源出来的工具。连续实值词表达也叫词嵌入 word embedding。
过程概述
再用一个具体的例子来说明:
如果在一个语料库中,吴彦祖帅到没朋友这句话经常出现,那么最终的训练结果中,[吴彦祖]这个词语会和[帅],[没朋友],这两个词的相似度非常高
如果在同一个语料库中,手环帅到没朋友这句话也经常出现,那么在最终的训练结果中[手环]这个词语会和[吴彦祖]的相似度也非常高.
我们可以推断,手环和吴彦祖一样帅
CBOW模型
CBOW模型是利用词的上下文来预测当前的单词,比如输入[帅], [没朋友]会输出一个[手环] (或者吴彦祖)
Skip-Gram模型
Skip-Gram模型是利用词来预测上下文,比如输入[吴彦祖],会输出[手环],[帅],[没朋友]
在这里不做模型的具体解析,只是额外介绍一下语言模型的大概概念,以更好的理解自然语言处理的基础问题
统计语言模型
基本概念
语言模型其实就是看一句话是不是正常人说出来的话.
比如说我们要计算一句话[吴彦祖帅到没朋友]是自然语言的概率,我们先要分词(将一个句子分成一个个词语,英文靠空格分词,中文就比较麻烦了),这句话就变成了[吴彦祖,帅,没朋友] (这里忽略掉到字比较好讲解)
一句话是自然语言的概率从数学上我们给出的公式是 ,
代表第i个词语
用上面的例子来说
<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="8.851ex" height="2.66ex" viewBox="-38.5 -832 3811 1145.2" role="img" focusable="false" style="vertical-align: -0.728ex; margin-left: -0.089ex;" class="in-text-selection"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><g transform="translate(893,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(51.874) matrix(1 0 0 -1 0 0)">吴</text></g><g transform="translate(1722,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(51.874) matrix(1 0 0 -1 0 0)">彦</text></g><g transform="translate(2552,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(51.874) matrix(1 0 0 -1 0 0)">祖</text></g></g></svg> 表示"吴彦祖"这个词在语料库中出现的概率;
<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="11.426ex" height="2.66ex" viewBox="-38.5 -832 4919.4 1145.2" role="img" focusable="false" style="vertical-align: -0.728ex; margin-left: -0.089ex;" class="in-text-selection"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><g transform="translate(893,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(51.874) matrix(1 0 0 -1 0 0)">帅</text></g><g transform="translate(2001,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(51.874) matrix(1 0 0 -1 0 0)">吴</text></g><g transform="translate(2831,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(51.874) matrix(1 0 0 -1 0 0)">彦</text></g><g transform="translate(3661,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(51.874) matrix(1 0 0 -1 0 0)">祖</text></g></g></svg> 表示"帅"这个词在"吴彦祖"后面出现的概率
<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="18.243ex" height="2.66ex" viewBox="-38.5 -832 7854.6 1145.2" role="img" focusable="false" style="vertical-align: -0.728ex; margin-left: -0.089ex;" class="in-text-selection"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><g transform="translate(893,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(51.874) matrix(1 0 0 -1 0 0)">没</text></g><g transform="translate(1722,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(51.874) matrix(1 0 0 -1 0 0)">朋</text></g><g transform="translate(2552,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(51.874) matrix(1 0 0 -1 0 0)">友</text></g><g transform="translate(3661,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(51.874) matrix(1 0 0 -1 0 0)">吴</text></g><g transform="translate(4491,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(51.874) matrix(1 0 0 -1 0 0)">彦</text></g><g transform="translate(5321,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(51.874) matrix(1 0 0 -1 0 0)">祖</text></g><g transform="translate(6596,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(51.874) matrix(1 0 0 -1 0 0)">帅</text></g></g></svg> 表示"没朋友"出现在"吴彦祖帅"后面的概率
最后把这几个概率乘起来就是"吴彦祖帅到没朋友"这句话出现的概率了.
这种方法简单直接,但是太过暴力了,计算一句话要计算这么多概率,三个词的句子要扫描3次语料库,计算三个子句出现的概率,如果语料库巨大且句子的词语数量较多的话,运算时间会出奇的慢,根本没有使用价值.
所以为了偷懒,我们可以用更简单的计算方式 -N-gram模型
N-gram模型
N-gram模型的核心就在这个N上, N-gram只管这个词前面的n-1个词,加上自己总共n个词,计算概率时指考虑这n个词来计算,即
其中,如果是空的话,就是它自己p(w),另外如“没朋友”的Context就是“吴彦祖”、“帅”,其余的对号入座。
如果n取2则"吴彦祖帅到没朋友"就只考虑"帅"和"没朋友"之间的出现概率了
这里如果n取得比较小的话,就比较省事了,当然也要看到n取得太小,会特别影响效果的,有可能计算出来的那个概率很不准。怎么平衡这个效果和计算就是大牛们的事情了,据大牛们的核算,n取2效果都还凑合,n取3就相当不错了,n取4就顶不住了。看下面的一些数据,假设词表中词的个数 |V| = 20,000 词,那么有下面的一些数据。
照图中的数据看去,取n=3是目前计算能力的上限了。在实践中用的最多的就是bigram(n=2)和trigram(n=3)了,而且效果也基本够了。
N-pos模型
N-pos模型是先将不同的词分为不同的词性(Part of Speech),之后再用上述方法计算,具体就不过多赘述了.
扩展
在应用中有更多的方法被开发出来,比如用函数直接你和计算 ,就是说不是根据庞大的语料库统计出来,而是直接把Context和wi代入函数计算出来,这样就不用统计那个庞大的语料库了,这就是更深入的内容了.
总结
本文只是从概念上说明了Word2Vec这个工具的涉及的基础内容,NLP中常用的词向量的表示方法,还有Word2Vec中的词向量表示法,介绍了Word2Vec这个工具的思想本质-两个语言学假说,然后稍微介绍了Word2Vec中常用的两种模型的基础思想,和目的,最后简单介绍了统计语言模型中的目的,这是自然语言中的基础课题,对我们理解自然语言处理有很大的帮助
博主也是NLP的新手,并不能保证所述文字的正确性,只是从其他博客中提取要点加以自己的理解,请理性看待.
接下来是关于Word2Vec的基础应用篇,这个应该会更加有趣.