当前位置: 首页 > 科技观察

基于语法的结构化CNN解码器

时间:2023-03-18 12:15:23 科技观察

代码生成摘要代码生成将程序描述映射到可执行编程语言中的源代码。现有方法主要依赖递归神经网络(RNN)编码器。然而,我们发现一个程序包含的标记比自然语言句子多得多,因此RNN可能不适合捕获这么长的序列。在本文中,我们提出了一种基于句法的结构化卷积,用于传统神经网络(CNN)中的代码生成。我们的模型通过预测语法规则生成过程编程语言;我们设计了多个CNN模块,包括基于树的卷积和预卷积,其信息将由专门的参与者-主动池化层进一步聚合。在《炉石传说》基准数据集上的实验结果表明,我们的CNN代码生成器明显优于之前的最先进方法5个百分点;对几个语义解析任务的额外实验证明了我们模型的稳健性。我们还进行了深入的消融测试,以更好地了解每个模型的组件。从自然语言描述中生成代码是人工智能中一项艰巨而艰巨的任务。对于var应用程序。例如,一个程序员想在Python中“打开一个文件,F1”,但不知道如何在编程语言中执行,他可以得到目标代码“f=open('F1','r')“通过代码生成。随着深度学习的蓬勃发展,编解码器框架成为序列生成方法的流行联盟。特别是,递归神经网络(RNN)经常用作编码器和解码器;此类架构师也称为序列到序列(Seq2Seq)模型。当应用于代码生成时,它将程序描述作为输入放置序列,并生成所需代码作为输出序列。在深度学习社区中,研究人员对使用卷积神经网络(CNN)作为解码器表现出越来越大的兴趣,因为它们效率高且易于训练。我们进一步观察到程序比自然语言句子大,而RNN甚至具有长短期记忆。相比之下,CNN能够通过滑动窗口区域有效地捕获不同位置的特征。为此,我们提出了一种用于代码生成的基于语法的结构化CNN。我们的模型通过AST中的语法构造规则遵循我们之前的框架工作,例如If→exprstmtstmt。由于子节点的顺序是由单个预测步骤生成的,因此与逐个令牌生成相比,它可以实现更多的合约预测。换句话说,我们的模型预测最终形成完整程序的语法规则序列。在我们的方法中,语法规则的预测主要基于三种类型的信息:先前预测的指定要生成的程序的语法规则的频率,以及已经生成的AST部分。在这里,前一个是编码器。后两者使模型能够自回归解码器,并且像往常一样,解码器也依赖于编码器。我们为适合程序生成的CNN的结构设计了几种不同的组件:(1)我们首先采用基于树的卷积的思想,在AST结构上应用滑动窗口。然后我们设计另一个CNN模块来遍历部分AST中的节点。这两个CNN捕获邻居——不仅在序列中,而且在信息结构树中。(2)为了增强“自回归”,我们将-anotherCNN模块应用于要生成的节点的祖先安装,因此网络知道在某个步骤生成的位置。(3)我们设计了一个attentivepooling来聚合具有不同机制的神经模块,以便与CNN交互。特别是,我们发现在代码生成期间考虑作用域名称(例如,函数和方法名称)很有用,使用诸如几个仔细的池化层之类的控制程序。我们在数据集《炉石传说》上进行实验,以根据已建立的基准生成python代码。实验结果表明,我们基于CNN的代码生成器大大优于以前的RNN方法。我们在两个Mantic解析任务上进一步评估我们的方法,其中目标程序比《炉石传说》短;我们的方法还实现了与以前最先进的方法一致的可比较结果,表明我们方法的稳健性。我们进行了广泛的消融测试,表明我们基于语法的架构设计CNN优于纯CNN。模型图2显示了我们网络的整体结构。我们首先描述基于语法的代码生成过程,然后详细描述每个模块。基于语法的代码生成对于程序描述的输入,我们的任务是生成一段符合描述的可执行代码。在传统的Seq2Seq模型中,一个程序可以表示为一个token序列x1,x2,...,xT,这些token是顺序生成的。或者,高效的程序可以使用抽象语法树(AST)。叶节点是表示为x,x1,x2,...的终端的符号。..,xT。非叶节点是非终结符n1,,nN,每个代表程序的一个抽象组件(例如,一个If块)。此外,从其父节点p派生的子节点n1,···,nk是通过应用一些文法规则r得到的,表示为p→n1···nk。在我们的工作中,通过检查训练集来确定规则,将不同的叶节点用户定义变量视为单独的语法。我们以深度优先的顺序遍历树,对于首先遇到的非终结符,我们预测应该使用什么规则来扩展它。换句话说,概率程序的分解是,虽然典型的编程语言比不同的AST节点包含更多的语法规则,但基于语法的生成更紧凑,因为子节点c1,...,ck是由单个预测形成的规则就地p→c1···ck。此外,生成的程序保证语法正确。在本节的其余部分,我们将介绍用于预测语法规则的CNN编码器-解码器模型。输入CNN我们模型的输入是指定要生成的程序的描述。卡片的代码生成在《炉石传说》,输入是半结构化数据,包含图4所示卡片的名称、属性和描述。对于其他任务,如语义解析,输入可能是自然量词句.形式上,可以计算提取的特征,其中W(enc,l)是编码器的卷积权重CNN,s由s=(k?1)/2计算,k是窗口大小(在我们的实验中设置)为2),l=1,···,L代表CNN的深层。特别是y(enc,0)是输入嵌入x(enc)。c(enc,l)=1表示偶数层,0表示奇数层,表示是否有下面的shortcut连接这一层。对于第一个和最后一个词,我们执行零填充。CNNforpredictionrules我们跟踪所有以前的规则并构建一个深度神经网络来提取此类信息。令r1,...,rn-1为先前预测的规则。我们将它们嵌入为实值向量r1,...,rn-1,其中嵌入是随机初始化的,可以通过反向学习传播。我们应用具有快捷连接的深度CNN模块常规嵌入r1,...,rn-1注释来提取特征y。预测的语法规则以紧凑的方式完整地指定生成的(部分)程序,这有利于准确的代码生成。然而,只有预先指定的自回归规则提供给解码器,因为它们不提供程序的具体/图片视图。为了缓解这个问题,我们增强了解码器部分AST,如下所述。AST的部分CNN我们设计了一个深度CNN模块来捕获AST的结构、文化信息。它包含基于树的卷积层、预遍历遍历卷积层和一个树路径CNN子模块,该子模块通知网络下一个语法规则将应用到哪里。基于树的CNN。我们首先将基于树的CNN应用于部分AST。主要思想是设计一个固定深度的局部特征检测器在树上滑动来提取结构特征。基于树的CNN的输入是具有以下内容的部分AST:一旦生成,每个节点都由一个嵌入表示。我们还放置了一个占位符节点来指示在何处应用下一个语法规则。假设节点n有一个父节点p和一个祖先节点g。然后可以计算基于树的CNN提取的特征,其中W(ast)是基于树的卷积ker-nell。我们用特殊标记填充图层,前两个节点没有父节点和/或祖父母节点。基于树的卷积,因为我们有更深的窗口,但不考虑兄弟信息。这是因为我们的语法-基于世代的人通过应用一次获得所有兄弟姐妹-遵循某些规则,所以兄弟姐妹不那么重要-比祖先更坦率。不幸的是,深度呈指数增长,同时深度变小且易于处理,而我们基于树的CNN变体早期呈线性增长。在卷积计算方面,我们使用类似感知器的交互。可以探索基于深度树(例如ResNet)的卷积和快捷连接作为未来的工作。CNN的预序遍历。获得一组由基于树的CNN提取的向量,我们应用与预输入y(ast)的遍历卷积。也就是说,AST节点处于遍历前顺序。可以证明,简单的预遍历对于树结构是不可逆的,即不同的树结构可能产生相同的序列。为了解决这个问题,我们在预序遍历期间跟踪回溯。T是AST中的节点数,带有回溯的预遍历产生2S个输入单元。请注意,基于树的CNN和顺序遍历CNN捕获不同的信息。前序遍历产生的顺序解决了AST节点在顺序邻居生成过程中的问题,而基于树的卷积为结构上相邻的节点提供了信息融合。例如,在图3中,节点n4是n2的子节点。但是,程序的其他部分(即n3和n6)生成后,节点n2和n4不再相互靠近。基于树的卷积直接为节点及其祖先的交互构建特征提取器。因此,我们认为这两种类型的CNN是相辅相成的。树径CNN。我们应该只考虑上面的CNN,它很难告诉在哪里应用下一个语法规则。例如,如果我们在图3中展开n4或n5,基于树的CNN和预遍历CNN会产生非常相似的特征,尽管我们为预遍历CNN引入了占位符。从技术上讲,如果我们遵循最左边的推导,那么在何处应用下一条规则是明确的。但是这样的线索太含蓄了,应该更明确地建模。所以我们提取了d中从根到结点的路径比如我们要展开n4,路径应该是n1,n2,n4。我们称之为树路径卷积。集成和注意CNN提取一组相同大小或形状的特征输入。为了促进代码生成的softmax预测,我们需要将信息聚合到一个或几个固定大小的向量中,与输入大小无关。传统上,人们对CNN和基于树的CNN使用顶部池化。然而,这使得底层的CNN模块在信息聚合过程中相互分离,无法通信。因此,我们结合了CNN的注意力池机制。本质上,注意力机制计算候选集的加权和函数(由CNN提取),其中权重由控制向量放置(例如,最大池化另一个CNN模块的向量)。形式上,给定控制向量c和一组候选卷积特征y1,...,yD通过CNN模块(D是特征向量的数量)。将这样一个仔细的池化层应用于我们的底层CNN,我们将一些关键信息视为控制向量。(1)输入描述指定程序生成,然后用于控制文法规则CNN和树路径CNN。特别是,我们应用最大池化层将输入的CNN特征聚合为固定大小的控制向量,用于计算权重和预测注意力树路径CNN的语法规则。(2)我们注意到作用域名称(即函数名称或方法名称)提供了有关其后代的启发性信息。此类信息不会被AST节点类型捕获,因此我们将作用域名称嵌入为一个向量,并用它来控制预遍历CNN和输入CNN。需要注意的是,如果当前程序段在两个或多个范围内(一个函数和一个方法),我们只将最近的范围视为拖动向量。如果代码段不属于任何函数或类,则将范围嵌入设置为零向量。除了针对基于树的层次结构之外,另一个最大池化层应用于保留遍历CNN特征。我们的经验发现,这是因为控制域中的嵌入也达到了相应AST节点的注意力峰值,??摘要信息不足。除了控制向量,另一个最大池信息层也可以保留更多信息。我们还注意到注意力机制设计选择及其影响在具有多个神经网络的深度神经网络中拖动连接模块。例如,我们最好按照以下控制原则使用CNN将所有其他模块的输入放入编码器-解码器框架中。然而,我们的初步实验表明,这样的设计会产生较低的性能,因此我们采用了当前的架构。训练和推理我们将所有最大池和激活池层连接在一起。它们被送入两层感知器,最后一层具有预测下一个语法规则的softmax激活函数。我们的模型是针对地面程序通过的。由于我们的整个模型可靠性不同,所有参数都是通过基于梯度的更新来学习的。为了进行推理,我们寻找一组语法规则来最大化以输入为条件的概率。递归如果规则中的每个叶节点终止规则的密集预测(树的一部分是终端符号。我们在实验中使用光束搜索近似全局推理,光束大小为5in。不考虑特定节点类型的无效规则在推理过程中。例如,如果p1不等于p2,则p2→c1c2不能应用于节点p1。评估在本节中,我们展示了基于CNN的代码生成的实验结果。我们评估了我们在两个任务上的方法:(1)用于从Python代码生成《炉石传说》游戏,以及(2)用于生成可执行逻辑形式的语义解析。实验1《炉石传说》代码生成数据集。我们的第一个实验基于构建基准数据集《炉石传说》。该数据集包含665不同的《炉石传说》游戏;每个数据点的输入是卡牌名称、费用、攻击、描述等属性的半字段的结构化描述;输出是实现以下功能的Python代码片段。《炉石传说》山口表2中的umn列出了数据集的相关统计信息。指数。我们通过准确性、BLEU分数来评估我们的方法。理想情况下,精度应该考虑部分功能正确程序的位置,不幸的是,这些程序不是图灵可计算的。我们还发现,几个生成的程序使用了不同的变量名,但实现了正确的功能,而且有时函数调用中的参数名要么指定,要么不指定。虽然与参考程序不同,但经过人工检查后显然是正确的程序,我们将人为调整的精度表示为Acc。在这里,我们不执行非ob-checking算法的Vious替代实现,因此Acc仍然是函数准确性的下限。生成代码的质量由BLEU分数作为辅助指标进一步评估,它计算生成代码与地面真值代码的接近程度。总体结果。表3列出了我们基于CNN的代码生成,与之前状态相比的最先进模型:(1)潜在预测网络,一种增强的序列到序列模型,具有多个标记级预测器;(2)SEQ2TREE,一种基于AST的sequence-to-sequence模型;(3)句法神经模型,一种基于AST的LSTM解码器;(4)AbstractSyntaxNetwork,另一种基于AST的序列到序列模型,它在水平和垂直方向上构建了两个LSTM预测规则。如图所示,我们的模型在准确性和BLEU分数方面优于之前的所有结果。特别是,我们的准确率比之前在字符串上的最先进结果高出大约5个百分点。生成的代码示例。准确性。对于人为调整的精度(Acc+),据报道在我们的场景中观察到类似的现象,我们获得了30.3%的Acc+分数,表明我们的方法是有效的。我们发现一个有趣的事实,即以前的几种方法可以获得与我们的方法相似的BLEU分数,但准确性要低得多。例如,ASN模型的BLEU分数为79.2,与我们模型的79.6分数相当。然而,ASN只能达到22.7%的字符串准确率,而我们的是27.3%。这是因为BLEU指标仅衡量程序相似性。似乎生成合理代码的ASN等现有方法实际上在细节上是不正确的。因此,我们只将BLEU分数(在以前的作品中)视为次要指标。主要指标,即准确性,表明我们的方法比以前的模型产生更多的沟通计划者。消融试验。我们进行了广泛的消融测试来分析每个组件的贡献。虽然我们的网络开发从一个简单的基线开始,然后我们逐渐添加有用的组件,但相关测试以相反的方式进行:它从完整模型开始,我们要么删除一个组件,要么用一些合理的替代品替换它。我们在表4中报告了消融测试的结果。我们首先通过替换基于LSTM的RNN的组件来分析CNN的有效性。由于主要信息在于部分AST中显示的年龄,而不是预测语法规则,因此我们在此对照实验中仅将遍历前的CNN替换为LSTM。应用于如此长的序列的RNN可能难以训练,从而获得更差的性能。我们还分析了模型的其他组件,包括CNN的预测规则、基于树的卷积常规层、树路径卷积、池化层机制和池化范围控制器。我们看到上述每个组件都以自己的方式为整体模型做出贡献,将准确度提高了3-6%。这些结果表明我们设计了一个合理的神经架构组合,适用于代码生成任务。实验2数据集和设置。语义解析旨在生成给定自然语言描述的逻辑形式。它可以被认为是特定领域的代码生成,一种形式语言,因为逻辑形式是可执行的。然而,语义解析的风格与Python代码生成有很大不同。由于我们的模型主要是在《炉石传说》数据集上开发的,因此该实验可作为对我们模型泛化能力的额外评估。我们在两个语义解析数据集上评估我们的模型,其中输入是自然语言句子。ATIS的输出是lambda演算形式,而JOBS是Prolog形式。从表2的统计数据可以看出,语义解析的逻辑形式包含的节点少于《炉石传说》Python代码。我们使用与《炉石传说》基本相同的网络层进行语义解析。网络层数为7。我们没有构建具有不同节点类型的单独网络,因为我们的网络很容易过度拟合这么小的数据集。此外,我们引入了用于复制变量名的指针网络。结果。我们通过准确性评估我们的方法。它计算精确匹配的分数,除了我们调整join和split子句的顺序以避免虚假错误,就像以前的所有工作一样。我们没有测量BLEU,因为它没有在现有研究中使用。表5显示了我们模型的性能。我们还看到我们基于语法的结构化CNN编码器取得了与最先进的神经Lahr模型相似的结果。还需要注意的是,语义解析,我们不能生成《炉石传说》这样的代码。这可能是因为语义解析的逻辑形式通常很短,只包含1/4–1/3的标记,如《炉石传说》,所以RNN和CNN适合生成逻辑表。这个实验提供了额外的泛化证据,因为我们创建了CNN代码,我们的能力和灵活性模型基本上是为长程序设计的(例如《炉石传说》),但也适用于语义解析。结论在本文中,我们提出了一种用于代码生成的基于语法的结构化CNN。我们的模型通过指定语法规则来利用抽象程序的语法树(AST)。我们解决了传统的基于RNN的方法可能不适合gram生成的问题,这可能是由于程序中有大量的kens/nodes。因此,我们设计了一个基于AST结构的CNN编码器-解码器模型。我们在《炉石传说》数据集上的主要实验表明我们优于以前基于RNN的方法。对两个语义解析任务的额外实验证明了我们方法的稳健性。我们还进行了深度消融测试,以验证模型中每个组件的有效性。致谢本文由南京大学软件学院iSE实验室2020级研究生张静翻译转载。