NLP的词向量 之 Word2vec
1. 词嵌入(Word Embedding)
自然语言是一套用来表达含义的复杂系统。在这套系统中,词是表义的基本单元。顾名思义,词向量是⽤来表示词的向量,也可被认为是词的特征向量或表征。把词映射为实数域向量的技术也叫词嵌⼊(word embedding)。近年来,词嵌⼊已逐渐成为⾃然语⾔处理的基础知识。
词向量指的是一个词的向量表示。如果你希望计算机能够进行一些复杂点的文本语义学习,你必须得将文本数据编码成计算机能够处理的数值向量吧,所以词向量是一个自然语言处理任务中非常重要的一环。
很久很久之前,一个词用onehot进行编码,如下图所示,这种方式简单粗暴,将一个词用一个只有一个位置为1,其他地方为0的向量表示。1的位置就代表了是什么词。

这种表示有如下缺点:
- 占用空间大
- 词与词之间的向量是正交关系,没有任何语义关联
为了克服onehot表示的两个缺点,Distributional representations的词向量应运而生。Distributional representations的词向量指的是将单词从原先所属的空间(一般是one-hot编码)映射到新的低维空间中去,同时,低维空间的词向量还能表达出一些语义,比如,词的相似性(similarity)或者一对词与一对之间的类比关系(analogy)。
词的相似性(similarity): 老婆 和 妻子
类比关系(analogy): 国王 - 男人 = 王后 - 女人
在NLP(自然语言处理)领域,文本表示是第一步,也是很重要的一步,因为普通的文本语言机器是看不懂的,必须通过转化来表征对应文本。通俗来说就是把人类的语言符号转化为机器能够进行计算的数字,或者说——嵌入到一个数学空间里。这种嵌入方式,就叫词嵌入(word embedding),而 Word2vec,就是词嵌入( word embedding) 的一种。早期是基于规则的方法进行转化,而现代的方法是基于统计机器学习的方法。
数据决定了机器学习的上限,而算法只是尽可能逼近这个上限,在本文中数据指的就是文本表示。文本表示分为离散表示和分布式表示。
2. 什么是 Word2vec
那我们如何得到上述具有语义Distributional representations的词向量呢,谷歌2013年提出的Word2Vec是目前最常用的词嵌入模型之一。其主要思想是:一个词的上下文可以很好的表达出词的语义,它是一种通过无监督的学习文本来用产生词向量的方式。Word2Vec实际是一种浅层的神经网络模型,它有两种网络结构,分别是CBOW(Continues Bag of Words)连续词袋和Skip-gram。Word2Vec和上面的NNLM很类似,但比NNLM简单。
大部分的有监督机器学习模型,都可以归结为:f(x)->y
在 NLP 中,把 x 看做一个句子里的一个词语,y 是这个词语的上下文词语,那么这里的 f,便是 NLP 中经常出现的『语言模型』(language model)。这个模型的目的,就是判断 (x,y) 这个样本是否符合自然语言的法则,更通俗点说就是:词语 x 和词语 y 放在一起,是不是人话。
Word2vec 正是来源于这个思想。但它的最终目的,不是要把 f 训练得多么完美,而是只关心模型训练完后的副产物——模型参数(这里特指神经网络的权重),并将这些参数作为输入 x 的某种向量化的表示,这个向量便叫做——词向量。
skip-gram,cbow的模型架构都是一层单层的神经网络,需要注意的部分是:神经网络的参数就是我们最后得到的词向量,神经网络训练过程就是学习词向量(网络参数)的过程。
我们来看个例子,如何用 Word2vec 寻找相似词:
- 对于一句话:『她们 夸 吴彦祖 帅 到 没朋友』,如果输入 x 是『吴彦祖』,那么 y 可以是『她们』、『夸』、『帅』、『没朋友』这些词
- 现有另一句话:『她们 夸 我 帅 到 没朋友』,如果输入 x 是『我』,那么不难发现,这里的上下文 y 跟上面一句话一样
- 从而 f(吴彦祖) = f(我) = y,所以大数据告诉我们:我 = 吴彦祖(完美的结论)
2.1 Skip-gram 和 CBOW 模型
上面我们提到了语言模型
-
如果是用一个词语作为输入,来预测它周围的上下文,那这种方法叫做『Skip-gram 』
- 如果是用一个词语的上下文作为输入,来预测这个词语本身,这种方法被叫做 『CBOW 』
Skip-gram是通过当前词,来预测窗口中上下文词出现的概率模型,把当前词当做x,把窗口中其它词当做y。通过一个隐层接一个Softmax激活函数来预测其它词的概率。
CBOW获得中间词两边的的上下文,然后用周围的词去预测中间的词,把中间词当做y,把窗口中的其它词当做x输入,x输入是经过one-hot编码过的,然后通过一个隐层进行求和操作,最后通过激活函数softmax,可以计算出每个单词的生成概率,接下来的任务就是训练神经网络的权重,使得语料库中所有单词的整体生成概率最大化,而求得的权重矩阵就是文本表示词向量的结果。
2.2 Skip-gram 和 CBOW 的简单情形
我们先来看个最简单的例子。上面说到, y 是 x 的上下文,所以 y 只取上下文里一个词语的时候,语言模型就变成:
用当前词 x 预测它的下一个词 y。
但如上面所说,一般的数学模型只接受数值型输入,这里的 x 该怎么表示呢? 显然不能用 Word2vec,因为这是我们训练完模型的产物,现在我们想要的是 x 的一个原始输入形式。
答案是:one-hot encoder。
所谓 one-hot encoder,其思想跟特征工程里处理类别变量的 one-hot 一样。本质上是用一个只含一个 1、其他都是 0 的向量来唯一表示词语。
参考文章:特征提取之文本特征:one-hot和 TF-IDF方法https://blog.csdn.net/sinat_26811377/article/details/98770008
我举个例子,假设全世界所有的词语总共有 V 个,这 V 个词语有自己的先后顺序,假设『吴彦祖』这个词是第 1 个词,『我』这个单词是第 2 个词,那么『吴彦祖』就可以表示为一个 V 维全零向量、把第 1 个位置的 0 变成 1,而『我』同样表示为 V 维全零向量、把第 2 个位置的 0 变成 1。这样,每个词语都可以找到属于自己的唯一表示。
OK,那我们接下来就可以看看 Skip-gram 的网络结构了,x 就是上面提到的 one-hot encoder 形式的输入,y 是在这 V 个词上输出的概率,我们希望跟真实的 y 的 one-hot encoder 一样。

首先说明一点:隐层的激活函数其实是线性的,相当于没做任何处理(这也是 Word2vec 简化之前语言模型的独到之处)。我们要训练这个神经网络,用反向传播算法,本质上是链式求导,在此不展开说明了,
当模型训练完后,最后得到的其实是神经网络的权重,比如现在输入一个 x 的 one-hot encoder: [1,0,0,…,0],对应刚说的那个词语『吴彦祖』,则在输入层到隐含层的权重里,只有对应 1 这个位置的权重被激活,这些权重的个数,跟隐含层节点数是一致的,从而这些权重组成一个向量 vx 来表示 x。而因为每个词语的 one-hot encoder 里面 1 的位置是不同的,所以,这个向量 vx 就可以用来唯一表示 x。
注意:上面这段话说的就是 Word2vec 的精髓!!
此外,我们刚说了,输出 y 也是用 V 个节点表示的,对应 V 个词语,所以其实,我们把输出节点置成 [1,0,0,…,0],它也能表示『吴彦祖』这个单词,但是激活的是隐含层到输出层的权重,这些权重的个数,跟隐含层一样,也可以组成一个向量 vy,跟上面提到的 vx 维度一样,并且可以看做是词语『吴彦祖』的另一种词向量。而这两种词向量 vx 和 vy,正是 Mikolov 在论文里所提到的,『输入向量』和『输出向量』,一般我们用『输入向量』。
需要提到一点的是,这个词向量的维度(与隐含层节点数一致)一般情况下要远远小于词语总数 V 的大小,所以 Word2vec 本质上是一种降维操作——把词语从 one-hot encoder 形式的表示降维到 Word2vec 形式的表示。
2.3 Skip-gram 更一般的情形
上面讨论的是最简单情形,即 y 只有一个词。当 y 有多个词时,网络结构如下:

可以看成是 单个 x-> 单个 y 模型的并联,cost function 是单个 cost function 的累加(取 log 之后)。
如果你想深入探究这些模型是如何并联、 cost function 的形式怎样,可以仔细阅读参考资料 4。
2.4 CBOW 更一般的情形
跟 Skip-gram 相似,只不过Skip-gram 是预测一个词的上下文,而 CBOW 是用上下文预测这个词。
网络结构如下

跟 Skip-gram 的模型并联不同,这里是输入变成了多个单词,所以要对输入进行处理(一般是求和然后平均),输出的 cost function 不变。
3. Word2vec 的训练 trick
为什么要用训练技巧呢? 如我们刚提到的,Word2vec 本质上是一个语言模型,它的输出节点数是 V 个,对应了 V 个词语,本质上是一个多分类问题,但实际当中,词语的个数非常非常多,会给计算造成很大困难,所以需要用技巧来加速训练。
这里我总结了一下这两个 trick 的本质,有助于大家更好地理解,在此也不做过多展开,有兴趣的同学可以深入阅读参考资料。
- hierarchical softmax
- 本质是把 N 分类问题变成 log(N) 次二分类
1. 层次Softmax:因为如果单单只是接一个softmax激活函数,计算量还是很大的,有多少词就会有多少维的权重矩阵,所以这里就提出层次Softmax(Hierarchical Softmax),使用Huffman Tree来编码输出层的词典,相当于平铺到各个叶子节点上,瞬间把维度降低到了树的深度,可以看如下图所示。这课Tree把出现频率高的词放到靠近根节点的叶子节点处,每一次只要做二分类计算,计算路径上所有非叶子节点词向量的贡献即可。

- negative sampling
- 本质是预测总体类别的一个子集
2. 负例采样(Negative Sampling):这种优化方式做的事情是,在正确单词以外的负样本中进行采样,最终目的是为了减少负样本的数量,达到减少计算量效果。将词典中的每一个词对应一条线段,所有词组成了[0,1]间的剖分,如下图所示,然后每次随机生成一个[1, M-1]间的整数,看落在哪个词对应的剖分上就选择哪个词,最后会得到一个负样本集合。

4. 扩展
深入进去我们会发现,神经网络形式表示的模型(如 Word2vec),跟共现矩阵分解模型(如 GloVe),有理论上的相通性,这里推荐阅读参考资料 5. ——来斯惟博士在它的博士论文附录部分,证明了 Skip-gram 模型和 GloVe 的 cost fucntion 本质上是一样的。是不是一个很有意思的结论? 所以在实际应用当中,这两者的差别并不算很大,尤其在很多 high-level 的 NLP 任务(如句子表示、命名体识别、文档表示)当中,经常把词向量作为原始输入,而到了 high-level 层面,差别就更小了。
鉴于词语是 NLP 里最细粒度的表达,所以词向量的应用很广泛,既可以执行词语层面的任务,也可以作为很多模型的输入,执行 high-level 如句子、文档层面的任务,包括但不限于:
- 计算相似度
- 寻找相似词
- 信息检索
- 作为 SVM/LSTM 等模型的输入
- 中文分词
- 命名体识别
- 句子表示
- 情感分析
- 文档表示
- 文档主题判别
5. 实战
上面讲了这么多理论细节,其实在真正应用的时候,只需要调用 Gensim (一个 Python 第三方库)的接口就可以。但对理论的探究仍然有必要,你能更好地知道参数的意义、模型结果受哪些因素影响,以及举一反三地应用到其他问题当中,甚至更改源码以实现自己定制化的需求。
这里我们将使用 Gensim 和 NLTK 这两个库,来完成对生物领域的相似词挖掘,将涉及:
- 解读 Gensim 里 Word2vec 模型的参数含义
- 基于相应语料训练 Word2vec 模型,并评估结果
- 对模型结果调优
gensim 中Fast-text 模型架构和Word2Vec的模型架构差几乎一样,只不过在模型词的输入部分使用了词的n-gram的特征。
这里需要讲解一下n-gram特征的含义。举个例子,如果原词是一个很长的词:你吃了吗。
- jieba分词结果:["你","吃了","吗"]。
- unigram(1-gram)的特征:["你","吃了","吗"]
- bigram(2-gram) 的特征: ["你吃了","吃了吗"]
所以n-gram是将词中连续的n个词连起来,组成一个单独的词。
如果使用unigram和bigram的特征,词的特征就会变成:["你","吃了","吗","你吃了","吃了吗"]这么一长串。
使用n-gram的词向量,使得Fast-text模型可以很好的解决未登录词(OOV——out-of-vocabulary)问题。
==== 评论区答疑节选 ====
Q1. gensim 和 google 的 word2vec 里面并没有用到 onehot encoder,而是初始化的时候直接为每个词随机生成一个 N 维的向量,并且把这个 N 维向量作为模型参数学习;所以 word2vec 结构中不存在文章图中显示的将 V 维映射到 N 维的隐藏层。
A1. 其实,本质是一样的,加上 one-hot encoder 层,是为了方便理解,因为这里的 N 维随机向量,就可以理解为是 V 维 one-hot encoder 输入层到 N 维隐层的权重,或者说隐层的输出(因为隐层是线性的)。每个 one-hot encoder 里值是 1 的那个位置,对应的 V 个权重被激活,其实就是『从一个 V*N 的随机词向量矩阵里,抽取某一行』。学习 N 维向量的过程,也就是优化 one-hot encoder 层到隐含层权重的过程
Q2. hierarchical softmax 获取词向量的方式和原先的其实基本完全不一样,我初始化输入的也不是一个 one-hot,同时我是直接通过优化输入向量的形式来获取词向量?如果用了 hierarchical 结构我应该就没有输出向量了吧?
A2. 初始化输入依然可以理解为是 one-hot,同上面的回答;确实是只能优化输入向量,没有输出向量了。具体原因,我们可以梳理一下不用 hierarchical (即原始的 softmax) 的情形:
隐含层输出一个 N 维向量 x, 每个 x 被一个 N 维权重 w 连接到输出节点上,有 V 个这样的输出节点,就有 V 个权重 w,再套用 softmax 的公式,变成 V 分类问题。这里的类别就是词表里的 V 个词,所以一个词就对应了一个权重 w,从而可以用 w 作为该词的词向量,即文中的输出词向量。
PS. 这里的 softmax 其实多了一个『自由度』,因为 V 分类只需要 V-1 个权重即可
我们再看看 hierarchical softmax 的情形:
隐含层输出一个 N 维向量 x, 但这里要预测的目标输出词,不再是用 one-hot 形式表示,而是用 huffman tree 的编码,所以跟上面 V 个权重同时存在的原始 softmax 不一样, 这里 x 可以理解为先接一个输出节点,即只有一个权重 w1 ,输出节点输出 1/1+exp(-w*x),变成一个二分类的 LR,输出一个概率值 P1,然后根据目标词的 huffman tree 编码,将 x 再输出到下一个 LR,对应权重 w2,输出 P2,总共遇到的 LR 个数(或者说权重个数)跟 huffman tree 编码长度一致,大概有 log(V) 个,最后将这 log(V) 个 P 相乘,得到属于目标词的概率。但注意因为只有 log(V) 个权重 w 了,所以跟 V 个词并不是一一对应关系,就不能用 w 表征某个词,从而失去了词向量的意义
PS. 但我个人理解,这 log(V) 个权重的组合,可以表示某一个词。因为 huffman tree 寻找叶子节点的时候,可以理解成是一个不断『二分』的过程,不断二分到只剩一个词为止。而每一次二分,都有一个 LR 权重,这个权重可以表征该类词,所以这些权重拼接在一起,就表示了『二分』这个过程,以及最后分到的这个词的『输出词向量』。
我举个例子:
假设现在总共有 (A,B,C) 三个词,huffman tree 这么构建:
第一次二分: (A,B), (C)
假如我们用的 LR 是二分类 softmax 的情形(比常见 LR 多了一个自由度),这样 LR 就有俩权重,权重 w1_1 是属于 (A,B) 这一类的,w1_2 是属于 (C) 的, 而 C 已经到最后一个了,所以 C 可以表示为 w1_2
第二次二分: (A), (B)
假设权重分别对应 w2_1 和 w2_2,那么 A 就可以表示为 [w1_1, w2_1], B 可以表示为 [w1_1, w2_2]
这样, A,B,C 每个词都有了一个唯一表示的词向量(此时他们长度不一样,不过可以用 padding 的思路,即在最后补 0)
当然了,一般没人这么干。。。开个脑洞而已
Q3. 是否一定要用 Huffman tree?
A3. 未必,比如用完全二叉树也能达到 O(log(N)) 复杂度。但 Huffman tree 被证明是更高效、更节省内存的编码形式,所以相应的权重更新寻优也更快。 举个简单例子,高频词在 Huffman tree 中的节点深度比完全二叉树更浅,比如在 Huffman tree 中深度为 3,完全二叉树中深度为 5,则更新权重时,Huffmantree 只需更新 3 个 w,而完全二叉树要更新 5 个,当高频词频率很高时,算法效率高下立判。
推荐资料:
1. Mikolov 两篇原论文:
『Distributed Representations of Sentences and Documents』
贡献:在前人基础上提出更精简的语言模型(language model)框架并用于生成词向量,这个框架就是 Word2vec
『Efficient estimation of word representations in vector space』
贡献:专门讲训练 Word2vec 中的两个trick:hierarchical softmax 和 negative sampling
优点:Word2vec 开山之作,两篇论文均值得一读
缺点:只见树木,不见森林和树叶,读完不得要义。
这里『森林』指 word2vec 模型的理论基础——即 以神经网络形式表示的语言模型
『树叶』指具体的神经网络形式、理论推导、hierarchical softmax 的实现细节等等
2. 北漂浪子的博客:『深度学习word2vec 笔记之基础篇』
优点:非常系统,结合源码剖析,语言平实易懂
缺点:太啰嗦,有点抓不住精髓
3. Yoav Goldberg 的论文:『word2vec Explained- Deriving Mikolov et al.’s Negative-Sampling Word-Embedding Method』
优点:对 negative-sampling 的公式推导非常完备
缺点:不够全面,而且都是公式,没有图示,略显干枯
4. Xin Rong 的论文:『word2vec Parameter Learning Explained』:
!重点推荐!
理论完备由浅入深非常好懂,且直击要害,既有 high-level 的 intuition 的解释,也有细节的推导过程
一定要看这篇paper!一定要看这篇paper!一定要看这篇paper!
5. 来斯惟的博士论文『基于神经网络的词和文档语义向量表示方法研究』以及他的博客(网名:licstar)
可以作为更深入全面的扩展阅读,这里不仅仅有 word2vec,而是把词嵌入的所有主流方法通通梳理了一遍
6. 几位大牛在知乎的回答:『word2vec 相比之前的 Word Embedding 方法好在什么地方?』
刘知远、邱锡鹏、李韶华等知名学者从不同角度发表对 Word2vec 的看法,非常值得一看
7. Sebastian 的博客:『On word embeddings - Part 2: Approximating the Softmax』
详细讲解了 softmax 的近似方法,Word2vec 的 hierarchical softmax 只是其中一种
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
