作者,四川大学博士生,刘大一恒。本文已经获得 ChatbotMagazine 公众号授权。
内容速览
☛ 什么是记忆网络
☛ 基于记忆网络的KB-QA
☛ 小结
在上两期,我们分别介绍了使用深度学习的卷积神经网络对向量建模和语义解析方法进行提升的两篇经典论文。(详情翻查公众号历史记录。)
本期我们将为大家带来两篇使用深度学习其他两种经典模型进行KB-QA的文章,分别是记忆网络(Memory Network)和带注意力机制的循环神经网络(Recurrent Neural Networks with Attention Mechanism)。它们都是深度学习用于自然语言处理领域(Deep Learning for NLP)中相当火热的方法。就让我们一起来看看如何将它们应用到KB-QA中吧。这一期将会分两篇介绍使用深度学习其他两种经典模型进行KB-QA的文章。
这一次先介绍关于记忆网络的文章,带注意力机制的循环神经网络我们将会在下一篇介绍。现在就让我们一起来看看如何将记忆网络应用到KB-QA中吧。
什么是记忆网络
(了解记忆网络的朋友可直接跳过该段)
记忆网络由Facebook AI Research的Jason Weston等人提出,其论文发表在2015年ICRL会议。对于很多问题(如自动问答、对话系统等),我们都希望我们的模型能够像我们人一样具有记忆机制,能够记住一些信息(上下文、知识库等),为此我们发明了很多的记忆模型。一个广为人知的记忆模型就是长短时记忆网络(Long Short-Term Memory, LSTM)。然而它的记忆实质上是一种内在(Internal)表达,只能记住在使用时所输入的一些历史信息。它就像计算机的内存一样,能够存储一些使用时的历史输入信息(把所有的历史输入信息都压缩到一个低维空间上,这样也会损失很多信息),一旦使用完毕,记忆就会被抹去,记忆量也非常有限。
我们能不能找到一种外部(External)表达的记忆,就像计算机的硬盘一样,能够长期存取大量的记忆信息呢?在使用的时候再去记忆库中读取相关的记忆。对于我们的KB-QA问题,我们能否将知识库里的知识直接存储在我们的模型中呢?近年来,人们在这方面的研究作出了不懈努力,发明了一些能够提供外部记忆的模型,其中有两个最著名的模型,一个是由Google DeepMind团队提出的神经图灵机(Neural Tuning Machine),而另一个就是今天要讲的记忆网络。
记忆网络其实是一种框架结构,它里面的每一个模块(也称组件,Component)都可以根据应用套用不同的模型,也可以根据应用的需要增加其他的模块。
总体来说它可以分为以下5个模块:
输入模块I(Input):将外部输入转化为内部表达。我们可以把输入模块想象成人类的感知器官,接受外部的原始输入并将其转化为能够被大脑处理的生物信号。具体来说,输入模块用于将外部的输入(如自然语言句子、图片等)转化为内在的分布式表达。输入模块可以根据应用的需要选用不同的模型,诸如CNN、LSTM、bag-of-words等等。
记忆模块M(Memory):用于存储记忆。每一条记忆都是一个分布式表达向量,每一个记忆有一个索引地址号,所有记忆组成了我们的记忆模块。我们的记忆模块就像是计算机中的硬盘一样,存储着一条条的信息,每一个信息都有一个物理地址。我们可以记忆模块进行记忆的读取,修改,删除,也可以插入新的记忆信息。
泛化模块G(Generalization):根据外部输入的内在表达去更新记忆。我们可以根据新的输入对记忆模块中的每一个记忆都进行更新并增加新的记忆,也可以仅对部分相关记忆作针对性更新。最简单的方式是,直接将输入存储在记忆模块中而不对其他的记忆进行修改,即。这里是一个为输入选择记忆槽(为输入确定记忆的索引地址)的函数,在记忆存储满的时候,也可根据函数对记忆进行替换。更复杂一点,我们也可以引入一些遗忘机制等等。
输出模块O(Output):根据外部输入的内在表达去选择记忆模块中与之最相关的记忆。该记忆也称为支撑记忆(Support Memory),即。这个选择的方式有很多,最简单的方法就是将和记忆向量投影到同一个向量空间中,通过比较相似度得分(cosine,点乘等)来选择最相似度得分最高的记忆作为输出。当然我们也可以根据应用的需要,选择多个记忆作为输出。选择多个记忆的方式也有很多种,最简单的方法就是选择相似度得分最高的k个记忆作为输出,论文中作者提出了另一种方法,先选择得分最高的作为第一个输出,再选择与得分加上与得分 最高的记忆作为第二个输出,以此类推(这种方法更像是在进行推理,先将输入作为推理的支点,选择与输入最相关的记忆作为第一条线索,再根据输入和第一条线索去确定下一条线索)。
回答模块R(Response):根据输入的内在表达和输出模块提供的记忆,输出满足应用需要格式的结果。它就相当于encoder-decoder模型中的decoder部分,将和作为输入,根据应用的需要使用不同的模型输出最终的结果(分类器、语言模型、RNN、CNN等)。
如何去训练记忆网络呢?给定训练数据 输入输出对我们可以通过梯度下降算法优化margin-based ranking损失函数,去训练记忆网络中的所有参数。假设输出模块每次输出两条支撑记忆,我们的损失函数如下:
其中是随机采样的一些负样本。需要注意的是,这里我们在构造损失函数的时候,需要提供输出模块输出正确记忆的标签(即上式的),即记忆的正样本。但是在一般情况下,我们的训练数据都只有 输入输出对 ,难以提供关于记忆的标签。针对这一问题,纽约大学和Facebook AI Research的Sukhbaatar等人提出了端到端学习(End-to-End)的记忆网络,感兴趣的朋友可以点进去看看。
关于记忆网络还有很多的技巧(trick),我们可以通过哈希或聚类的方法提高查找记忆的效率,通过单词的上下文来处理未见过的单词等等,这里我们不再展开。
可以看出相比LSTM的内部记忆,记忆网络可以存储大量的外部记忆,并且它具有很强的扩展性(记忆网络自提出之后吸引了大量研究,出现了各式各样的变体和应用,如同现在的生成对抗网络一样火爆)。
那么如何将记忆网络应用在KB-QA中呢?
基于记忆网络的KB-QA
我们以Facebook AI Research的Bordes等人在2015年发表的论文Large-sacle Simple Question Answering with Memory Networks为例,介绍如何将记忆网络应用于KB-QA,该论文的作者Bordes也是我们在第四期中介绍的KB-QA向量建模方法经典论文的一作。
这篇论文初步尝试了将记忆网络应用于KB-QA中。作者认为现在的KB-QA对于解决只依赖一个知识三元组的简单问题(称为 Simple Question Answering)仍然有困难,为此作者构建了一个更大的简单问题数据集,称作SimpleQuestions。该数据集的每个问题都依据一个知识三元组知识,进行人工构建问题,数据集最终一共包含了108,442个问题-答案对,相比之前只含8000多个问题-答案对的benchmark数据集WebQuestion,其数据量大了很多。该数据集的部分数据如下图所示(下划线表示答案):
接下来我们看看作者如何使用记忆网络。其整体思想是将知识库里的知识存储到记忆模块M中,问题经过输入模块I转化为分布式表达,输出模块O选择与问题最相关的支撑记忆(由于SimpleQustions的问题只依赖一个知识,所以只需要选择一条记忆),回答模块R将该记忆对应三元组的宾语作为最终答案输出。最后,为了测试记忆网络的泛化能力,在模型训练完毕后,我们将Reverb中提取的三元组(我们在揭开知识库问答KB-QA的面纱2·语义解析篇中对Reverb作过介绍,它的知识三元组是自然语言形式,如(“Obama”, “was also born in”, “August1961”),知识三元组抽取自ClueWeb)作为新的知识,用泛化模块G将新知识存储到记忆模块中,在不经过re-training的情况下使用该记忆回答问题,测试模型的泛化性能。
具体来说,整体流程可以分为以下三步:
1.存储知识。
首先我们要将我们的知识库里的知识,存储到记忆网络中。作者使用Freebase的两个子集FB2M(含2M实体和5K实体关系)和FB5M(含5M实体和7K实体关系)分别作为知识库。使用输入模块I来处理数据。
由于一个问句可能有多个答案,并且对于一个问题输出模块O只选择一个支撑记忆,我们先对知识做两种预处理:
a.将具有相同主语和实体关系的三元组进行合并(Group),这样每一条知识将包含k个不同的宾语,即。合并的原因在于我们想用一条记忆回答具有多个答案的问题(我们将合并前的知识三元组称为Atomic Facts,合并后三元组的称为Facts),合并后和合并前的知识库大小如下:
b.去除中间节点。有些知识中日期会链接两个实体以区分某一事实的时间范围,我们可以将中间节点(mediator node)去除转化成一个二阶关系,这样我们就把长度为2的路径压缩成了长度为1的路径,即压缩为一个三元组。这个操作使得WebQuestion里的能被单一关系回答的问题数量从65%上升到86%。
预处理完知识后,我们的输入模块I对知识进行预处理并存储到记忆中。这里使用词袋模型bag-of-symbol的方法,用一个维的multi-hot向量来表示每一条知识并作为记忆。的大小为知识库实体和实体关系的大小之和,主语实体 和实体关系对应向量维的值为1,宾语实体对应维的值设为。
2.训练记忆网络。
我们用问题-答案对来训练记忆网络。
首先用输入模块I来处理输入的自然语言问句,我们使用n-gram词袋模型(bag-of-ngrams)方法,用一个维的multi-hot向量来表示每一个问句。的大小是字典大小,字典包含所有问题中出现的单词和所有知识库实体的自然语言别称(这个别称可能由多个单词构成,我们用1个n-gram来表示)。
对于输入,我们的输出模块O要在记忆中寻找一个与之最相关的支撑记忆。为了避免遍历整个记忆模块里的每一条知识,我们先确定一个候选范围。确定方式如下,将问句中的所有n-gram与知识库实体别称进行匹配,以确定候选实体,将含有候选实体作为主语的知识作为我们的候选支撑记忆。我们将记忆和问题投影到一个低维分布式空间,通过cosine相似度作为得分函数,来寻找最相关的支撑记忆,即:
这里我们需要学习的参数就是两个权值矩阵。和我在揭开知识库问答KB-QA的面纱4·向量建模篇(详情请关注公众号ChatbotMagazine,翻查公众号历史记录。)中提到的训练方法一样,我们构建margin-based ranking损失函数,也进行多任务的训练,通过多任务训练让语义相同的问题的分布式表达相似。这里不再赘述。
需要注意的是,我们知道构建margin-based ranking损失函数需要提供支撑记忆的正样本和负样本,由于SimpleQuestions数据集的每个问题都有对应的知识标签,因此我们已经有支撑记忆的正确标签。但是对于WebQuestion数据集,我们没有正确的支撑记忆标签,作者通过类似之前寻找候选支撑记忆的方式去得到标签。
训练完毕后,作者在WebQuestion和SimpleQuestions上做了测试,在WebQuestion上取得了42.2的F1-Score,在SimpleQuestion上正确率63.9%。作者发现如果仅用WebQuestion来训练模型,那么在SimQuestion测试集上正确率只有46.6%,说明了WebQuestion数据集的数据量还是具有一定的局限性。
3.测试网络泛化能力。
使用泛化模块G来连接新的知识库Reverb到我们的记忆中,通过实体链接和实体别名匹配等方式,来匹配已有记忆中的实体和新知识库里的实体(这种方式只能匹配到新知识库中17%的实体)。新知识库中剩下的实体和所有的关系都用词袋模型表示,因此我们可以用一个维的向量来表示新知识并将其存储到记忆中。同样的,输出模块在寻找支撑记忆时的相似度得分函数为:
其中矩阵直接由之前训练好的拼接(concatenate)而成。
我们将该新的知识库存储到记忆中,在不经过re-training的情况下用Reverb的一个测试集(含691个问题)进行测试,达到了67%的正确率,接近当时state-of-the-art的方法。
可以看出,该方法使用了一个很基础版本的记忆网络来解决简单问题的KB-QA。
小结
在这篇论文中我们可以看出,他使用的方法很简单,本质上和传统向量建模方法很接近。但是我们也可以看出,记忆网络这种结构具有的很强大的扩展性,它的每个模块都有很多改进的空间。总的来说,记忆网络是一种很适合进行KB-QA的深度学习框架,相信今后会有很多使用记忆网络进行KB-QA的优秀文章。
此外,个人认为使用更加复杂的记忆网络是未来深度学习解决KB-QA的一个很有前景的途径。记忆网络的框架给了我们很多的提升空间:引入更多的技巧,使用更合理的模型作为记忆网络的组件,在记忆选择中引入推理机制,注意力机制和遗忘机制,将多源的知识库存入记忆等等。
下一篇,我们将会介绍另一篇使用深度学习另一种经典模型——带注意力机制的循环神经网络(Recurrent Neural Networks with Attention Mechanism)进行KB-QA的文章。
- End -
ChatbotMagazine 是智言科技(深圳)有限公司旗下的一个技术分享栏目,智言科技是一家专注于基于知识图谱问答系统研发的 AI 公司。欢迎扫描二维码关注 ChatbotMagazine 公众号。
OpenKG.CN
中文开放知识图谱(简称OpenKG.CN)旨在促进中文知识图谱数据的开放与互联,促进知识图谱和语义技术的普及和广泛应用。
点击阅读原文,进入 OpenKG 博客。