记忆网络(译)

笔者:本文为英文论文的翻译文章,供机器学习、深度学习相关学者参考,若有错误理解之处请指出,不胜感激!(如需转载,请联系本人:jtianwen2014,并注明出处)。api

记忆网络(译)

Jason Weston, Sumit Chopra & Antoine Bordes.数组

Facebook AI Research, 770 Broadway, New York, USA.网络

{jase,spchopra,abordes}@fb.com架构

摘要

本文将介绍一种新的学习模型,称为记忆网络。记忆网络利用结合了长期记忆模块的推断组件进行推理;并学习如何联合地使用它们。长期记忆模块被用做预测,能够读出也能够写入。咱们将记忆网络用于问答任务,长期记忆模块扮演着知识库的角色,记忆网络的输出是文本回复。咱们在一个大规模的问答任务上,以及一个从仿真的世界里生成的小规模可是足够复杂的玩具任务(toy task)上进行评测。在本文的末尾,咱们经过链乘支持语句到须要理解动词意图的问答来展现这写模型的推理能力。框架

1 概述

大多数机器学习模型缺少一种简单的方式从长期记忆模块中读取或写入,并没有缝地结合到推理中。因此,这些方法并无利用现代计算机的卓越的优点之一。举个例子,考虑一个任务,给定一些事实或者故事的集合,而后须要回答相关的问题。理论上这个任务能够经过语言模型来完成,好比循环神经网络(RNN)(Mikolov et al., 2010; Hochreiter & Schmidhuber, 1997) ,由于这些模型被训练得能够对于给定的单词流预测出下一个(或多个)可能的单词(或单词集合)。然而,它们的内存(编码在隐状态和权值)通常很小,并不能准确地记住过去的事实(导致被压缩到稠密的向量中)。众所周知,RNNs很难执行记忆操做,好比简单的拷贝任务即输出刚刚读到的输入(Zaremba & Sutskever, 2014)。一样的情形发生在其余的任务上,好比,在视频和音频领域,观看影片须要长期记忆以回答关于这个影片的问题。机器学习

在本文的工做中,咱们介绍一种叫作记忆网络的模型,尝试修复以上提到的问题。核心思想就是将在机器学习中用于推理的有效学习策略和能够读写的内存模块相结合。而后训练模型,使之能够高效的操做内存内存模块。咱们在第2部分介绍总体的框架,在第3部分相你们展现在文本问答领域的具体实现。咱们在第4部分讨论相关工做,而后再第5部分介绍实验部分,最后在第6部分做出总结。函数

2 记忆网络

一个记忆网络由1个内存模块\(\mathbf{m}\)(用\(m_i\)索引的数组)和以下的4个(经过学习获得的)模块\(I,G,O,R\)学习

\(\mathbf{I}\):(输入特征映射)—— 将输入转换为内部特征表示。测试

\(\mathbf{G}\):(泛化)—— 对于给定新的输入更新旧的内存。咱们称之为泛化是由于在这个阶段网络有机会压缩并泛化其内存以供将来某些须要。优化

\(\mathbf{O}\):(输出特征映射)—— 给定新的输入与当前的内存状态,产生新的输出(在特征空间中)。

\(\mathbf{R}\):(回复)—— 将输出转换为特定格式的回复。好比,文本回复或者一个动做。

给定输入\(x\)(好比,一个输入字符,单词或者句子,这依赖于粒度的选择,一幅图片或者一段音频信号),模型执行以下的流程:

  1. \(x\)转换为内部特征表示\(I(x)\)
  2. 对于给定的新的输入,更新内存\(\mathbf{m}_i\)\(\mathbf{m}_i=G(\mathbf{m}_i,I(x),\mathbf{m}),\forall i\)
  3. 对于给定的新的输入和内存,计算输出特征\(o\)\(o=O(I(x),\mathbf{m})\)
  4. 最后,将输出\(o\)解码为最后的回复:\(r=R(o)\)

训练和测试阶段都须要这个过程,这两个阶段的差异在于测试阶段不更新\(I,G,O,R\)的参数。记忆网络能够用于不少任务。其组件\(I,G,O,R\)可使用不少目前存在的机器学习策略,如,SVMs、决策树、等等。

\(I\)组件:组件\(I\)能够利用一些通用的预处理过程,如,为文本输入进行句法分析、指代和实体消解。它也能够将输入编码到一个内部特征表示,好比,将文本转换到稀疏或稠密的特征向量。

\(G\)组件:\(G\)最简单的形式是将\(I(x)\)存储在内存的‘槽’中:

\[ \mathbf{m}_H(x) = I(x) \tag{1} \]

其中\(H(.)\)是槽选择函数。也就是,\(G\)只更新内存\(\mathbf{m}\)中索引为\(H(x)\)的部分,而不去触碰其余部分。\(G\)的更复杂的变种能够基于当前输入\(x\)所获的的信息来回退并更新早期存储的内存(或者所有内存)。若是输入是字符级别或者能够词级别,那么能够将其进行分组(也就是,将其分块化)并将每块存储到一个内存槽中。

若是须要的内存巨大(好比,对于Freebase或者Wikidata),那么咱们须要对其进行组织。这能够经过以前介绍的槽选择函数来实现:好比,能够对其设计或者训练使之能够按照实体或者主题存储记忆。所以,为了提升扩展的效率,\(G\)(以及\(O\))不须要在全部内存上进行操做:能够只对检索到的候选子集进行操做(只在相关主题的记忆上进行操做)。咱们将在后续的实验中介绍一个简单的变种。

若是内存满了,\(H\)能够经过选择替换哪一个内存来进行“忘记”处理,好比,\(H\)能够对每一个记忆的价值进行打分,覆盖掉最没有价值的部分。咱们还未开展这个实验。

\(O\)\(R\)组件:组件\(O\)一般负责从内存中读取并执行推理,好比,计算哪一个是能够得到优质回复的相关内存。组件\(R\)对于给定的\(O\)产生最后的回复。举个例子,在问答任务上,阶段\(O\)找到相关的内存,而后由\(R\)产生实际的回答词语,好比\(R\)多是个以\(O\)为输入的RNN。咱们的假设是,若是没有这些记忆做为条件,这样的RNN没法很好执行。

3 为文本实现记忆网络

有一种特别的记忆网络,其组件都是神经网络。咱们称其为记忆神经网络。在本节中,咱们描述具备文本输入和输出的记忆神经网络的一个相对简单实现。

3.1 基础模型

在基础架构中,\(I\)模块以文本为输入。咱们首先假设这是一个句子:也能够是一个事实的陈述,或者须要系统回答的问题(稍后咱们基于单词的输入序列)。这个文本以原始的形式存储在下一个可用的内存槽中,也就是\(S(x)\)返回下一个空的内存槽\(N\)\(\mathbf{m}_N=x,N=N+1\)\(G\)模块只用来存储这个新的记忆,旧的内存不被更新。更加复杂的模型将在后续的章节中叙述。

推理的核心模块位于\(O\)\(R\)模块。对于给定\(x\),模块\(O\)经过查找\(k\)个支持记忆来产生输出特征。咱们将\(k\)设为2,可是这个过程适用于更大的\(k\)。对于\(k=1\),经过以下方式检索出得分最高的支持记忆:

\[ o_1 = O_1(x,\mathbf{m})=\mathop{\arg\max}_{i=1,\cdots,N}s_O(x,\mathbf{m}_i) \tag{2} \]

其中,\(s_O\)\(x\)\(\mathbf{m}_i\)的匹配程度进行打分的函数。对于\(k=2\),咱们能够利用迭代的方式发现第二个支持记忆:

\[ o_2 = O_2(x,\mathbf{m})=\mathop{\arg\max}_{i=1,\cdots,N}s_O([x,\mathbf{m}_{o_1}],\mathbf{m}_i) \tag{3} \]

其中候选支持记忆\(\mathbf{m}_i\)如今须要基于初始输入和第一个支持记忆经过打分,方括号表明列表。最终的输出\(o\)\([x,\mathbf{m}_{o_1},\mathbf{m}_{o_2}]\),做为模块\(R\)的输入。

最后,\(R\)须要产生一个文本回复\(r\)。最简单的回复就是返回\(\mathbf{m}_{o_k}\),也就是输出刚刚检索到的句子。为了进行真实语句的生成,能够利用RNN来代替。在咱们的实验中,咱们也考虑使用一种简单的方式来评估方法,即咱们经过排序的方式将文本回复限定为一个单词:

\[ r=\mathrm{argmax}_{w\in W}s_R([x,\mathbf{m}_{o_1},\mathbf{m}_{o_2}],w) \tag{4} \]

其中\(W\)是字典中全部单词的集合,\(s_R\)是对匹配进行打分的函数。

图1给出了一个任务的例子。将来回答问题\(x=\)“Where is the milk now?”,模块\(O\)须要首先对全部内存进行打分,也就是全部以前见过的语句,以\(x\)为背景进行检索最相关的事实,在这个例子中\(\mathbf{m}_{o_1}=\)“Joe left the milk”。而后在给定\([x,\mathbf{m}_{o_1}]\)的状况下,再一次搜索第二个相关事实,也就是\(\mathbf{m}_{o_2}=\)“Joe travelled to the office”(在Joe放下牛奶以前去过的最后一个地方)。最后,模块\(R\)对给定的\([x,\mathbf{m}_{o_1},\mathbf{m}_{o_2}]\)利用公式(4)对单词进行打分,输出\(r=\)“office”。

图 1:

在咱们的实验中,打分函数\(s_O\)\(s_R\)具备相同的形式,一个嵌入表示模型:

\[ s(x,y) = \Phi_x(x)^{\top}U^{\top}U\Phi_y(y) \tag{5} \]

其中,\(U\)是一个\(n\times D\)矩阵,\(D\)是特征的数量以及\(n\)是嵌入表示的维度。\(\Phi_x\)\(\Phi_y\)是用于将原始文本映射到\(D\)维的特征空间里。特征空间最简单的选择是词袋表示,对于\(s_O\)咱们选择\(D=3|W|\),也就是词典中的每一个单词有三个不一样的表示:一个用于\(\Phi_y(.)\),另外两个用于\(\Phi_x(.)\),依赖于输入的单词来自于实际输入\(x\)仍是支持记忆,以使得它们能够不一样建模。相似地,对于\(s_R\)也使用\(D=3|W|\)。这两个打分函数使用不一样的矩阵\(U_O\)\(U_R\)

训练 咱们在彻底有监督的设置下训练,在训练数据中给定应有的输入和回答,以及被标记的支持这个回答的句子(但在测试集中只有输入)。也就是在训练时咱们知道eq.(2)和eq.(3)的最佳选择。训练使用一个边际排序损失和随机梯度降低(SGD)来进行。更确切点说,对于给定真实回复\(r\)的问题\(x\),以及支持的语句\(\mathbf{m}_{o_1},\mathbf{m}_{o_2}\)(当\(k=2\)时),咱们在参数\(U_O\)\(U_R\)之上优化模型:

\[ \sum_{\overline{f}\ne \mathbf{m}_{o_1}}\mathrm{max}(0, \gamma-s_O(x,\mathbf{m}_{o_1})+s_O(x,\overline{f}))+ \tag{6} \]

\[ \sum_{\overline{f'}\ne \mathbf{m}_{o_2}}\mathrm{max}(0, \gamma-s_O([x,\mathbf{m}_{o_1}], \mathbf{m}_{o_2})+s_O([x,\mathbf{m}_{o_1}],\overline{f'}))+ \tag{7} \]

\[ \sum_{\overline{r}\ne r}\mathrm{max}(0, \gamma-s_R([x,\mathbf{m}_{o_1}, \mathbf{m}_{o_2}], r)+s_O([x,\mathbf{m}_{o_1}, \mathbf{m}_{o_2}], \overline{r}))+ \tag{8} \]

其中\(\overline{f},\overline{f'}\)以及\(\overline{r}\)都是非正确的标签选择,是\(\gamma\)边际。在SGD的每一步,咱们采样选取\(\overline{f},\overline{f'},\overline{r}\)而不是为每一个训练样例计算全部的总和,这和Weston et al.(2011)的作法相同。

当咱们使用RNN来实现记忆神经网络的\(R\)模块时(而不是像上面那样用单词回复),咱们将最后一项替换为语言建模任务中使用的标准对数似然函数,其中RNN的输入是序列\([x,o_1,o_2,r]\)。在测试的时候,在给定\([x,o_1,o_2]\)的状况下输出\(r\)。对比最简单的模型,即便用\(k=1\)而且输出\(\mathbf{m}_{o_1}\)的记忆做为回复\(r\),将只使用第一项用来训练。

接下来的部分,咱们将考察一些基于基础模型的扩展。

3.2 词序列做为输入

若是输入是词而非句子级别,即词以流的形式到达(就像RNN常常处理的那样)而且陈述和问题都没有进行词分割,咱们须要修改下以前描述的方法。因此咱们加入“分割”函数,将会经过学习获得,输入单词的最后没有分割的序列以寻找分割点。当分割器触发时(指示当前序列时分割段)咱们将序列写入内存,而后就能够像之前同样处理。这个分割器的建模方式和咱们其余的模块相似,以嵌入表示模型的形式:

\[ seg(c) = W^{\top}_{seg}U_S\Phi_{seg}(c) \tag{9} \]

其中\(W_{seg}\)是一个向量(其实是嵌入空间里的线性分类器的参数),\(c\)是用词袋表示的词序列。若是\(seg(c)>\gamma\),其中\(\gamma\)是边际,那么这个序列被视为一个分割。经过这种方式,咱们的记忆神经网络在写操做时拥有一个学习模块。咱们将这个分割器视为第一个概念证实:固然,能够设计得更加复杂。训练时进一步的细节将在附录B中展示。

3.3 利用散列表的高效记忆

若是存储的记忆集合十分庞大,那么eq.2和eq.3中对全部记忆进行打分的代价将十分巨大。咱们使用散列的技巧来加速查找:将输入\(I(x)\)散列到一个或多个桶中,而后只对相同桶里的记忆\(\mathbf{m}_i\)进行打分。咱们考察两种散列的方式:(i)散列词语;以及(ii)对词嵌入表示进行聚类。对于方法(i)咱们构造和词典中词语数量相同的桶,而后对于给定的语句咱们将其散列到所包含词语的对应的桶中。(i)的问题在于记忆\(\mathbf{m}_i\)只有当和\(I(x)\)至少一个相同的词语时才被考虑。方法(ii)试图经过聚类解决这个问题。在训练嵌入式矩阵\(U_O\)以后,咱们使用K-近邻进行聚类词向量\((U_O)_i\),因此给出了K个桶。而后咱们将语句散列到全部包含词语落入的桶中。由于词向量会和其同义词相接近从而彼此聚类到一块儿,因此咱们将会对这些类似的记忆进行打分。输入和记忆之间匹配的词语都会按照定义被打分。选择\(K\)控制速度准确权衡。

3.4 建模写入时间

咱们能够将什么时候一个内存被写入加入到咱们的模型中。这对于回答固定事实的问题(“What is the capital of France?”)并不重要,但当回答一个如图1的故事相关的问题时倒是重要的。对于给定的\(\mathbf{m}_j\),实现这个的一种明显方式就是向表示\(\Phi_x\)\(\Phi_y\)中加入编码\(j\)的额外特征,假设\(j\)遵循写时间(也就是,没有内存槽被重写)。然而,须要处理的事绝对时间而非相对时间。咱们对如下过程有着更多的成功经验:代替打分输入,候选对利用上述的\(s\)学习一个定义在三元组上的函数\(s_{O_t}(x,y,y')\)

\[ s_{O_t}(x,y,y') = \Phi_x(x)^{\top}U_{O_t}^{\top}U_{O_t}(\Phi_y(y)-\Phi_y(y')+\Phi_t(x,y,y')) \tag{10} \]

\(\Phi_t(x,y,y')\)使用三个新的特征,取值0或1:是否\(x\)\(y\)更加久,\(x\)\(y‘\)更加久,\(y\)\(y’\)更加久。(也就是,咱们将全部的\(\Phi\)维度扩展3位,若是不适用的时候都设置位0)如今,若是\(\Phi_t(x,y,y')>0\),模型更偏于选择\(y\),若是\(\Phi_t(x,y,y')<0\),模型更偏于选择\(y'\)。eq.2和eq.3中的argmax替换为在\(i=1,\cdots,N\)的循环,在每步中持续赢取内存记忆(\(y\)或者\(y'\)),即老是比较当前赢得的内存和下一个内存\(\mathbf{m}_i\)。若是把时间特征移走,这个过程等价于以前的argmax。更多的细节将在附录C中讨论。

3.5 建模生词

即便对于阅读量很大的人类来讲,生词也是常常遇到。好比指环王中的单词“Boromir”。一个机器学习模型如何来处理这个问题?一个可能的方式是使用语言模型:经过生词周围的词语,来预测可能的单词,并假设这个生词和预测的单词语义类似。咱们提出的方法正是采用这个想法,可是咱们将其融入到咱们的网络\(s_O\)\(s_R\)而不是做为一个单独的步骤。

具体地,对于咱们看到的单词,咱们将其周围词保存在词袋中,一个词袋保存左侧的词语,另外一个保存右侧的词语。任何未知的词语均可以这样表示。因此咱们将特征表示\(D\)\(3|W|\)扩展到\(5|W|\)来对这些上下文进行建模(每一个词袋有\(|W|\)个特征)。咱们的模型在训练阶段使用一种“dropout”技术来处理新的单词:\(d\%\)的时间咱们装做从未读取过任何词语,不使用\(n\)维嵌入表示这个词语,而是用它的上下文来代替。

3.6 精准匹配和生词

因为低维度\(n\)嵌入式模型没法进行精准的词汇匹配。一个解决方案是对词对\(x,y\)进行以下打分来替代以前的:

\[ \Phi_x(x)^{\top}U^{\top}U\Phi_y(y) + \lambda\Phi_x(x)^{\top}\Phi_y(y) \tag{11} \]

也就是,向学习到的嵌入式分数加入“词袋”的匹配(使用一个混合参数\lambda)。另外一个,相关的方法仍是在这个\(n-\)维的嵌入式空间里,可是为特征表示\(D\)扩展更多的匹配特征,好比,一个词汇。一个匹配的特征意味着这个词在\(x\)\(y\)中都有出现。也就是,咱们使用\(\Phi_x(x)^{\top}U^{\top}U\Phi_y(y,x)\)进行打分,其中\(\Phi_y\)实际创建在\(x\)基础上:若是\(y\)中的词语与\(x\)中的一次匹配,咱们就将这些匹配特征设置为1。未登陆词可使用类似的方法建模,在上下文词汇中使用匹配特征。最后,\(D=8|W|\)

相关文章
相关标签/搜索