软件正日益主宰世界。对更多、更好的软件的巨大需求正在把软件开发人员的工具和技术变成一个高效经济和强大社会的重要因素。这些工具旨在通过在各种开发任务中(部分)自动化来支持开发人员,从而提高开发人员的工作效率。例如,开发人员工具完成部分编写的代码,警告潜在的bug和漏洞,查找代码克隆,或帮助开发人员在庞大的代码库中搜索。
构建开发人员工具的传统方法是基于精确、逻辑推理的程序分析。这种传统的程序分析部署在编译器和许多其他广泛使用的工具中。尽管它取得了成功,但仍存在许多传统程序分析只能部分解决的问题。原因是实际上所有有趣的程序分析问题都是不可确定的,也就是说,对于非平凡的程序,给出保证精确和正确的答案是不可能的。相反,程序分析必须接近被分析软件的行为,通常在精心设计的启发式的帮助下。
制定有效的启发式是困难的,特别是因为正确的分析结果往往依赖于不确定的信息,例如,自然语言信息或公共编码约定,这是不服从于精确的、基于逻辑的推理的。幸运的是,软件是由人类编写的,因此遵循规则模式和编码习惯,类似于自然语言。16例如,开发人员通常将循环变量称为i或j,大多数开发人员更喜欢afor循环
在一个while循环
在迭代顺序数据结构时。软件的这种“自然性”激发了基于机器学习的软件分析的研究,该分析利用了代码的规律和约定。1,31
在过去的几年里,深度神经网络已经成为一种对不确定数据进行推理和进行概率预测的强大技术。软件可以被认为是神经网络的“数据”吗?本文以肯定的回答回答了这个问题。我们展示了最近的一系列研究,我们称之为神经软件分析——基于神经机器学习模型对软件进行推理的程序分析的另一个选择。
本文根据神经软件分析何时可能补充甚至超越传统程序分析来定义何时使用神经软件分析的标准。然后,我们提出了一个概念框架,展示了神经软件分析通常是如何构建的,并通过一系列示例来说明它,其中三个我们将进行更详细的描述。示例分析解决了常见的开发问题,例如错误检测或代码完成,并且已经被从业者使用,尽管该领域还很年轻。最后,我们讨论了开放的挑战,并展望了未来神经软件分析工作的前景。
原则上,实际上所有的程序分析问题都可以用传统的、基于逻辑推理的方式来表述,也可以用数据驱动的、基于学习的方式来表述,例如神经软件分析。下面描述了神经软件分析最适合的情况,并且可能优于传统的、基于逻辑的程序分析。看到图1为了一个视觉插图。
维度1:可用信息的模糊性。传统的程序分析是基于从精确的输入信息中得出明确的结论。然而,这种精确的、逻辑的推理往往不能代表不确定性。相反,神经软件分析可以处理提供给分析的模糊输入,例如,嵌入代码的自然语言。可获得的信息越模糊,神经软件分析就越适合。原因是神经模型识别模式,同时允许对这些模式进行不精确的描述。例如,与传统程序分析所使用的“如果代码具有属性a,那么B成立”的严格规则不同,神经软件分析学习“如果代码类似模式a,那么B可能成立”的模糊规则。
维度2:定义良好的正确性标准。一些程序分析问题具有定义良好的正确性标准或规范,它精确地描述了分析提供的答案何时是人想要的,而无需与人进行检查。例如,这是测试引导的程序合成的情况,其中提供的测试用例指定了答案何时是正确的,或者对于类型检查程序的分析,其中类型系统的规则定义了何时保证程序是类型安全的。相反,许多其他分析问题并没有提供定义良好的正确性标准。对于这些问题,人类开发人员最终决定分析的答案是否符合开发人员的需求,通常是基于分析是否成功地模仿开发人员将要做的事情。例如,这些问题包括基于自然语言查询的代码搜索,基于部分编写的代码的代码完成,或者预测代码更改是否会导致错误。对于缺乏定义良好的正确性准则的问题,神经软件分析往往优于传统分析。原因在于,解决这种“不需要规范”的问题归根结底是要找到合适的启发式,在这个任务中,学习过的模型是非常有效的。
维度3:可学习的例子数量。神经模型需要大量的数据,因此,如果有大量的例子可以从中学习,那么神经软件分析的效果最好。通常,训练一个有效的神经模型至少需要数千个例子。这些示例可以以各种形式出现,例如,从大型代码语料库中提取的代码片段。一些神经软件分析不仅从代码原样中提取示例,而且修改代码以创建其他方面表现不足的类的示例,例如,有bug的代码。
许多神经软件分析都有一个由五个组件组成的体系结构图2).给定一个要学习的代码语料库,第一个组件提取代码示例适合于分析试图解决的问题。这些代码示例被转换为向量——或者基于编译器已知的中间表示,如标记序列或抽象语法树,或者基于专门为基于学习的分析开发的新代码表示。接下来,这些示例用作训练数据火车一个神经模型。前三个步骤都发生在只执行一次的培训阶段,在将分析部署给开发人员之前。训练之后,分析进入预测阶段,开发人员查询神经模型包含以前未见过的代码示例。该模型为给定的查询生成预测,这些预测可以直接提供给开发人员,也可以通过可选的方法进行验证和排名组件。验证和排序有时依赖于传统的程序分析,结合了神经和基于逻辑的推理的优势。本节的其余部分将更详细地讨论这些组件。
提取代码示例。轻量级静态分析。为了提取可供学习的代码示例,大多数神经软件分析都建立在轻量级静态分析的基础上。这样的静态分析重用几乎任何编程语言都可以使用的标准工具和库,例如,将程序代码分解为令牌的标记器,或将程序代码转换为抽象语法树(AST)的解析器。这些工具作为IDE或编译器的一部分很容易获得。建立在这种轻量级的标准静态分析之上,而不是求助于更复杂的静态分析,有两个方面的好处。首先,它保证了神经软件分析能够很好地扩展到用于有效训练的大型代码语料库。其次,它可以很容易地将一种语言开发的神经软件分析移植到另一种语言。
获取标签的例子。实际上,所有现有的神经软件分析都使用某种形式的监督学习。因此,它们需要有标记的代码示例,即带有预期预测结果的代码示例,以便神经模型能够从中学习。如何获得这样的标记示例取决于分析处理的具体任务。例如,预测类型的分析可以从现有的类型注释中学习,14,24,28预测代码编辑的分析可以从编辑历史中学习,例如,记录在版本控制系统中。10,36因为大量的标记示例是有效监督学习的先决条件,神经软件分析社区最关注的开发任务部分是由足够大的、带注释的数据集的可用性驱动的。
将软件表示为向量。由于神经模型是关于数字向量的,神经软件分析最重要的设计决策是如何将前一步提取的代码示例转化为向量。我们将讨论这一步骤的两个方面:如何表示代码的基本构建块,例如,单个代码标记。如何将基本构建块的表示组合成更大的代码片段的表示,例如语句或函数。
令牌代表代码。任何将代码表示为向量的技术都面临着如何将编程语言的基本构建模块映射为向量的问题。大多数神经软件分析以两种方式之一解决令牌表示的挑战。一种方法是抽象掉代码中的所有非标准标记,例如,通过将变量名抽象为var1
,var2
,等等。13,36虽然这种方法有效地减少了词汇表的大小,但它也丢弃了可能有用的信息。另一种方法将每个令牌映射到一个固定大小的嵌入向量。这里的目标是表示语义上相似的标记,例如,两个标识符len
而且大小
,与相似的向量。38为了获得这样的嵌入,一些分析在训练处理主要任务的神经模型之前训练一个标记嵌入,然后使用预先训练的嵌入将每个标记映射到一个向量。17,30.或者,一些分析结合整体神经模型学习嵌入函数,本质上使处理许多不同标识符的任务成为机器学习模型处理的整体优化任务的一部分。2
代码的神经模型几乎完全是分类模型,这是由与程序相关的大多数信息是离散的这一事实所驱动的。
一个关键的挑战是,当新项目添加到代码语料库中时,开发人员可以自由选择的标识符词汇表(例如变量和函数名)以明显的线性方式增长。18原因是开发人员为不同的应用程序和应用程序域提出了新的术语和约定,导致在只有几千个项目的语料库中产生数百万个不同的标识符。处理词汇表问题的最简单方法是将词汇表固定到(比如说)10,000个最常见的标记,同时用一个特殊的“未知”向量表示所有其他词汇表之外的标记。更复杂的技术将标记分成子词,例如,写文件
进入“write”和“file”,分别表示每个子词,然后将子词向量组合成完整标记的表示。为了将标记拆分为子词,神经软件分析可以依赖于约定3.或者压缩算法,计算一个固定大小的最频繁出现的子词集合。18
表示代码片段。最近,如何将源代码片段(例如,语句或函数中的代码)转换为向量表示受到了研究人员和实践者的广泛关注。许多提出的技术可以大致概括为两类。如前所述,它们都依赖于将最基本的代码构建块映射到向量的某种方式。一方面,有些技术可以将代码片段转换为一个或多个向量序列。这是最简单的,但却非常流行和有效的技术13,14,36从代码令牌序列开始,并将每个令牌映射到一个向量。例如,一个代码片段x = true
;会映射成一个由四个向量组成的序列“x”、“=”、“true”
,和“;”。与将代码视为标记的平面序列不同,其他技术利用了这样一个事实:与自然语言(例如)相比,代码具有定义良好且明确的结构。5,26这类技术通常从代码片段的AST开始,并通过树提取一条或多条路径,将路径中的每个节点映射到一个向量。例如,流行的code2vec技术5提取许多这样的AST路径,每个路径连接树中的两个叶。
另一方面,有几种技术将代码片段表示为向量图。2,10,39这些图通常基于ast,可能用表示数据流、控制流和其他可以通过传统静态分析计算的代码元素之间的关系的附加边进行增强。给定这样一个图,这些技术将每个节点映射成一个向量,生成一个向量的图。基于图的代码向量表示的主要优点是,它们为神经模型提供了丰富的代码结构和语义信息。缺点是,代码的富图表示在编程语言之间的可移植性较差,而且基于图的神经模型在计算上往往比基于序列的模型更昂贵。
软件的神经模型。一旦源代码被表示为向量,下一步就是将这些向量输入到机器学习模型中。软件的神经模型通常由两部分组成。一部分将给定的源代码总结(或编码)为更紧凑的表示形式,例如,单个向量。根据这个总结,另一部分对代码进行预测。图3展示了在这两个部分中使用的常用神经组件,下面我们将更详细地讨论这些组件。每个神经成分本质上都对应于一个习得的函数,它将一些输入映射到一些输出。
图3。神经组件流行于分析软件。原则上,左边的任何汇总组件都可以与右边的任何预测组件自由组合。
总结源代码。总结代码最简单的方法是将描述代码的向量连接起来,并使用前馈网络将连接映射成一个更短的向量。例如,对于表示为向量序列的代码,每个向量表示一个标记,循环神经网络或变压器37可以总结一下它们。前者只遍历序列一次,而后者则迭代地关注序列的特定元素,在这些元素中,决定要注意什么是可以学习的。另一个常见的神经组件是树状结构的模型,它总结了代码的树状表示,例如,代码片段的AST。5,26最后,当今最复杂的技术可能是图神经网络(GNNs),2它对代码的图形表示进行操作。给定每个节点的初始向量表示的图,GNN根据相邻节点的当前表示重复更新节点,有效地跨代码元素传播信息。
做一个预测。代码的神经模型几乎完全是分类模型,这是由与程序相关的大多数信息是离散的这一事实所驱动的。一个常见的预测组件是二进制分类器,例如,用来预测一段代码是正确的还是有错误的。23,30.同样,anN-ary分类器预测固定集合中的哪个类(es)N类,例如,从一组通用类型中预测变量的类型。14,24,28这样的分类器输出可用类的概率分布,模型通过传递未缩放的输出(分对数),透过softmax函数,把网络的较早层连结起来。除了平面分类,一些神经代码分析还可以预测向量序列,例如,如何编辑给定的一段代码,36或者是代码的自然语言描述。3.这类任务的常见神经模型是编码器-解码器模型,它将序列编码器与预测序列的解码器结合在一起。在这些模型中,解码器在每一步的输出是一个概率分布,例如,跨可能的源级标记,类似于平面分类器。next-token预测,19这是一个经典的语言模型学习任务,只有一个解码器模型就足够了,因为序列编码隐含在解码器的状态中。
培训和查询。训练和查询软件的神经模型就像在其他领域一样:控制模型行为的各种函数的参数(称为权重和偏差)被优化以适应输入和预期输出的例子。例如,对于一个N-ary分类模型,训练将通过损失函数(例如交叉熵)将预测的概率分布与期望的分布进行比较,然后通过随机梯度下降将损失最小化。一旦训练成功,该模型通过从训练中看到的例子中泛化,对以前未见过的软件进行预测。
对于排名,一种选择是使用模型预测的数值向量来确定模型最确信的预测。在使用soft-max函数的分类模型中,许多方法将类的预测似然解释为概率分布,然后根据类的预测概率对类进行排序。14,28在编码器-解码器模型中,波束搜索通常用于获取k最有可能的预测结果是保持k在解码复杂输出(如代码令牌序列)时进行最可能的总体预测。36
给定神经软件分析的概念框架,我们现在讨论具体的实例分析。作为一个更广泛的概述,表1展示了适合于神经软件分析的选定分析问题,以及解决这些问题的一些代表性工具。Allamanis et al。1提供更多分析的广泛调查。这些工具解决了一系列不同的问题,从分类任务,如错误检测或类型预测,到生成任务,如代码完成和代码标题,再到检索任务,如代码搜索。
本节的其余部分将更详细地讨论神经软件分析的三个具体示例。为了说明示例分析,我们使用一个小的Python代码示例(参见图4).这个例子是一款井字游戏的实现,围绕着一个代表游戏所处3x3网格的类板。游戏的主循环(游戏邦注:第19至28行)实现了玩家所采取的回合。在每个回合中,一名玩家在网格上标记一个点,直到其中一名玩家连续标记三个点或直到网格被填满。
我们用这个例子来说明在表2.这些分析对于在下一个示例中查找错误、预测函数的类型和分别完成示例的代码非常有用。
表2。三种神经软件分析以及它们如何映射到概念框架图2.
学会发现bug。DeepBugs30.是一种神经软件分析,它处理软件开发中一个持续存在的重要问题——发现bug的问题。虽然在传统的、基于逻辑的分析上有大量的工作要做,但是基于学习的错误检测直到最近才出现。基于学习的bug检测器的一个例子是Deep-Bugs,它利用一种通常被程序分析忽略的信息:编码在自然语言标识符中的隐式信息。由于此信息固有的模糊性(参见维度1),并且如果没有人(维度2),往往无法确定一段代码是否正确,因此基于学习的方法很适合解决此问题。DeepBugs将错误检测定义为一个分类问题,也就是说,它预测给定的代码片段是正确的还是有问题的。
提取代码示例。为了收集训练数据,DeepBugs提取了着重于特定类型语句和这些语句中可能出现的错误模式的代码示例。的第24行说明了其中一个错误模式图4在这里,函数的参数y和x被意外地交换了。为了找到这种交换的参数错误,分析提取所有至少有两个参数的函数调用。基于大多数代码都是正确的这一常见假设,提取的调用作为正确代码的示例。与这种方法可以提取的许多正确示例相比,如何收集大量的错误代码示例并不明显(Dimension 3)。DeepBugs通过人为地在提取的代码示例中引入错误来解决这一挑战。例如,创建交换的参数错误相当于简单地交换在代码库中找到的调用的参数,这很可能产生不正确的代码。Deep-Bugs是一个通用框架,它支持交换参数以外的其他bug模式,为了简洁起见,这里省略了交换参数。
转换成向量。Deep-Bugs将每个代码示例表示为几条信息的串联。最重要的是,该表示包括代码片段中涉及的自然语言标识符。对于示例中的bug图4,分析提取被调用函数的名称,mark_point
除了标识符名称之外,分析还考虑关于代码段的上下文信息,例如AST中代码的祖先节点或表达式中涉及的操作符。这些信息片段被表示为基于预先训练的嵌入的向量。为了表示标识符,DeepBugs预先训练了一个Word2vec模型25在源代码的标记序列上,这使分析能够跨类似的标识符进行泛化。对于我们正在运行的示例,这种泛化使DeepBugs能够理解,当将名称类似于x和y的参数赋给名称类似于的函数时mark_point
,通常将x作为两个参数中的第一个。
神经模型。将一段代码分为错误和正确的神经模型是一个简单的前馈神经网络。图5(左上)用一个例子说明了模型。该模型将所有输入的嵌入向量串联起来,然后预测概率p代码有bug。对于所有未经修改就从代码库中提取的代码示例,即应该正确的代码,训练模型进行预测p= 0.0,而它被训练为预测p人为注入的bug = 1.0。经过训练后,DeepBugs模型可以预测之前看不到的代码有多大的可能性存在缺陷。为此,分析提取与训练过程中完全相同的信息,并使用它们查询分类模型。如果模型预测p超过某些可配置的阈值,分析将向开发人员报告一个警告。
验证和排名。DeepBugs在将潜在bug作为警告报告给开发人员之前,不会进一步验证它们。然而,为了对警告进行优先级排序,DeepBugs会根据预测概率对可能有bug的代码进行排名p。然后,开发人员可以使用p高于某个阈值,然后从最可能的错误开始往下看。
受deepbugs启发的代码分析工具可用于各种Jet-Brains ide。分析JavaScript的插件一个和Python代码已经被成千上万的开发人员下载。
学习预测类型。打字机28是一种神经软件分析,用于预测动态类型语言(如Python或JavaScript)中的类型注释。虽然在这些语言中不需要类型注释,但在项目增长时通常需要类型注释,因为它们有助于确保正确性,促进维护,并改善开发人员可用的IDE支持。为了说明这个问题,考虑mark_point
函数图4.因为函数没有任何类型注释,所以问题是要推断其参数的类型及其返回类型。类型预测是神经软件分析的主要目标,因为它符合前面讨论的所有三个维度。源代码提供了关于变量或函数类型的各种提示,其中许多提示是模糊的,例如变量的名称、函数附带的文档或变量的使用方式(Dimension 1)。因为开发人员可以合理选择的正确类型注释有时不止一个,因此没有定义良好的标准来自动检查人类是否同意预测的类型(Dimension 2)。大量的代码已经用类型进行了注释,为神经模型(Dimension 3)提供了足够的训练数据。
提取代码示例。为了预测函数参数的类型和返回类型,TypeWriter从Python代码中提取两种信息。一方面,分析提取与每个可能的类型注释程序元素相关的自然语言信息,例如函数参数的名称或与函数相关的注释的名称。另一方面,分析提取编程语言信息,例如如何使用代码元素。的返回类型mark_point
函数。TypeWriter在第14行提取返回语句,其中包括一个变量名(has_…)和一个与函数相关的注释(“…返回是否…”),两者都暗示返回类型是Boolean。为每个代码语料库中的每个函数提取这些信息。对于已经有类型注释的函数,分析还提取现有的注释,这将作为学习的基础真理。
转换成向量。TypeWriter将提取的信息表示为基于预先训练的嵌入的几个向量序列。所有与类型关联的代码标记和标识符名称都使用代码标记嵌入映射到向量。代码令牌嵌入是在分析学习的所有Python代码上预先训练的。与类型相关的注释表示为单词序列,每一个都表示为通过单词嵌入获得的向量。单词embedding对从给定代码语料库中提取的所有注释进行了预先训练,以确保它非常适合Python注释中通常出现的词汇表。
神经模型。打字机的神经模型(图5(右)使用多个循环神经网络总结给定的向量序列:一个用于与待键入的程序元素相关的所有标识符名称,一个用于与之相关的所有代码标记,还有一个用于所有相关的自然语言单词。这三个循环神经网络每个都得到一个向量,这些向量的连接然后作为前馈网络的输入,前馈网络充当分类器。分类器输出固定类型集合上的概率分布,例如,语料库中最常见的1000种类型。TypeWriter将神经模型预测的概率解释为给定程序元素的可能类型的排序列表,概率最高的类型位于列表的顶部。
验证和排名。最前面的预测类型可能是正确的,也可能是错误的。例如,神经模型可以预测int
作为一种player_name
尽管它应该如此字符串
.要在实践中发挥作用,类型预测工具必须确保添加它建议的类型不会引入任何类型错误。TypeWriter使用渐进式类型检查器来验证神经模型预测的类型,并找到一组彼此一致的新类型注释以及与任何先前存在的注释一致的注释。为此,该方法将为每个尚未注释的程序元素分配一个预测类型的问题转化为组合搜索问题。根据渐进式类型检查器报告的类型错误数量,TypeWriter尝试添加尽可能多的缺失类型,而不引入任何新的类型错误。基于类型检查器的验证结合了神经软件分析和传统程序分析的优点,使用后者对前者所做的预测进行验证。
TypeWriter是由Facebook开发的,用于向Python代码添加类型注释。它已经为数十亿人使用的软件增加了数千种类型。
学习完成部分代码。作为第三个例子,我们描述了一种神经代码补全技术。当开发人员输入代码时,该技术预测光标位置的下一个标记。神经模型生成潜在输出令牌的概率分布,通常情况下,最可能的前5或10个令牌将显示给开发人员。下一个令牌预测问题非常适合神经软件分析:对于维度1,信息是模糊的,因为没有简单的方法来明确规定下一个应该出现哪个令牌。b对于Dimension 2,除了程序应该继续编译之外,没有定义良好的正确性标准。此外,互动性需求排除了在每个预测点进行昂贵的验证的可能性。最后,关于Dimension 3,有大量可用的训练数据,因为一种给定编程语言中的几乎所有代码都可以作为训练数据。
提取代码示例。代码示例提取很简单:对于任何给定的上下文—这意味着直到光标位置的代码标记—在训练语料库中紧接在光标后面的标记是正确的预测。对于在图4,假设开发人员在第28行请求代码完成,光标位于标记为??的位置。分析提取了前面的标记序列,即:game_done, =, True, board,。
,这里的预期预测是show_winner
.
转换成向量。令牌通过固定大小的词汇表表示,词汇表之外的令牌由特殊的“未知”令牌表示。例如,上面的输入可以重写为42,233,8976,10000,5,其中数字是进入词汇表的索引,board是由索引10000表示的词汇表外标记。此外,所有输入输出示例通常使用额外的填充令牌填充为相同的长度。
神经模型。虽然预测下一个标记似乎是一个简单的分类问题,但我们希望将预测限定在前面的标记序列上,而不仅仅是最后一个标记。循环神经网络(RNN)自然适合这项任务(参见图5左下侧)。在每一步中,该网络通过一个隐藏向量接收前一个令牌序列的摘要,该向量在图中由从左侧进入每个节点的边描述。它还接收当前令牌的嵌入。嵌入是在训练过程中以端到端方式学习的,而不是像前面的分析那样单独预先训练。
给定隐藏向量和当前令牌的嵌入,解码器产生一个输出令牌,该输出令牌预计与输入序列相等,只是移位了一个。通过这种方式,在考虑到该点之前的上下文的情况下,期望解码的每一步都生成下一个标记。(解码的每一步也会产生一个传递到下一步的隐藏向量。)更准确地说,译码器在每一步生成词汇表上的概率分布,也就是说,概率最大的令牌将被认为是最顶层的预测。在训练过程中,损耗相对于使用负对数似然损耗的理想解码器输出按点计算。
作为基于rnn的模型的替代方案,最近提出的变压器体系结构37也可以用于代码预测。19
验证和排名。IDE中的代码完成通常显示最可能的下一个令牌的排序列表。给定模型为每个令牌生成的概率分布,IDE可以显示(例如)最可能出现的前五个令牌。例如,基于项目中常用的api的局部启发式可能会在将这个排名列表显示给用户之前进一步调整它。如果开发人员对预测多个令牌感兴趣,那么束搜索(前面提到过)可以预测多个可能的序列。
神经编码补全一直是工业界感兴趣的活跃课题。例如,它在TabNine中可用,在Facebook等公司的内部使用研究,以及广泛使用的ide,如JetBrains的IntelliJ和微软的Visual Studio的IntelliCode。34最近的进展解决了这里没有考虑到的三个问题。首先,词汇表外的令牌是代码补全的一个关键问题,因为要预测的令牌可能在训练期间没有看到。这个问题可以通过将复杂的标识符名称拆分为更简单的组成名称来解决18或者通过使用习得的注意机制从上下文中复制标记。21第二,rnn记住的代码上下文的数量有限。最近的工作19,34通过基于转换器的体系结构解决了这个问题,例如,使用GPT-2转换器模型对解析树进行深度优先遍历。19第三,需要一次预测多个标记,例如,完成整行代码,可以通过束搜索来解决。34
神经软件分析是一个新概念,研究人员和实践者才刚刚开始探索它。下面将讨论开放挑战,并展望该领域将如何发展。
更多的分析任务。未来工作最明显的方向可能是用神经方法针对更多的分析任务。原则上,每个分析任务都可以表述为一个学习问题。然而,我们看到了符合本文开头提到的三个方面的问题的最大潜力。到目前为止,神经软件分析社区很少或根本没有注意到一些任务,包括软件性能特性的预测、自动化测试输入生成和自动化故障注入。
更好的收集数据的方法。目前的大多数工作都集中在相对容易获得大量高质量训练数据的问题上。一旦这些“低垂的果实”被收获,我们预计社区将把注意力转移到更复杂的获取数据的方法上。基于运行时信息对软件进行神经分析是一个很有前途的方向。到目前为止,几乎所有现有的工作都集中在静态神经软件分析上。
更好的模型。每个神经软件分析的核心问题是如何将软件表示为向量,使神经模型能够对软件进行推理。代码的学习表示是一个活跃的研究领域,具有很好的结果。5,15,26由于观察到代码提供了与自然语言相似程度的“自然性”和规律性,16社区通常是由在自然语言处理中成功的技术驱动的。然而,由于软件和自然语言文档显然是不一样的,我们设想将重点更多地转移到专门为软件设计的模型上。
半监督学习和非监督学习。半监督学习和无监督学习是避免需要获取标记训练数据进行监督学习的一个很有前途的方向。其基本思想是在一些“伪任务”上预先训练模型,因此很容易获得大量的标记数据,例如,语言模型或自动编码器,32然后在相关任务中使用预训练模型,而这些任务几乎没有标记训练数据。这种从几次到零次的学习在自然语言任务中显示了令人印象深刻的结果,并有可能在未来被应用到软件中。
可解释性。神经模型往往缺乏可解释性。这个普遍问题影响神经软件分析,特别是因为这些分析的“消费者”通常是开发人员,也就是人类用户。未来的研究应该研究如何与开发人员沟通模型做出预测的原因,以及如何让开发人员更有信心遵循神经软件分析的预测。将模型的预测归为特定代码行的工作是朝着这个方向迈出的有希望的第一步。12
与传统程序分析集成。神经分析技术和传统分析技术有互补的优点和缺点,对于许多问题,将两者结合起来可能比单独使用它们更有效。集成这两种分析的一种方法可能是一个连续的反馈循环,其中一个神经分析和一个传统分析以一种使其他分析能够涵盖更多情况的方式重复增强程序。另一个想法是在将代码传递给神经分析之前应用传统的程序切片,而不是像今天通常做的那样简单地传递所有代码。TypeWriter展示了一个整合神经和传统分析的早期例子,后者验证了前者的预测。
神经软件分析是一个雄心勃勃的想法,以解决软件主导世界的挑战。
可伸缩性。到目前为止提出的大多数神经软件分析都集中在小的代码片段上,这些代码片段通常不超过一个函数。未来的工作可能会解决如何对更大的代码片段(例如整个模块或应用程序)进行预测的问题。扩大神经软件分析需要新的方法来分解分析所执行的推理,并将对程序一部分的预测传播到程序的另一部分。
超出软件本身的与软件相关的工件。本文和迄今为止所做的大部分神经软件分析工作都集中在软件本身。还有许多其他与软件相关的工件也可以从神经分析中受益。这些工件包括混合了自然语言和代码元素的文本,例如,发生在代码评审期间的通信或错误报告中,以及软件生成的工件,例如崩溃跟踪或日志。29
神经软件分析是一个雄心勃勃的想法,以解决软件主导世界的挑战。这个想法已经在各种开发任务中显示出了有希望的结果,包括从业者所采用的工作。从一个基本的观点来看,神经软件分析提供了一种强大而优雅的方法来推理软件的不确定性本质。这种不确定性既与程序分析问题通常是不可确定的这一事实有关,也与嵌入到程序中的“模糊”信息有关,例如自然语言和编码约定。从实用主义的角度来看,神经软件分析可以大大减少产生软件分析所需的工作量。传统的基于逻辑的分析通常是由程序分析专家构建的,世界上只有几百个这样的专家,而神经软件分析是从数据中学习的。这种数据驱动的方法使数以百万计的开发人员,也许在不知不觉中,仅仅因为他们生产软件的事实,就为神经软件分析的成功做出了贡献。也就是说,神经软件分析利用开发人员工具需求的根本原因——不断增加的软件数量、复杂性和多样性——来响应这种需求。
第一作者得到了欧洲研究理事会(ERC,拨款协议851895)和德国研究基金会在ConcSys和Perf4JS项目中的支持。
1.Allamanis, M., Barr, E., Devanbu, P.和Sutton, C.大代码和自然的机器学习的调查。ACM计算调查51, 4(2018), 81。
2.Allamanis, M., Brockschmidt, M.,和Khademi, M.学习用图表示程序。在六人会议记录th实习生。关于学习表征的讨论(2018年4月30日- 5月3日,加拿大温哥华);https://openreview.net/forum?id=BJOFETxR-
3.Allamanis, M., Peng, H.和Sutton, C.一个用于源代码极端摘要的卷积注意网络。在《实习生会议录》关于学习表征的讨论, 2016, 2091 - 2100。
4.Alon, U., Brody, S., Levy, O.和Yahav, E. code2seq:从代码的结构化表示生成序列。在七人会议记录th实习生。关于学习表征的讨论(美国,新奥尔良,洛杉矶。2019年5月6 - 9日);https://openreview.net/forum?id=H1gKYo09tX
5.阿隆,U., Zilberstein, M., Levy, 0。,而且Yahav, E. code2vec: Learning distributed representations of code. InACM计划论文集。朗。32019年,40:1-40:29;https://doi.org/10.1145/3290353
6.巴维希,莱米厄,C,福克斯,R,森,K,和斯托伊卡,I. AutoPandas:用于程序合成的神经支持生成器。在ACM计划论文集。朗。2019年,168:1-168:27。https://doi.org/10.1145/3360594
7.Chen Z., Kommrusch, S., Tufano, M., Pouchet, L., Poshyvanyk, D.和Monperrus, M. SequenceR:端到端程序修复的序列对序列学习。IEEE谢霆锋(2019)。
8.David, Y., Alon, U.和Yahav, E.使用增强控制流图的条带二进制的神经逆向工程。在ACM计划论文集。朗。42020年,225:1-225:28;https://doi.org/10.1145/3428293
9.Devlin, J., Uesato, J., Bhupatiraju, S., Singh, R., Mohamed, A.和Kohli, P. RobustFill:噪声I/O下的神经程序学习。在34人会议记录th实习生。机器学习会议(2017年8月6日至11日,澳大利亚悉尼)。D. Precup和Y.W. The, Eds。PMLR, 990 - 998;http://proceedings.mlr.press/v70/devlin17a.html
10.Dinella, E., Dai, H., Li, Z., Naik, M., Song, L.,和Wang, K. Hoppity:学习图转换来检测和修复程序中的bug。在八人会议记录th实习生。关于学习表征的讨论(2020年4月26日至30日,埃塞俄比亚亚的斯亚贝巴);https://openreview.net/forum?id=SJeqs6EFvB
11.顾X,张H,金s,深度代码搜索。在40年会议记录th实习生。Conf. Softw。Eng。(2018年5月27日至6月03日,瑞典哥德堡)。肖德龙先生,克伦科维奇先生,切切克先生,哈曼先生,主编。ACM, 933 - 944;https://doi.org/10.1145/3180155.3180167
12.Gupta, R, Kanade, A,和Shevade, S.学生程序中语义错误定位的神经归因。在神经信息处理系统年会论文集(2019年12月8日至14日,加拿大BC省温哥华)。H.M.沃拉赫、H.拉罗谢尔、A.贝格尔齐默、F. d'Alché-Buc、E.B.福克斯和R.加内特,编11861-11871;https://proceedings.neurips.cc/paper/2019/hash/f29a179746902e331572c483c45e5086-Abstract.html
13.Gupta, R., Pal, S., Kanade, A.和Shevade, S.深度修复:通过深度学习修复常见的C语言错误。在31人的议事录圣人工智能会议(2017年2月4-9日,美国加利福尼亚州旧金山)。Satinder P. Singh和Shaul Markovitch, Eds。AAAI出版社,1345 - 1351;http://aaai.org/ocs/index.php/AAAI/AAAI17/paper/view/14603
14.Hellendoorn, V., Bird, C., Barr, E.和Allamanis, M.深度学习类型推理。在2018年ACM欧洲软件联席会议论文集。Eng。Conf.和电脑。Softw的基础。Eng。(2018年11月4日至9日,美国佛罗里达州布埃纳维斯塔湖)。g。t。利文斯,a。加西亚,c。s。帕萨雷努,ed。ACM, 152 - 162;https://doi.org/10.1145/3236024.3236051
15.Hellendoorn, V., Sutton, C., Singh, R., Maniatis, P.和Bieber, D.源代码的全局关系模型。在八人会议记录th实习生。关于学习表征的讨论(2020年4月26日至30日,埃塞俄比亚亚的斯亚贝巴)。OpenReview.net;https://openreview.net/forum?id=B1lnbRNtwr
16.Hindle, A., Barr, E., Su, Z., Gabel, M.和Devanbu, P.关于软件的自然性。在34人会议记录th实习生。Conf. Softw。Eng。(瑞士苏黎世),2012年6月2-9日),837-847。
17.Kanade, A., Maniatis, P., Balakrishnan, G.和Shi, K.学习和评估源代码的上下文嵌入。在37次会议的会议记录th实习生。机器学习会议,(虚拟事件,2020年7月13-18日),PMLR, 5110-5121;http://proceedings.mlr.press/v119/kanade20a.html
18.Karampatsis, R., Babii, H., robes, R., Sutton, C.和Janes, A.大代码=大词汇表:源代码的开放词汇表模型。在学报42nd实习生。Conf. Softw。Eng。(2020年6月19日至27日,韩国首尔)。G.罗瑟梅尔和D-H Bae, Eds。ACM, 1073 - 1085;https://doi.org/10.1145/3377811.3380342
19.Kim, S, Zhao, J, Tian, Y,和Chandra, S.用输入树到变压器的代码预测。在IEEE/ACM实习生论文集。Conf. Softw。Eng。
20.拉科米斯,J., Yin, P., Schwartz, E., Allamanis, M., Goues, C., Neubig, G.和Vasilescu, B.:反编译标识符命名的神经方法。日月光半导体, 2019年。
21.李建军,王玉玉,吕明明,李建军。基于神经注意和指针网络的代码完成。在27国会议记录th实习生。人工智能联合会议(斯德哥尔摩,瑞典,2018)。AAAI出版社,4159 - 25。
22.Li, Y., Wang, S.,和Nguyen, T. DLFix:基于上下文的代码转换学习用于自动程序修复。ICSE, 2020年。
23.李,Z.,等。VulDeePecker:基于深度学习的漏洞检测系统。教你们, 2018年。
24.Malik, R., Patra, J.和Pradel, M. NL2Type:从自然语言信息推断JavaScript函数类型。在第四十一届会议记录圣实习生。Conf. Softw。Eng。(2019年5月25-31日,加拿大蒙特利尔),304-315;https://doi.org/10.1109/ICSE.2019.00045
25.Mikolov, T., Sutskever, I., Chen, K., Corrado, G.和Dean, J.词汇和短语的分布式表示及其构成。在27国会议记录th神经信息处理系统年度会议(Lake Tahoe, NV, USA, 2013年12月5-8日),3111-3119。
26.牟亮,李国光,张磊,王涛,金铮,用于编程语言处理的树结构卷积神经网络。在30人会议记录th人工智能会议(美国凤凰城,AZ, 2016年2月12-17日),1287-1293。
27.Panthaplackel, S., Gligoric, M., Mooney, R.和Li, J.关联自然语言注释和源代码实体。在34人会议记录th人工智能会议;的32nd人工智能的创新应用;和10thAAAI计算机协会。人工智能的教育进展(2020年2月7日至12日,美国纽约)。AAAI出版社,8592 - 8599;https://aaai.org/ojs/index.php/AAAI/article/view/6382
28.Pradel, Gousios, G, Liu, J,和Chandra, S.打字机:基于搜索验证的神经类型预测。在28人会议记录thACM联合欧洲软件。Eng。Conf.和电脑。Softw的基础。Eng。(虚拟活动,美国,2020年11月8-13日),209-220;https://doi.org/10.1145/3368089.3409715
29.Pradel, M., Murali, V., Qian, R., Machalica, M., Meijer, E.和Chandra, S.脚手架:数百万文件上的bug定位。在29人会议记录thACM SIGSOFT实习生。计算机协会。Softw。测试和分析(2020年7月18日至22日,美国虚拟活动)。S. Khurshid和C.S. Pasareanu, Eds。ACM, 225 - 236;https://doi.org/10.1145/3395363.3397356
30.Pradel, M.和Sen, K. DeepBugs:基于名称的错误检测的学习方法。PACMPL 2 OOPSLA147:1-147:25 (2018);https://doi.org/10.1145/3276517
31.雷切夫,M.T.维切夫和克劳斯,A.预测《大代码》中的程序属性。编程语言原理,(2015), 111 - 124。
32.Rozière, B., Lachaux, M., Chanussot, L.和Lample, G.编程语言的无监督翻译。在2020年神经信息处理系统会议论文集。(虚拟活动,2020年12月6日- 12日)。H. Larochelle, M'A Ranzato, R. Hadsell, M- f Balcan, H-Tien Lin, Eds;https://proceedings.neurips.cc/paper/2020/hash/ed23fbf18c2cd35f8c7f8de44f85c08d-Abstract.html
33.Sachdev S, Li H, Luan S, Kim S, Sen K, Chandra S,源代码检索:一种神经代码搜索。在2号会议记录ndACM SIGPLAN实习生。机器学习和编程语言研讨会。ACM, 31-41。
34.Svyatkovskiy, A., Deng, S., Fu, S., Sundaresan, N. IntelliCode编写:使用变压器的代码生成。在28人会议记录thACM联合欧洲软件。Eng。Conf.和电脑。Softw的基础。Eng。(2020年11月8日至13日,美国虚拟活动)。p·德凡布,m·b·科恩,t·齐默尔曼,ed。ACM, 1433 - 1443;https://doi.org/10.1145/3368089.3417058
35.Tarlow, D.等。学习用Graph2Diff神经网络修复构建错误。在42人会议记录nd实习生。Conf. Softw。Eng。研讨会(2020年6月29日至7月19日,韩国首尔)。ACM, 19日至20日;https://doi.org/10.1145/3387940.3392181
36.Tufano, M., Pantiuchina, J., Watson, C., Bavota, G.和Poshyvanyk, D.通过神经机器翻译学习有意义的代码更改。在第四十一届会议记录圣实习生。Conf. Softw。Eng。(2019年5月25-31日,加拿大蒙特利尔),25-36;https://dl.acm.org/citation.cfm?id=3339509
37.Vaswani等人。你所需要的就是注意力。在2017神经信息处理系统学术会议论文集(2017年12月4-9日,美国加利福尼亚州长滩),6000-6010;http://papers.nips.cc/paper/7181-attention-is-all-you-need
38.Wainakh, Y., Rauf, M.和Pradel, M. IdBench:评估源代码中标识符名称的语义表示。在43人会议记录理查德·道金斯IEEE / ACM的实习生。Conf. Softw。Eng。(西班牙马德里,2021年5月22-30日),562-573。
39.Wei, J., Goyal, M., Durrett, G.和Dillig . I. LambdaNet:使用图神经网络的概率类型推理。在八人会议记录th实习生。关于学习表征的讨论(2020年4月26日至30日,埃塞俄比亚亚的斯亚贝巴)。OpenReview.net;https://openreview.net/forum?id=Hkx6hANtwH
40.White, M., Tufano, M., Vendome, C.和Poshyvanyk, D.用于代码克隆检测的深度学习代码片段。日月光半导体。87 - 98。
数字图书馆是由计算机协会出版的。版权所有©2022 ACM, Inc.
没有发现记录