Abstract
我们提出了TRANX,一个基于transition的神经语义解析器,将自然语言(NL)映射到formal meaning representation(MRs)。TRANX对目标MR使用了一个基于抽象语法描述语言的转换系统,这给了它两个主要的优势:(1)该方法具有较高的准确性,可以利用目标MR的语法信息来约束输出空间并对信息流进行建模;(2)该方法具有较高的泛化性,只需编写一个与目标MR中允许结构相对应的抽象语法描述,就可以很容易地应用于新的MR模型。在四个不同的语义解析和代码生成任务上的实验表明,与现有的神经语义解析器相比,我们的系统具有较强的通用性、可扩展性和有效性
Introduction
语义解析是将自然语言(NL)转换为formal meaning representation(MRs)的任务。目标MRs可以根据各种形式来定义。这包括语言动机语义表征,旨在捕捉任何句子的意义,如λ表达式或抽象意义表征。另外,对于更多的任务驱动的语义解析方法,通常是用意义表示来表示可执行程序,如SQL查询,机器人命令,智能手机指令,甚至通用编程语言,如Python和Java。
由于MRs的形式各不相同,语义解析器的设计,尤其是基于神经网络的语义解析器,通常集中在一小部分任务上——为了确保生成的MRs的语法格式良好,解析器(parser)通常被专门设计来在模型的结构中反映MRs的领域相关语法。为了缓解这一问题,人们最近在使用通用语法模型进行神经语义解析方面做出了一些努力。Yin和Neubig(2017)提出了一种序列到序列的模型,该模型使用一系列的树构建动作生成树形结构的MRs,并由提供给模型的任务特定的上下文无关语法进行先验指导。Rabinovich等人(2017)提出了抽象语法网络(abstract neural network),其中特定领域的MRs由抽象语法树(AST,图2左)表示,该树是在抽象语法描述语言(ASDL)框架下指定的。ASN采用模块化架构,为ASDL语法中的每个构造使用专门设计的神经网络生成AST。
受现有研究的启发,我们开发了TRANX,一个基于transition的抽象语法解析器,用于语义解析和代码生成。TRANX的设计遵循以下原则:
1.泛化性。TRANX将AST作为一种通用的中间意义表示,将依赖于任务的语法作为外部知识提供给系统来指导解析过程,从而将语义解析过程与语法的特殊性解耦。
2.拓展性。TRANX使用一个简单的转换系统将NL语句解析为树形结构的ast。转换系统被设计为易于扩展,需要最少的工程来适应需要处理额外领域特定信息的任务。
3.有效性。我们在四个语义解析(ATIS, GEO)和代码生成(DJANGO, WIKISQL)任务上测试了TRANX,并证明了TRANX能够泛化到不同的领域,同时表现出强大的性能,在四个数据集中的三个(GEO, ATIS, DJANGO)上优于现有的基于神经网络的方法。
Methodology
给定一个NL语句,TRANX将其解析为正式的含义表示,通常表示为λ演算逻辑式、领域特定(DSL)或通用编程语言(如Python)。在下面的描述中,我们使用Python代码生成作为一个运行示例,其中程序员的自然语言意图被映射到Python源代码。图1描绘了TRANX的工作流程。我们将在§3中介绍更多TRANX的使用案例。
TRANX的核心是一个transition system。给定一个输入的自然语言x, TRANX使用转换系统的一系列树构造动作将自然语言x映射到AST z(§2.2)。TRANX使用AST作为中间意义表示,对MRs的特定领域结构进行抽象。这个解析过程由用户定义的、在ASDL形式下指定的特定领域语法(§2.1)指导。给定生成的AST z,解析器调用用户定义的函数AST_to_MR(·),将中间AST转换为特定于领域的含义表示y,完成解析过程。TRANX使用一个由神经网络参数化的概率模型p(z|x)对每个假设AST进行评分(§2.3)。
Modeling ASTs using ASDL Grammar
TRANX使用AST作为MRs的通用、中间语义表示。AST通常用于表示编程语言,也可以用来表示其他树状结构的MRs(例如λ-calculus)。ASDL框架是定义ast的语法形式。
ASDL语法有两个基本组成: types和constructors。复合类型是由该类型下的构造函数集定义的。例如,图1中的stmt和expr复合类型分别引用Python语句和表达式,每个语句和表达式都由一系列构造函数定义。构造函数使用其字段指定特定类型的语言构造。例如,复合类型expr下的Call构造函数表示函数调用表达式,有三个字段:func、args和keywords。构造函数中的每个字段也是强类型的,它指定字段可以保存的值的类型。具有复合类型的字段可以由相同类型的构造函数实例化。例如,上面的func字段可以保存expr类型的构造函数。还有一些具有基本类型的字段,用于存储值。例如,Name构造函数的id字段有一个原始类型标识符,用于存储标识符名称。而Str (string)构造函数中的字段s保存字符串字面值。最后,每个字段(field)都有一个基数(single, optional ? and sequential ∗),表示该字段保存的值的数量。
然后,一个AST由多个构造函数组成,树上的每个节点对应于构造函数(constructors)中的一个类型(typed)字段(根节点除外,根节点表示根构造函数)。根据字段的基数,节点可以保存一个或多个构造函数作为其值。例如,图1中ASDL语法中具有单一基数的func字段用一个Name构造函数实例化,而具有序列基数的args字段有多个子构造函数。
Transition System
受Yin和Neubig(2017)(以下简称YN17)的启发(这不就是你们自己吗) ,我们开发了一个转换系统,将AST的生成过程分解为一系列的树构造动作。现在,我们使用正在运行的示例来解释转换系统。图2右侧列出了构造示例AST的动作序列。在高层,生成过程从一个具有单个根节点的初始派生AST开始,按照自上而下,从左到右的顺序遍历该AST。在每个时间步中,会触发以下三种动作之一来扩展派生的开放frontier field nftn_{ft}nft:
APPLYCONSTR[c] 动作将构造函数c应用到与c类型相同的复合开放边界字段(opening composite frontier field),使用c中的字段填充开放节点。如果frontier field具有顺序基数,动作将该构造函数附加到该字段持有的构造函数列表中。
(其实这就相当于一个给字段复制构造初值的过程)
REDUCE 动作标志着具有optical(?)或multiple(∗)基数的字段的子值生成完成。
GENTOKEN[v] 动作用一个令牌v填充一个(空的)原始边界字段。例如,图2上的字段f7具有类型:identifier,并使用单个GENTOKEN动作实例化。对于string类型的字段,比如f8,它的值可以由多个令牌组成(这里只显示一个),可以使用一系列GENTOKEN操作填充它,并使用一个特殊的GENTOKEN[< /f>]操作终止token的生成。
一旦衍生上没有前沿域(frontier field),生成就完成了。然后TRANX调用用户指定的函数AST_to_MR(·),将生成的中间AST z转换为目标领域特定的MR y。TRANX提供各种辅助函数,以简化编写转换函数的过程。例如,将AST转换为Python源代码的示例转换函数只包含32行代码。TRANX还附带了几个内置的转换函数,用于处理语义解析和代码生成中常用的MRs,比如λ演算逻辑形式和SQL查询。
Computing Action Probabilities p(z∣x)p(z|x)p(z∣x)
给定转换系统,z的概率被分解为用于生成z的动作序列的概率:
p(z∣x)=∏tp(at∣a<t,x)p(z|x) = ∏_t p(a_t|a_{<t}, x)p(z∣x)=t∏p(at∣a<t,x)
在YN17之后,我们使用一个具有增强循环连接的神经编码器-解码器网络来参数化基于转换的解析器p(z|x),以反映AST的拓扑结构。
Encoder
该编码器是一个标准的双向长短期记忆(LSTM)网络,将n个令token的输入话语x, x[1..n]x_{[1..n]}x[1..n]编码为向量表示h[1..n]h_{[1..n]}h[1..n]。
Decoder
解码器也是一个LSTM网络,在每个时间步,其隐藏状态sts_tst由下式给出:
st=fLSTM([at−1:st−1∼:pt],st−1)s_t = f_{LSTM}([a_{t−1} : s^{\sim}_{t−1} : p_t], s_{t−1})st=fLSTM([at−1:st−1∼:pt],st−1)
[:] 表示向量连接,at−1a_{t−1}at−1是上一时间步的action embedding,我们会为每个action维护一个embedding action,st∼s^{\sim}_tst∼是注意向量,定义如下:
st∼=tanh(Wc[ct:st]).s^{\sim}_t = tanh(W_c[c_t : s_t]).st∼=tanh(Wc[ct:st]).
其中ctc_tct是使用注意力机制从输入编码h[1..n]h_{[1..n]}h[1..n]检索到的上下文向量。
Parent Feeding
ptp_tpt编码了派生过程中parent frontier field nftn_{ft}nft的信息。它是两个向量的拼接:边界域nftn_{ft}nft的embedding,以及APPLYCONSTR动作生成nftn_{ft}nft构造函数时的解码器状态spts_{pt}spt。Parent Feeding输入反映了树状结构的AST的拓扑结构,并在生成复杂的MRs(如Python代码)时提供了更好的性能(§3)。
Action Probabilities
已有了embedding ∗∗ac∗∗**a_c**∗∗ac∗∗,生成APPLYCONSTR[c]动作的概率可由下式计算:
对于GENTOKEN操作,我们采用了生成和复制的混合方法,允许在x中超出词汇表(oov)的变量名称和字面量(例如,图1中的“file.csv”)直接复制到派生中。具体来说,action概率被定义为边际概率
二进制概率p(gen|·)和p(copy|·)由softmax(W~st)softmax(W̃_{st})softmax(W~st)给出。闭集词汇表p(v|gen,·)生成v的概率定义类似于Eq.(1)。复制x中第i个单词的复制概率定义为使用指针网络
Experiment
Semantic parsing数据集:GEO和ATIS
Code Generation数据集:Django 和wikiSQL
作者在针对wikiSQL数据集上的任务做了一些额外的改进:
为了获得更强的结果,现有的解析器和表3中的大多数模型一样,使用专门设计的架构来反映SQL查询的语法结构。我们展示了TRANX所使用的转换系统可以很容易地扩展为WIKISQL,并且只需要很少的工程,同时拥有强大的性能。首先,我们按照SQL的语法定义了一个简单的ASDL语法(图4)。然后,我们用一个特殊的GENTOKEN动作SELCOLUMN[k]来增强转换系统。SELCOLUMN[k]动作用于通过选择表中的第k列来填充语法中的Select和Condition构造函数中的原始列idx字段。为了计算SELCOLUMN[k]操作的概率,我们在列编码上使用指针网络,其中列编码是通过一个双向LSTM网络根据输入表中的列名给出的。这可以通过在TRANX中重写基本Parser类并修改计算操作概率的函数来简单实现。
Result
表3显示了在WIKISQL上的结果。我们首先讨论我们的标准模型,该模型在推断过程中只使用列名信息,而不使用输入表的内容,如表3中最上面的两个块所示。我们发现,TRANX虽然只是通过简单的扩展来适应这个数据集,但却取得了令人印象深刻的结果,并优于许多特定于任务的方法。这表明TRANX很容易扩展,以合并特定于任务的信息,同时保持其有效性。我们还使用一个非常简单的答案剪枝策略来扩展TRANX,在这个策略中,**我们在beam中针对输入表执行候选SQL查询,并修剪那些产生空执行结果的查询。**结果列在表3底部的两个块中,在这里我们将与同样使用表内容的系统进行比较。令人惊讶的是,这个(令人沮丧的)简单扩展产生了显著的改进,性能超过了许多使用专门设计的、精心设计的神经网络来合并表内容信息的特定任务模型。