自然语言处理:从ngram到BOW到Word2Vec

自然语言处理是一个历史悠久的方向,个人目前研究不深,所以本文以我个人的思路展开,具体内容大部分摘抄自其他大佬们的博客,其中主要摘抄自


NLP的基本问题

自然语言处理中的一个基本问题:如何计算一段文本序列在某种语言下出现的概率?之所为称其为一个基本问题,是因为它在很多NLP任务中都扮演着重要的角色。例如,在机器翻译的问题中,如果我们知道了目标语言中每句话的概率,就可以从候选集合中挑选出最合理的句子做为翻译结果返回。
统计语言模型(Statistical Language Model)给出了这一类问题的一个基本解决框架。对于一段文本序列

\[S=w_1, w_2, ... , w_T \]

它的概率可以表示为:

\[p(S)=P(w_1, w_2, ..., w_T)=\prod_{t=1}^Tp(w_t|w_{t-1}, w_{t-2}, ..., w_1) \]

即将序列的联合概率转化为一系列条件概率的乘积。问题变成了如何去预测这些给定previous words下的条件概率:

\[p(w_t|w_{t-1}, w_{t-2}, ..., w_1) \]

由于其巨大的参数空间,这样一个原始的模型在实际中并没有什么用。我们更多的是采用其简化版本——Ngram模型:

\[p(w_t|w_{t-1}, w_{t-2}, ..., w_1) \approx p(w_t|w_{t-1}, w_{t-2}, ..., w_{t-n+1}) \]

NGram

NGram,2Gram,3Gram

N-Gram是基于一个假设:第n个词出现与前n-1个词相关,而与其他任何词不相关。(这也是隐马尔可夫当中的假设。)整个句子出现的概率就等于各个词出现的概率乘积。各个词的概率可以通过语料中统计计算得到。假设句子T是有词序列w1,w2,w3...wn组成,用公式表示N-Gram语言模型如下:

\[p(S)=\prod_{t=1}^T p(w_t|w_{t-1}, w_{t-2}, ..., w_{t-n+1}) \]

常见的如bigram模型(N=2)和trigram模型(N=3)。事实上,由于模型复杂度和预测精度的限制,我们很少会考虑N>3的模型。
我们可以用最大似然法去求解Ngram模型的参数——等价于去统计每个Ngram的条件词频。
BiGram: \(p(S)=\prod_{t=1}^T p(w_t|w_{t-1})\)
TriGram: \(p(S)=\prod_{t=1}^T p(w_t|w_{t-1},w_{t-2})\)
因为我们是基于统计获得每个条件词频的,所以有可能出现0,此时需要一些类似拉普拉斯平滑的操作。

NGram距离

Ngram的应用方向之一就是模糊匹配,即判断句子s和句子t是否相似。
那么这就需要使用Ngram距离:
|GN(s)|+|GN(t)|−2×|GN(s)∩GN(t)|
此处,|GN(s)|是字符串 s的 N-Gram集合,N 值一般取2或者3。以 N = 2 为例对字符串Gorbachev和Gorbechyov进行分段,可得如下结果(我们用下画线标出了其中的公共子串)。

结合上面的公式,即可算得两个字符串之间的距离是8 + 9 − 2 × 4 = 9。显然,字符串之间的距离越小,它们就越接近。当两个字符串完全相等的时候,它们之间的距离就是0。

NGram应用

1.模糊匹配,就像上面说的,另外一个常见的模糊匹配的场景就是搜索引擎。我们在搜索“我是”的时候,搜索引擎就会自动给我们推荐:

2.作家或语料库风格文本的生成。比如类似莎士比亚的诗赋的生成。

词向量

NGram是将词作为一个个独立的个体来对待的,这种处理方式等价于one-hot编码和词袋(Bag Of Words)模型,我们有N个词,我们的词向量就有N维,且是独热的形态。
比如我们的词库来自"I love you"。那么这三个词的词向量就分别是[1,0,0],[0,1,0],[0,0,1]。
但是这样做无法考虑到词内部的关联,只能通过统计的概率来进行判断,而且实际场景中我们的词袋会非常的大(N非常大),于是还会面临维度灾难问题(The Curse of Dimensionality)。
于是出现了词嵌入(word embedding)。即将巨大且稀疏的one hot vector映射到一个维度更小的稠密向量中去。
其实现方法可以理解为,将原始的one hot vector x (1V)与embedding参数W (VD) 做矩阵乘法,由于x中只有一个元素为1,即可取出W中一行,得到稠密向量表示e (1*D),这个稠密向量叫做Distributed Representation。
也可以理解为,把参数矩阵看作一张表,知道了单词编号,去查表(lookup)。
这个概念在信息检索(Information Retrieval)领域叫做向量空间模型(Vector Space Model,以下简称VSM)。

神经网络语言模型(Neural Network Language Model,NNLM)

Language Model语言模型,我们可以通俗的理解为解决单词填空问题的一类模型。这个单词出现在句尾,则就是预测下一个单词,出现在句中,则是句子补全。
NNLM则是基于神经网络的语言模型,出现在2003年,Bengio等人的文章:A neural probabilistic language model。

其网络结构如图,采用NGram模型,输入为前N个单词的index,然后经过embedding lookup(embedding向量可训练),之后经过tanh激活的隐层,最后输出层维度和单词个数V相同,经过softmax输出index i对应的单词成为下一个单词的概率。
目标函数则使用交叉熵加参数正则化约束项。
NNLM相当于使用一个简单的前向反馈神经网络\(f(w_{t-n+1},...,w_{t})\)来拟合一个词序列的条件概率\(p(w_t|w_{t-1}, w_{t-2}, ..., w_{t-n+1})\)

Word2Vec: CBoW 与 Skip-gram Model

NNLM相比原始的bigram,trigram,已经可以将考虑的gram数量提升很多。
但是它的训练是非常的慢的,因为语料库规模要有千万甚至上亿,这导致embedding向量和网络最后一层的softmax层参数量极大。
于是2013年,Mikolov通过两篇论文,提出了word2vec。
很多人误以为word2vec是一种深度学习算法。其实word2vec算法的背后是一个浅层神经网络。另外需要强调的一点是,word2vec是一个计算word vector的开源工具。当我们在说word2vec算法或模型的时候,其实指的是其背后用于计算word vector的CBoW模型和Skip-gram模型。很多人以为word2vec指的是一个算法或模型,这也是一种谬误。
所以word2vec是一个工具,这个工具包含了CBow和Skip-gram两种模型来计算word vector。CBow和Skip-gram也可以用于NNLM,但是word2vec并不是这么做的,它针对NNLM的缺点提出了新的训练技巧Hierarchical Softmax和Negative Sampling。

CBow模型 (Continuous Bag-of-Words Model)

CBOW模型的训练输入是某一个特征词的上下文相关的词对应的词向量,而输出就是这特定的一个词的词向量。比如下面这段话,我们的上下文大小取值为4,特定的这个词是"Learning",也就是我们需要的输出词向量,上下文对应的词有8个,前后各4个,这8个词是我们模型的输入。由于CBOW使用的是词袋模型,因此这8个词都是平等的,也就是不考虑他们和我们关注的词之间的距离大小,只要在我们上下文之内即可。

这样我们这个CBOW的例子里,我们的输入是8个词向量,输出是所有词的softmax概率(训练的目标是期望训练样本特定词对应的softmax概率最大),对应的CBOW神经网络模型输入层有8个神经元,输出层有词汇表大小个神经元。隐藏层的神经元个数我们可以自己指定。通过DNN的反向传播算法,我们可以求出DNN模型的参数,同时得到所有的词对应的词向量。这样当我们有新的需求,要求出某8个词对应的最可能的输出中心词时,我们可以通过一次DNN前向传播算法并通过softmax激活函数找到概率最大的词对应的神经元即可。
这里介绍的是CBow的思想,也可以理解为在NNLM中使用CBoW。基于CBoW的word2vec工具在这个思想基础上还做了很多训练技巧的改进。
所以如果用基于CBow的NNLM,目标函数可以选交叉熵。

Skip-gram模型

Skip-Gram模型和CBOW的思路是反着来的,即输入是特定的一个词的词向量,而输出是特定词对应的上下文词向量。还是上面的例子,我们的上下文大小取值为4, 特定的这个词"Learning"是我们的输入,而这8个上下文词是我们的输出。
这样我们这个Skip-Gram的例子里,我们的输入是特定词, 输出是softmax概率排前8的8个词,对应的Skip-Gram神经网络模型输入层有1个神经元,输出层有词汇表大小个神经元。隐藏层的神经元个数我们可以自己指定。通过DNN的反向传播算法,我们可以求出DNN模型的参数,同时得到所有的词对应的词向量。这样当我们有新的需求,要求出某1个词对应的最可能的8个上下文词时,我们可以通过一次DNN前向传播算法得到概率大小排前8的softmax概率对应的神经元所对应的词即可。
和CBoW一样,这里介绍的是Skip-Gram的思想,也可以理解为在NNLM中使用Skip-Gram。基于Skip-Gram的word2vec工具在这个思想基础上也做了很多训练技巧的改进。
这里目标函数同样可以选取交叉熵。

Hierarchical Softmax

NNLM中,hidden layer是由input经过神经网络的线性变换加激活函数得到的,基于CBow的word2vec中,将这步简化为了直接对input中的词向量们做average pooling,即输入(1,2,3,4),(9,6,11,8),(5,10,7,12),得到(5,6,7,8)。(基于Skip-gram的word2vec的hidden layer就直接等于input了,其实就是没有hiddenlayer)
另外第二个改进是针对隐藏层到softmax层的。我们知道,哈夫曼树是一种让权重高的节点(使用频率高的)编码短(更快取到)的数据结构。word2vec就使用哈夫曼树来对单词们编码,从根节点开始,每个节点之间都对应一个权重,通过节点权重和隐层中间语义的二分类逻辑回归来判断对应的下一个单词应该出现在那个叶子节点上。可以看出,哈夫曼树的叶子节点就对应了NNLM中输出softmax层中的一个个神经元。
这样,我们在训练阶段,如果使用NNLM,我们需要对所有V个节点都进行前向传播,而使用了Hierarchical Softmax之后,前向传播最多只用计算logV次即可(哈夫曼树树深)。大大降低了前向传播的计算量。
不过反向传播更新参数的计算量可能并没有减少。我们依然可以把哈夫曼树的叶子节点们看作NNLM中最后一层输出层,所以目标函数还是可以用同样的softmax。
Hierarchical Softmax与两种word2vec模型的具体结合参见:word2vec原理(二) 基于Hierarchical Softmax的模型

Negative Sampling

Hierarchical Softmax有效降低了前向传播的计算量,但是其实它是增加了网络的参数量的。Negative Sampling则是从另一个方向来对NNLM做改进。
其实思路比Hierarchical Softmax简单,就是我们要根据输入的\(w_i\)两边的2c个词,然\(w_i\)在输出中概率最高,那么我们再采几个负样本的词,然后他们在输出中概率最低,这样可以避免网络的参数倾向于让大家的得分都越来越高(冷落了那些出现较少的但是其实也很重要的词)。这点在推荐系统中比较常见。
Negative Sampling具体参见:word2vec原理(三) 基于Negative Sampling的模型
以上的改进在论文https://arxiv.org/pdf/1411.2738.pdf中也有详细介绍。

参考文献

https://www.cnblogs.com/guoyaohua/p/9240336.html 整体,Word2Vec
https://www.cnblogs.com/ljy2013/p/6425277.html NGram
https://www.jianshu.com/p/4452cf120bd7 NGram

posted @ 2019-04-22 21:14  大胖子球花  阅读(5727)  评论(0编辑  收藏  举报