第二章:分布式表征
基于统计的 NLP 已经成为建模复杂自然语言任务的首要选择。然而在它刚兴起的时候,基于统计的 NLP 经常遭受到维度灾难,尤其是在学习语言模型的联合概率函数时。这为构建能在低维空间中学习分布式词表征的方法提供了动力,这种想法也就导致了词嵌入方法的诞生。
第一种在低维空间中学习密集型的分布式词表征是 Yoshua Bengio 等人在 2003 年提出的 A Neural Probabilistic Language Model,这是一种基于学习而对抗维度灾难的优美想法。
词嵌入
如下图 2 所示,分布式向量或词嵌入向量基本上遵循分布式假设,即具有相似语义的词倾向于具有相似的上下文词,因此这些词向量尝试捕获邻近词的特征。分布式词向量的主要优点在于它们能捕获单词之间的相似性,使用余弦相似性等度量方法评估词向量之间的相似性也是可能的。
词嵌入常用于深度学习中的第一个数据预处理阶段,一般我们可以在大型无标注文本语料库中最优化损失函数,从而获得预训练的词嵌入向量。例如基于上下文预测具体词(Mikolov et al., 2013b, a)的方法,它能学习包含了一般句法和语义的词向量。这些词嵌入方法目前已经被证明能高效捕捉上下文相似性,并且由于它们的维度非常小,因此在计算核心 NLP 任务是非常快速与高效的。
图 2:分布式词向量表征,其中每一个词向量只有 D 维,且远小于词汇量大小 V,即 D<本身词嵌入就能直接用于搜索近义词或者做词义的类推,而下游的情感分类、机器翻译、语言建模等任务都能使用词嵌入编码词层面的信息。最近比较流行的预训练语言模型其实也参考了词嵌入的想法,只不过预训练语言模型在词嵌入的基础上进一步能编码句子层面的语义信息。总的而言,词嵌入的广泛使用早已体现在众多文献中,它的重要性也得到一致的认可。
分布式表示(词嵌入)主要通过上下文或者词的「语境」来学习本身该如何表达。上个世纪 90 年代,就有一些研究(Elman, 1991)标志着分布式语义已经起步,后来的一些发展也都是对这些早期工作的修正。此外,这些早期研究还启发了隐狄利克雷分配等主题建模(Blei et al., 2003)方法和语言建模(Bengio et al., 2003)方法。
在 2003 年,Bengio 等人提出了一种神经语言模型,它可以学习单词的分布式表征。他们认为这些词表征一旦使用词序列的联合分布构建句子表征,那么就能构建指数级的语义近邻句。反过来,这种方法也能帮助词嵌入的泛化,因为未见过的句子现在可以通过近义词而得到足够多的信息。
图 3:神经语言模型(图源:http://www.jmlr.org/papers/volume3/bengio03a/bengio03a.pdf)Collobert 和 Weston(2008) 展示了第一个能有效利用预训练词嵌入的研究工作,他们提出的神经网络架构构成了当前很多方法的基础。这一项研究工作还率先将词嵌入作为 NLP 任务的高效工具,不过词嵌入真正走向 NLP 主流还是 Mikolov 等人在 2013 年做出的研究《Distributed Representations of Words and Phrases and their Compositionality》。
Mikolov 等研究者在这篇论文中提出了连续词袋模型(CBOW)和 Skip-Gram 模型,这两种方法都能学习高质量的分布式词表征。此外,令这两种方法受到极大关注的是另一种附加属性:语义合成性,即两个词向量相加得到的结果是语义相加的词,例如「man」+「royal」=「king」。这种语义合成性的理论依据最近已经由 Gittens et al. (2017) 给出,他们表示只有保证某些特定的假设才能满足语义合成性,例如词需要在嵌入空间中处于均匀分布。
Pennington et al. (2014) 提出了另一个非常出名的词嵌入方法 GloVe,它基本上是一种基于词统计的模型。在有些情况下,CBOW 和 Skip-Gram 采用的交叉熵损失函数有劣势。因此 GloVe 采用了平方损失,它令词向量拟合预先基于整个数据集计算得到的全局统计信息,从而学习高效的词词表征。
一般 GloVe 模型会先对单词计数进行归一化,并通过对数平滑来最终得到词共现矩阵,这个词共现矩阵就表示全局的统计信息。这个矩阵随后可以通过矩阵分解得到低维的词表征,这一过程可以通过最小化重构损失来获得。下面将具体介绍目前仍然广泛使用的 CBOW 和 Skip-Gram 两种 Word2Vec 方法(Mikolov et al., 2013)。
Word2Vec
可以说 Mikolov 等人彻底变革了词嵌入,尤其是他们提出的 CBOW 和 Skip-Gram 模型。CBOW 会在给定上下文词的情况下计算目标词(或中心词)的条件概率,其中上下文词的选取范围通过窗口大小 k 决定。而 Skip-Gram 的做法正好与 CBOW 相反,它在给定目标词或中心词的情况下预测上下文词。一般上下文词都会以目标词为中心对称地分布在两边,且在窗口内的词与中心词的距离都相等。也就是说不能因为某个上下文词离中心词比较远,就认为它对中心词的作用比较弱。
在无监督的设定中,词嵌入的维度可以直接影响到预测的准确度。一般随着词嵌入维度的增加,预测的准确度也会增加,直到准确率收敛到某个点。一般这样的收敛点可以认为是最佳的词嵌入维度,因为它在不影响准确率的情况下最精简。通常情况下,我们使用的词嵌入维度可以是 128、256、300、500 等,相比于几十万的词汇库大小已经是很小的维度了。
下面我们可以考虑 CBOW 的简化版,上下文只考虑离中心词最近的一个单词,这基本上就是二元语言模型的翻版。
图 4:CBOW 模型如图 4 所示,CBOW 模型就是一个简单的全连接神经网络,它只有一个隐藏层。输入层是上下文词的 one-hot 向量,它有 V 个神经元(词汇量),而中间的隐藏层只有 N 个神经元,N 是要远远小于 V 的。最后的输出层是所有词上的一个 Softmax 函数。层级之间的权重矩阵分别是 V*N 阶的 W 和 N*V 阶的 W',词汇表中的每一个词最终会表征为两个向量:v_c 和 v_w,它们分别对应上下文词表征和目标词表征。若输入的是词表中第 k 个词,那么我们有:
总体而言,在给定上下文词 c 作为输入的情况下,对于任意词 w_i 有:
参数 θ={V_w, V_c} 都是通过定义目标函数而学习到的,一般目标函数可以定义为对数似然函数,且通过计算以下梯度更新权重:
在更广泛的 CBOW 模型中,所有上下文词的 one-hot 向量都会同时作为输入,即:
词嵌入的一个局限是它们无法表示短语(Mikolov et al., 2013),即两个词或多个词的组合并不表示对应的短语意义,例如「人民」+「大学」并不能组合成「人民大学」。Mikolov 提出的一种解决办法是基于词共现识别这些短语,并为它们单独地学一些词嵌入向量,而 Rie Johnson 等研究者在 15 年更是提出直接从无监督数据中学习 n-gram 词嵌入。
另一种局限性在于学习的词嵌入仅基于周围词的小窗口,有时候「good」和「bad」几乎有相同的词嵌入,这对于情感分析等下游任务很不友好。有时候这些相似的词嵌入有正好相反的情感,这对于需要区别情感的下游任务简直是个灾难,它甚至比用 One-hot 向量的表征方法还要有更差的性能。Duyu Tang(2014)等人通过提出特定情感词嵌入(SSWE)来解决这个问题,他们在学习嵌入时将损失函数中的监督情感纳入其中。
一个比较重要的观点是,词嵌入应该高度依赖于他们要使用的领域。Labutov 和 Lipson(2013) 提出了一种用于特定任务的词嵌入,他们会重新训练词嵌入,因此将词嵌入与将要进行的下游任务相匹配,不过这种方法对计算力的需求比较大。而 Mikolov 等人尝试使用负采样的方法来解决这个问题,负采样仅仅只是基于频率对负样本进行采样,这个过程直接在训练中进行。
此外,传统的词嵌入算法为每个词分配不同的向量,这使得其不能解释多义词。在最近的一项工作中,Upadhyay 等人 (2017) 提出了一种新方法来解决这个问题,他们利用多语平行数据来学习多语义词嵌入。例如英语的「bank」在翻译到法语时有两种不同的词:banc 和 banque,它们分别表示金融和地理意义,而多语言的分布信息能帮助词嵌入解决一词多义的问题。
下表 1 提供了用于创建词嵌入的现有框架,它们都可以训练词嵌入并进一步与深度学习模型相结合:
说到这里,小编不得不宣传一波我们的小项目,我们主要使用维基的中文语料训练了一个中文词嵌入,并提供了 Skip-Gram 和 GloVe 两种模型的训练方法。读者可以简单地使用我们已训练的词嵌入,或者根据我们提供的 Jupyter Notebook 教程学习如何训练词嵌入。简单而言,训练主要可以分为 5 个步骤,即下载维基中文语料、将繁体转化为简体、采用结巴分词、预处理并构建数据集、开始训练。
当然我们放在 Colab 的示例代码只是训练部分维基语料,但也能做出了较为合理的中文词嵌入。
项目地址:https://github.com/HoratioJSY/c