NLP里面,最细粒度的是 词语,词语组成句子,句子再组成段落、篇章、文档。所以处理 NLP 的问题,首先就要拿词语开刀。词语,是人类的抽象总结,是符号形式的(比如中文、英文、拉丁文等等),所以需要把他们转换成数值形式,或者说——嵌入到一个数学空间里,这种嵌入方式,就叫词嵌入(word embedding)。简单点来说就是把一个词语映射一个新的空间,并以多维的实数向量表示,来让机器读取数据。
NLP 中最直观,也是到目前为止最常用的词表示方法是 One-hot Representation,这种方法把每个词表示为一个很长的向量。这个向量的维度是词表大小,其中绝大多数元素为 0,只有一个维度的值为 1,这个维度就代表了当前的词。
举个栗子,
“话筒”表示为 [0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 …]
“麦克”表示为 [0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 …]
每个词都是茫茫 0 海中的一个 1。
这种 One-hot Representation 如果采用稀疏方式存储,会是非常的简洁:也就是给每个词分配一个数字 ID。比如刚才的例子中,话筒记为 3,麦克记为 8(假设从 0 开始记)。如果要编程实现的话,用 Hash 表给每个词分配一个编号就可以了。这么简洁的表示方法配合上最大熵、SVM、CRF 等等算法已经很好地完成了 NLP 领域的各种主流任务。
当然这种表示方法也存在一个重要的问题就是“词汇鸿沟”现象:任意两个词之间都是孤立的。光从这两个向量中看不出两个词是否有关系,哪怕是话筒和麦克这样的同义词也不能幸免于难。
Deep Learning 中一般用到的词向量并不是刚才提到的用 One-hot Representation 表示的那种很长很长的词向量,而是用 Distributed Representation表示的一种低维实数向量。
该方法最早由 Hinton在 1986 年提出。它是一种低维实数向量,这种向量一般长成这个样子:[0.792, −0.177, −0.107, 0.109, −0.542, …]。维度以 50 维和 100 维比较常见。这种向量的表示不是唯一的,后文会提到目前计算出这种向量的主流方法。
采用低维空间表示法,不但解决了维数灾难问题,并且挖掘了word之间的关联属性,从而提高了向量语义上的准确度。
语言模型形式化的描述就是给定一个字符串,看它是自然语言的概率 P ( w 1 , w 2 , … , w n ) P(w_1,w_2,…,w_n) P(w1,w2,…,wn),其中 w 1 , w 2 , … , w n w_1,w_2,…,w_n w1,w2,…,wn依次表示这句话中的各个词。如何计算这样的概率呢?为了简便处理,我们可以根据前n个词来预测下一个词。这样我们就得到了Unigram Model,Bigram Model, Trigram Model或者N-gram Model。
unigram是将每个单词都视为独立无关的
P ( w 1 , w 2 , … , w n ) = ∏ i = 1 n p ( w i ) P(w_1,w_2,…,w_n) = \prod_{i=1}^np(w_i) P(w1,w2,…,wn)=i=1∏np(wi)
Birgram Model是指如果当前单词只依赖前一单词,可以用 p ( w 2 ∣ w 1 ) p(w_2|w_1) p(w2∣w1)表示在出现单词w1时出现w2的概率
P ( w 1 , w 2 , … , w n ) = ∏ i = 2 n p ( w i ∣ w i − 1 ) P(w_1,w_2,…,w_n) = \prod_{i=2}^np(w_i|w_{i-1}) P(w1,w2,…,wn)=i=2∏np(wi∣wi−1)
N-gram model
P ( w 1 , w 2 , … , w n ) = ∏ i = 2 n p ( w i ∣ w 1 , … , w i − 1 ) ≈ ∏ i = 2 n p ( w i ∣ w i − ( n − 1 ) , … , w i − 1 ) P(w_1,w_2,…,w_n)=\prod_{i=2}^np(w_i|w_1,…,w_{i-1})\approx\prod_{i=2}^np(w_i|w_{i-(n-1)},…,w_{i-1}) P(w1,w2,…,wn)=i=2∏np(wi∣w1,…,wi−1)≈i=2∏np(wi∣wi−(n−1),…,wi−1)
事实上直接使用N-gram模型来计算句子概率是有问题的。因为它太简单了,最多能表示单词和前n个单词的关系,前n+1个单词就无法表示。而且n不能太大,太大会导致计算问题,并且n太大通常性能不会有明显的提升。
1) LSA矩阵分解模型
采用线性代数中的奇异值分解方法,选取前几个比较大的奇异值所对应的特征向量将原矩阵映射到低维空间中,从而达到词矢量的目的。
2)PLSA 潜在语义分析概率模型
从概率学的角度重新审视了矩阵分解模型,并得到一个从统计,概率角度上推导出来的和LSA相当的词矢量模型。
3) LDA 文档生成模型
按照文档生成的过程,使用贝叶斯估计统计学方法,将文档用多个主题来表示。LDA不只解决了同义词的问题,还解决了一词多义的问题。目前训练LDA模型的方法有原始论文中的基于EM和 差分贝叶斯方法以及后来出现的Gibbs Samplings采样算法。
4)Word2Vector 模型
其通过神经网络机器学习算法来训练N-gram语言模型,并在训练过程中求出word所对应的vector的方法。
word2vec就是将词表征为实数值向量的一种高效的算法模型,其利用深度学习的思想,可以通过训练,把对文本内容的处理简化为 K 维向量空间中的向量运算,而向量空间上的相似度可以用来表示文本语义上的相似。其使用 Distributed representation 的词向量表示方式。
通过训练将每个词映射成 K 维实数向量(K 一般为模型中的超参数),通过词之间的距离(比如 cosine 相似度、欧氏距离等)来判断它们之间的语义相似度.其采用一个 三层的神经网络 ,输入层-隐层-输出层。有个核心的技术是根据词频用Huffman编码 ,使得所有词频相似的词隐藏层激活的内容基本一致,出现频率越高的词语,他们激活的隐藏层数目越少,这样有效的降低了计算的复杂度
word2vec模型中,主要有Skip-Gram和CBOW两种模型,从直观上理解,Skip-Gram是给定input word来预测上下文。而CBOW是给定上下文,来预测input word。
word2vec模型实际上分为了两个部分,第一部分为建立模型,第二部分是通过模型获取嵌入词向量。Word2Vec的整个建模过程实际上与自编码器(auto-encoder)的思想很相似,即先基于训练数据构建一个神经网络,当这个模型训练好以后,我们并不会用这个训练好的模型处理新的任务,我们真正需要的是这个模型通过训练数据所学得的参数,例如隐层的权重矩阵——后面我们将会看到这些权重在Word2Vec中实际上就是我们试图去学习的“word vectors”
word2vec给定一个词,预测词汇表中每个词出现在其上下文的概率
这个算法的步骤如下:
假设从我们的训练文档中抽取出10000个唯一不重复的单词组成词汇表。我们对这10000个单词进行one-hot编码,得到的每个单词都是一个10000维的向量,向量每个维度的值只有0或者1,假如单词ants在词汇表中的出现位置为第3个,那么ants的向量就是一个第三维度取值为1,其他维都为0的10000维的向量(ants=[0, 0, 1, 0, …, 0])。
模型的输入如果为一个10000维的向量,那么输出也是一个10000维度(词汇表的大小)的向量,它包含了10000个概率,每一个概率代表着当前词是输入样本中output word的概率大小。
基于成对的单词来对神经网络进行训练,训练样本是 ( input word, output word ) 这样的单词对,input word和output word都是one-hot编码的向量。最终模型的输出是一个概率分布。
对于我们在训练原始文本中遇到的每一个单词,它们都有一定概率被我们从文本中删掉,而这个被删除的概率与单词的频率有关。
如果我们设置窗口大小(即),并且从我们的文本中删除所有的“the”。
p ( w i ) p(w_i) p(wi)代表保留单词 w i w_i wi的概率, z ( w i ) z(w_i) z(wi)代表 w i w_i wi出现的频率,sample代表阈值,默认为0.001
p ( w i ) = ( z ( w i ) 0.001 + 1 ) ∗ 0.001 z ( w i ) p(w_i)=(\sqrt{\frac {z(w_i)}{0.001}}+1)*\frac{0.001}{z(w_i)} p(wi)=(0.001z(wi)+1)∗z(wi)0.001
不同于原本每个训练样本更新所有的权重,负采样每次让一个训练样本仅仅更新一小部分的权重。
当我们用训练样本 ( input word: “fox”,output word: “quick”) 来训练我们的神经网络时,“ fox”和“quick”都是经过one-hot编码的。如果我们的vocabulary大小为10000时,在输出层,我们期望对应“quick”单词的那个神经元结点输出1,其余9999个都应该输出0。在这里,这9999个我们期望输出为0的神经元结点所对应的单词我们称为“negative” word。
当使用负采样时,我们将随机选择一小部分的negative words(比如选5个negative words)来更新对应的权重。我们也会对我们的“positive” word进行权重更新(在我们上面的例子中,这个单词指的是”quick“)。
在论文中,作者指出指出对于小规模数据集,选择5-20个negative words会比较好,对于大规模数据集可以仅选择2-5个negative words。
一个单词被选作negative sample的概率跟它出现的频次有关,出现频次越高的单词越容易被选作negative words。
p ( w i ) = f ( w i ) 3 / 4 ∑ j = 0 n f ( w i ) 3 / 4 p(w_i)=\frac{f(w_i)^{3/4}}{\sum_{j=0}^nf(w_i)^{3/4}} p(wi)=∑j=0nf(wi)3/4f(wi)3/4
Word2Vec概述与基于Hierarchical Softmax的CBOW和Skip-gram模型公式推导
理解 Word2Vec 之 Skip-Gram 模型
基于TensorFlow实现Skip-Gram模型