人机交互系统(2.2)——Embedding的历史由来
1 前言
首先回顾一下自然语言处理中的一个基本问题:
- 如何计算一段文本序列在某种语言下出现的概率?
- 之所以称其为一个基本问题,是因为它在很多NLP任务中都扮演着重要的角色。
- 例如:去哪 。。。联想到“ 吃饭!”的概率,即“吃饭”这个词在“去哪”这种语言环境下出现的概率。
2 词向量
最早的词向量是很冗长的,它使用是词向量维度大小为整个词汇表的大小,对于每个具体的词汇表中的词,将对应的位置置为1。比如我们要表示春夏秋冬四季,词“Queen”的序号为2, 那么它的词向量就是(0,1,0,0,)。这种词向量的编码方式我们一般叫做1-of-N representation
或者one hot representation.
One hot representation
用来表示词向量非常简单,但是却有很多问题。最大的问题是我们的词汇表一般都非常大,比如达到百万级别,这样每个词都用百万维的向量来表示简直是内存的灾难。这样的向量其实除了一个位置是1,其余的位置全部都是0,表达的效率不高。
另外一个问题,这些向量之间是正交的,向量之间无法关联。例如:我们期望 一天+一天 = 两天 ,用one hot representation
是无法表示的。
3 N-gram 模型
3.1 N-Gram模型作用
N-Gram模型(有时也称为N元模型)是自然语言处理中一个非常重要的概念,通常在NLP中,人们基于一定的语料库,可以利用N-Gram来预计或者评估一个句子是否合理。另外一方面,N-Gram的另外一个作用是用来评估两个字符串之间的差异程度。这是模糊匹配中常用的一种手段。
假设有一个字符串 s,那么该字符串的N-Gram
就表示按长度 N 切分原词得到的词段,也就是 ss 中所有长度为 N 的子字符串。设想如果有两个字符串,然后分别求它们的N-Gram,那么就可以从它们的共有子串的数量这个角度去定义两个字符串间的N-Gram距离。但是仅仅是简单地对共有子串进行计数显然也存在不足,这种方案显然忽略了两个字符串长度差异可能导致的问题。比如字符串 girl
和 girlfriend
,二者所拥有的公共子串数量显然与 girl 和其自身所拥有的公共子串数量相等,但是我们并不能据此认为 girl
和girlfriend
是两个等同的匹配。
为了解决该问题,有学者便提出以非重复的N-Gram分词为基础来定义 N-Gram距离这一概念,可以用下面的公式来表述:
|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。
常见的如bigram
模型(N=2)和trigram
模型(N=3)。事实上,由于模型复杂度和预测精度的限制,我们很少会考虑N>3的模型
3.2 缺陷
- 参数爆炸式增长
- 没有考虑词与词之间的联系性
3.3 应用
- S=w1,w2,…,wT
- 它的概率可以表示为:
P(S) = P(w1,w2,w3,…,wt) - 公式的含义:“我们”这个词出现后接下来出现的词的概率,即计算
P(都),P(不),P(长),P(的)...
- 由于其巨大的参数空间,这样一个原始的模型在实际中并没有什么用。我们更多的是采用其简化版本——Ngram模型:
p(wt|w1,w2,…,wt−1)≈p(wt|wt−n+1,…,wt−1)
4 分布式语义表达(Distributed representation)
Ngram本质上是将词当做一个个孤立的原子单元(atomic unit
)去处理的。这种处理方式对应到数学上的形式是一个个离散的one-hot
向量(除了一个词典索引的下标对应的方向上是1 ,其余方向上都是0)。
例如,对于一个大小为5的词典:{“I”, “love”, “nature”, “luaguage”, “processing”},“nature”对应的one-hot向量为:[0,0,1,0,0] 。显然,one-hot
向量的维度等于词典的大小。这在动辄上万甚至百万词典的实际应用中,面临着巨大的维度灾难问题(The Curse of Dimensionality
)
能否用一个连续的稠密向量去刻画一个word
的特征呢?
这样,我们不仅可以直接刻画词与词之间的相似度,还可以建立一个从向量到概率的平滑函数模型,使得相似的词向量可以映射到相近的概率空间上。这个稠密连续向量也被称为word
的distributed representation
Distributed representation可
以解决One hot representation
的问题,它的思路是通过训练,将每个词都映射到一个较短的词向量上来。
所有的这些词向量就构成了向量空间,进而可以用普通的统计学的方法来研究词与词之间的关系。这个较短的词向量维度是多大呢?这个一般需要我们在训练时自己来指定。可以用n个维度来表示。
有了用Distributed Representation表示的较短的词向量,我们就可以较容易的分析词之间的关系了,比如我们将词的维度降维到2维,有一个有趣的研究表明,用下图的词向量表示我们的词时,我们可以发现:
可见我们只要得到了词汇表里所有词对应的词向量,那么我们就可以做很多有趣的事情了。不过,怎么训练得到合适的词向量呢?一个很常见的方法是使用神经网络语言模型。
6 Neural Network Language Model
鉴于Ngram等模型的不足,2003年,Bengio等人发表了一篇开创性的文章:A neural probabilistic language model[4]。在这篇文章里,他们总结出了一套用神经网络建立统计语言模型的框架(Neural Network Language Model,以下简称NNLM),并首次提出了word embedding的概念(虽然没有叫这个名字),从而奠定了包括word2vec在内后续研究word representation learning的基础。
NNLM[5]模型的基本思想可以概括如下:
- 假定词表中的每一个word都对应着一个连续的特征向量;
- 假定一个连续平滑的概率模型,输入一段词向量的序列,可以输出这段序列的联合概率;同时学习词向量的权重和概率模型里的参数。
首先是一个线性的Embedding层。它将输入的N−1个one-hot词向量,通过一个共享的D×V的矩阵C,映射为N−1个分布式的词向量(distributed vector)。其中,V是词典的大小,D是Embedding向量的维度(一个先验参数)。C矩阵里存储了要学习的word vector。
其次是一个简单的前向反馈神经网络g。它由一个tanh隐层和一个softmax输出层组成。通过将Embedding层输出的N−1个词向量映射为一个长度为V的概率分布向量,从而对词典中的word在输入context下的条件概率做出预估。
8 CBOW与Skip-Gram用于神经网络语言模型
NNLM模型的训练其实可以拆分成两个步骤:
- 用一个简单模型训练出连续的词向量
- 基于词向量的表达,训练一个连续的Ngram神经网络模型
问题:
- 只能处理定长的序列
- 训练慢
如果只是想得到word的连续特征向量,可以对第二步里的神经网络模型进行简化。于是 Mikolov 在2013年一口气推出了两篇paper,并开源了一款计算词向量的工具——至此,word2vec
横空出世,主角闪亮登场。
对原始的NNLM模型做如下改造:
- 移除前向反馈神经网络中非线性的hidden layer,直接将中间层的Embedding layer与输出层的softmax layer连接;
- 忽略上下文环境的序列信息:输入的所有词向量均汇总到同一个Embedding layer;
- 将Future words纳入上下文环境
得到的模型称之为CBOW模型(Continuous Bag-of-Words Model),也是word2vec算法的第一个模型:
从数学上看,CBOW模型等价于一个词袋模型的向量乘以一个Embedding矩阵,从而得到一个连续的embedding向量。这也是CBOW模型名称的由来。
- 在word2vec出现之前,已经有用神经网络DNN来用训练词向量进而处理词与词之间的关系了。采用的方法一般是一个三层的神经网络结构(当然也可以多层),分为输入层,隐藏层和输出层(softmax层)。
- 这个模型是如何定义数据的输入和输出呢?一般分为CBOW(Continuous Bag-of-Words 与Skip-Gram两种模型。
- CBOW模型的训练输入是某一个特征词的上下文相关的词对应的词向量,而输出就是这特定的一个词的词向量。比如下面这段话,我们的上下文大小取值为4,特定的这个词是"Learning",也就是我们需要的输出词向量,上下文对应的词有8个,前后各4个,这8个词是我们模型的输入。由于CBOW使用的是词袋模型,因此这8个词都是平等的,也就是不考虑他们和我们关注的词之间的距离大小,只要在我们上下文之内即可。
这样我们这个CBOW的例子里,我们的输入是8个词向量,输出是所有词的softmax概率(训练的目标是期望训练样本特定词对应的softmax概率最大),对应的CBOW神经网络模型输入层有8个神经元,输出层有词汇表大小个神经元。隐藏层的神经元个数我们可以自己指定。通过DNN的反向传播算法,我们可以求出DNN模型的参数,同时得到所有的词对应的词向量。这样当我们有新的需求,要求出某8个词对应的最可能的输出中心词时,我们可以通过一次DNN前向传播算法并通过softmax**函数找到概率最大的词对应的神经元即可。
Skip-Gram模型和CBOW的思路是反着来的,即输入是特定的一个词的词向量,而输出是特定词对应的上下文词向量。还是上面的例子,我们的上下文大小取值为4, 特定的这个词"Learning"是我们的输入,而这8个上下文词是我们的输出。
这样我们这个Skip-Gram的例子里,我们的输入是特定词, 输出是softmax概率排前8的8个词,对应的Skip-Gram神经网络模型输入层有1个神经元,输出层有词汇表大小个神经元。隐藏层的神经元个数我们可以自己指定。通过DNN的反向传播算法,我们可以求出DNN模型的参数,同时得到所有的词对应的词向量。这样当我们有新的需求,要求出某1个词对应的最可能的8个上下文词时,我们可以通过一次DNN前向传播算法得到概率大小排前8的softmax概率对应的神经元所对应的词即可。
10 层次Softmax(Hierarchical Softmax)
然而,直接对词典里的V个词计算相似度并归一化,显然是一件极其耗时的impossible mission。为此,Mikolov引入了两种优化算法:层次Softmax(Hierarchical Softmax)和负采样(Negative Sampling)。
层次Softmax的方法最早由Bengio在05年引入到语言模型中。它的基本思想是将复杂的归一化概率分解为一系列条件概率乘积的形式:
其中,每一层条件概率对应一个二分类问题,可以通过一个简单的逻辑回归函数去拟合。这样,我们将对V个词的概率归一化问题,转化成了对logV个词的概率拟合问题。
11 Negative Sampling
比如我们有一个训练样本,中心词是w,它周围上下文共有2c个词,记为context(w)。由于这个中心词w的确和context(w) 相关存在,因此它是一个真实的正例。
通过Negative Sampling采样,我们得到neg个和w不同的中心词Wi,i=1,2,…neg,这样context(w) 和wi就组成了neg个并不真实存在的负例。利用这一个正例和neg个负例,我们进行二元逻辑回归,得到负采样对应每个词wi对应的模型参数θi,和每个词的词向量。
12 FastText
fastText[6]是一种 Facebook AI Research 在16年开源的一个文本分类器。 其特点就是fast。相对于其它文本分类模型,如SVM,Logistic Regression 和 neural network等模型,fastText 在保持分类效果的同时,大大缩短了训练时间。
FastText的原理fastText 方法包含三部分:
- 模型架构
- 层次 Softmax
- N-gram 特征
fastText 模型输入一个词的序列(一段文本或者一句话),输出这个词序列属于不同类别的概率。序列中的词和词组组成特征向量,特征向量通过线性变换映射到中间层,中间层再映射到标签。
1.模型的输出层:word2vec的输出层,对应的是每一个term,计算某term的概率最大;而fasttext的输出层对应的是 分类的label,不过不管输出层对应的是什么内容,起对应的vector都不会被保留和使用。
2.模型的输入层:word2vec的输入层,是 context window 内的term;而fasttext 对应的整个sentence的内容,包括term,也包括 n-gram的内容;
13 参考文献
[1] https://blog.csdn.net/baimafujinji/article/details/51281816
[2] https://www.cnblogs.com/pinard/p/7160330.html
[3] Speech and Language Processing. Daniel Jurafsky & James H. Martin, 3rd. Chapter 4
[4] A neural probabilistic language model. http://www.jmlr.org/papers/volume3/bengio03a/bengio03a.pdf
[5] https://blog.csdn.net/lilong117194/article/details/82018008
[6] https://www.cnblogs.com/huangyc/p/9768872.html
上一篇: itchat--使用python实现与图灵机器人交互
下一篇: Geetest极验验证码的使用