像人一样编辑源代码,谷歌大脑提出神经网络也可以学「编程」

利用机器学习学会如何自动写代码或修改代码一直非常诱人,它不仅能减少大量工程努力,同时也能构建更高级的智能体。在这篇论文中,谷歌大脑的研究者提出利用神经网络建模我们对源代码的编辑,也就是说将我们对代码的编辑视为一个序列,然后像语言模型那样学会如何「写代码」。

总体而言,这份研究在于理解人类编写代码的过程(例如 GitHub 的 commit),并使用深度神经网络模拟这个动态的编辑过程。只需要给定上一次的编辑信息,模型就能预测下一次代码编辑该改什么,从而继续修改与生成代码。前一段时间,OpenAI GPT-2 能生成逼真的自然语言对话,也许采用相同的模式,这种动态代码编辑也能生成「逻辑合理」的源代码。

这篇论文的四位作者都来自于谷歌大脑,其中二作 David Bieber 还发布过一个可以自动生成命令行接口的库:Python Fire。

什么是代码建模

代码是一种机器语言,它和自然语言一样以一种序列的方式展现出来。以前机器之心曾介绍过多种代码生成的方式,其中研究最多的是如何根据 GUI 生成对应代码,例如 17 年提出的 Pix2Code,我们只需要输入界面图像就能生成对应的前端代码。

其次,2018 年 11 月,北大研究者首次成功用 CNN 自动生成代码,他们这篇 AAAI 2019 论文采用了 CNN 解码器,并在《炉石传说》数据集上进行了测试,效果超过了此前各类业内最佳模型。这类研究一般都会采用结构化的神经网络来建模代码结构,例如北大研究者的这篇论文就根据抽象语法树(AST)中的语法结构规则生成代码。

但是,这些方法都将代码生成看成是一种「一次到位」的静态过程。不过我们知道,代码的编写是动态的,随着新特性的实现、bug 的修复以及重构的进行,源代码库一直处在变化之中。其实在人类开发的过程中,开发者都需要访问已有的代码库或片段,考虑用一个或多个意图对其进行更改。

在本文中,谷歌大脑团队探讨的主要问题是如何观察一个过去的编辑序列并预测即将发生的编辑。这是一个重要的问题,因为构建更好的开发者工具的核心挑战是理解开发者行为背后的意图。

这也是一个有趣的研究挑战,因为仅根据编辑的内容(输入或删除的内容)无法理解编辑模式。我们需要根据变更与变更之前的状态之间的关系来理解编辑,而且,准确地对编辑序列建模需要学习过去编辑的表征,这一表征允许模型泛化模式并预测未来编辑。

如图 1 所示,图中有两个可能的编辑序列(History A 和 History B)。经过两次编辑后,两个序列都有了相同的编码状态(State 2),但 History A 正在给 foo 函数添加一个额外的参数,History B 正在从 foo 函数中移除第二个参数

研究者希望通过观察初始状态(State 0)和编辑序列(Edits 1 & 2)让模型具备预测 Edit 3 的能力。在 History A 的情况下,要插入的特定值是不明确的,但是在该位置插入某个值这一事实应该具有相当高的置信度。

图 1:两个编辑序列图示。History A 和 History B 共享相同的 State 2,但根据以往经验,History A 更有可能通过修改对 foo 函数的调用来获取一个额外的参数,History B 更有可能通过修改 foo 的定义来获取一个参数

因此在谷歌大脑的这篇研究中,神经网络需要学习不同的编辑序列及编辑内容,从而在给定编辑序列的情况下,模型能知道后面该怎样继续「写代码」。这就和语言模型一样,给定一小段话,模型就能接着用自然语言「编下去」。

谷歌大脑的解决方案

编辑建模序列的主要挑战是如何开发良好的表征,既能捕捉所需的意图信息,又能优雅地缩放序列长度。研究者考虑了两种编辑表征:显式表征和隐式表征。

显式表征明确实例化序列中每一次编辑的状态结果,而隐式表征实例化完整的初始状态以及更紧凑的类 diff 表征中的后续编辑。在显式表征中,研究者将层级递归指针网络模型视为一个强大但计算昂贵的基线。

在隐式表征中,研究者考虑一个简单的序列到序列模型以及一个基于注意力的双向模型,后者拥有一个生成编辑位置的指针网络 head 和一个生成编辑内容的内容 head。这些模型显示了源自不同问题公式化之间的权衡,并为将来的编辑序列模型提供设计方案。

在精心设计的合成数据以及对 Python 源代码进行细粒度编辑的大规模数据集中,研究者根据模型观察一系列过去编辑的能力来评估模型的可扩展性和准确性,然后预测未来的编辑。

在制作合成数据集以评估模型的特定功能之后,研究者将注意力转移到真实数据。研究者根据开发实际代码的专业开发人员创建的谷歌代码库构建了一个大型编辑序列数据集。

开发人员每保存一份文件,就会创建一份静态代码状态,由此生成比典型 Git commit 等更细的粒度。研究者对不同模型观察以往编辑和预测未来编辑的能力进行可扩展性和准确性评估。

结果显示,双向注意力模型特别能够在真实数据中实现高准确率、精准置信度和较好的可扩展性,这使得研究者对开发者工具的前景保持乐观,而这些工具在开发人员对大型和真实代码库进行编辑时学习提取他们的意图。

总之,本文将研究从编辑序列中学习和预测编辑的问题,是对模型空间的初步探索,此外还展示了从开发者编辑源代码过程中学习的适用性。

论文:NEURAL NETWORKS FOR MODELING SOURCE CODE EDITS

论文地址:https://arxiv.org/pdf/1904.02818.pdf

摘要:编程语言正成为机器学习中一个充满挑战与趣味的领域。其核心任务是构建源代码的生成模型,这一任务近年来已受到大量关注。

但是,就目前所知,以前的生成模型总是生成静态代码片段。在本文中,我们将源代码视作动态目标,要解决的问题是建模软件工程师对源代码文件进行的编辑。

解决上述问题需要从先前的编辑中提取意图,然后利用它来生成后续编辑。我们开发了几个神经网络,并利用合成数据来测试它们学习编辑模式的能力,而这需要很强的泛化能力。然后我们收集并在谷歌源代码的大型数据集上训练了我们的模型,该源代码包含来自数千 Python 开发者的数百万次细粒度编辑。

从建模的角度来看,我们的主要结论是注意力和指针网络组件的新组合提供了最好的整体性能和可扩展性。而从应用角度来看,我们的结果表明,开发工具以学习预测未来的编辑是可行的。

模型方法

第一个要思考的问题是我们该如何表征编辑代码的序列数据。我们定义了两种数据格式,它们各有各的权衡。下图 2(a) 所示为显式格式,它将编辑序列以二维网格的形式表示为序列的序列,横纵坐标分别为两种序列。这种格式的预测任务会根据前面 t-1 行的编辑序列预测第 t 个时间步的编辑位置与内容。

图 2:编辑序列的显式和隐式表征,它们都将「BACA」转换为「BABBCACC」,其中<S>和<E>分别为起始和终止符。

如上图 2(b) 所示,隐式格式将初始状态表示为一个 Token 序列,并将其作为(position, content)对进行编辑。

根据两种数据表征格式,现在我们有基线显式模型和基线隐式模型。其中基线显式模型是一个两阶段的 LSTM 网络,有点类似于层级 RNN 模型。

在最简单的基线显式模型中,第一阶段的 LSTM 会并行地编码每一个状态序列,并产生隐藏状态;而第二阶段的 LSTM 会将前面的隐藏状态和已观察到的编辑序列作为输入,并产生解码的隐藏状态和输出状态。下图 3(a) 有一个更形象的展示。

而基线隐式模型最自然的方式就是使用 Seq2Seq 框架,将初始状态序列输入到编码器中,并期待解码器输出(position, content)对。

图 3:(a):基线显式模型;(b, c)隐式注意力模型。

除了基线模型,更强大的是隐式注意力模型,该模型能对隐式表征进行操作,并能更好地捕捉到编辑内容和编辑上下文之间的关系序列。隐式注意力模型的编码器和解码器在上图 3(b, c) 中展示,其中编码器会将初始状态和所有已知编辑编码为隐藏向量,解码器会将其解码为每一个编辑的位置、以及给定位置的编辑内容。该模型的细节见原论文的附录,它参考了 Transformer 的位置编码与 Multi-head Attention(MHA)。

实验

实验的目标是了解模型的能力和限制。两个主要的因素是,模型能够多准确地识别编辑序列中的模式?它对大型数据的适应效果如何?

表 1 中报告了能够产生最佳开发性能的步骤和超参数设置的测试性能。显式模型和改进的隐式模型几乎可以解决所有任务,甚至是那些涉及元字符和具有较长替换序列的任务。

表 1:具有最佳开发性能的步骤和超参数设置在合成数据集上的测试准确率准确率在.5% 以内的结果用粗体显示。POMP:Position-Oracle Match-Pattern;E:显式基线模型;IR:隐式基线模型;IA:改进的隐式模型。

如图 4 所示,显式模型始终比隐式模型要昂贵,而且随着数据的增加,这个差距也在拉大。长度为 100 的插入序列比真实数据集中的序列小十倍,但在运行时方面已经存在一个数量级的差异。

图 4:(a)-(c):具有不同插入数量(10,50,100)的 n 元问题的训练过程中处理序列所需的时间。注意,每个图的 y 轴刻度不同。(d):把预测限制到模型置信度最高时,模型在真实数据集上的 Token 级别准确率

理论机器学习谷歌大脑自动编程编程
1
相关数据
OpenAI 机构

OpenAI是一家非营利性人工智能研究公司,旨在以惠及全人类的方式促进和发展友好的人工智能。OpenAI成立于2015年底,总部位于旧金山,旨在通过向公众开放其专利和研究与其他机构和研究人员“自由合作”。创始人的部分动机是出于对通用人工智能风险的担忧。

https://www.openai.com/
机器学习技术

机器学习是人工智能的一个分支,是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、计算复杂性理论等多门学科。机器学习理论主要是设计和分析一些让计算机可以自动“学习”的算法。因为学习算法中涉及了大量的统计学理论,机器学习与推断统计学联系尤为密切,也被称为统计学习理论。算法设计方面,机器学习理论关注可以实现的,行之有效的学习算法。

重构技术

代码重构(英语:Code refactoring)指对软件代码做任何更动以增加可读性或者简化结构而不影响输出结果。 软件重构需要借助工具完成,重构工具能够修改代码同时修改所有引用该代码的地方。在极限编程的方法学中,重构需要单元测试来支持。

参数技术

在数学和统计学裡,参数(英语:parameter)是使用通用变量来建立函数和变量之间关系(当这种关系很难用方程来阐述时)的一个数量。

超参数技术

在机器学习中,超参数是在学习过程开始之前设置其值的参数。 相反,其他参数的值是通过训练得出的。 不同的模型训练算法需要不同的超参数,一些简单的算法(如普通最小二乘回归)不需要。 给定这些超参数,训练算法从数据中学习参数。相同种类的机器学习模型可能需要不同的超参数来适应不同的数据模式,并且必须对其进行调整以便模型能够最优地解决机器学习问题。 在实际应用中一般需要对超参数进行优化,以找到一个超参数元组(tuple),由这些超参数元组形成一个最优化模型,该模型可以将在给定的独立数据上预定义的损失函数最小化。

神经网络技术

(人工)神经网络是一种起源于 20 世纪 50 年代的监督式机器学习模型,那时候研究者构想了「感知器(perceptron)」的想法。这一领域的研究者通常被称为「联结主义者(Connectionist)」,因为这种模型模拟了人脑的功能。神经网络模型通常是通过反向传播算法应用梯度下降训练的。目前神经网络有两大主要类型,它们都是前馈神经网络:卷积神经网络(CNN)和循环神经网络(RNN),其中 RNN 又包含长短期记忆(LSTM)、门控循环单元(GRU)等等。深度学习是一种主要应用于神经网络帮助其取得更好结果的技术。尽管神经网络主要用于监督学习,但也有一些为无监督学习设计的变体,比如自动编码器和生成对抗网络(GAN)。

准确率技术

分类模型的正确预测所占的比例。在多类别分类中,准确率的定义为:正确的预测数/样本总数。 在二元分类中,准确率的定义为:(真正例数+真负例数)/样本总数

逻辑技术

人工智能领域用逻辑来理解智能推理问题;它可以提供用于分析编程语言的技术,也可用作分析、表征知识或编程的工具。目前人们常用的逻辑分支有命题逻辑(Propositional Logic )以及一阶逻辑(FOL)等谓词逻辑。

生成模型技术

在概率统计理论中, 生成模型是指能够随机生成观测数据的模型,尤其是在给定某些隐含参数的条件下。 它给观测值和标注数据序列指定一个联合概率分布。 在机器学习中,生成模型可以用来直接对数据建模(例如根据某个变量的概率密度函数进行数据采样),也可以用来建立变量间的条件概率分布。

序列到序列技术

深度神经网络技术

深度神经网络(DNN)是深度学习的一种框架,它是一种具备至少一个隐层的神经网络。与浅层神经网络类似,深度神经网络也能够为复杂非线性系统提供建模,但多出的层次为模型提供了更高的抽象层次,因而提高了模型的能力。

语言模型技术

语言模型经常使用在许多自然语言处理方面的应用,如语音识别,机器翻译,词性标注,句法分析和资讯检索。由于字词与句子都是任意组合的长度,因此在训练过的语言模型中会出现未曾出现的字串(资料稀疏的问题),也使得在语料库中估算字串的机率变得很困难,这也是要使用近似的平滑n元语法(N-gram)模型之原因。

GPT-2技术

GPT-2是OpenAI于2019年2月发布的基于 transformer 的大型语言模型,包含 15 亿参数、在一个 800 万网页数据集上训练而成。据介绍,该模型是对 GPT 模型的直接扩展,在超出 10 倍的数据量上进行训练,参数量也多出了 10 倍。在性能方面,该模型能够生产连贯的文本段落,在许多语言建模基准上取得了 SOTA 表现。而且该模型在没有任务特定训练的情况下,能够做到初步的阅读理解、机器翻译、问答和自动摘要。

推荐文章
暂无评论
暂无评论~