「将类似 i = i + 1 的语句替换为 i++」,「好的,已替换~」
IDE 除了检查语法错误或拼写错误,能不能更高级一点?借助深度学习,代码编辑能更智能,编辑器也能理解一些高级语义。在这篇文章中,CMU 和微软的研究者介绍了一篇 ICLR 2019 的新研究,它只需要输入一些高级语义,编辑器就能自动改改代码。
「这是我的顶会论文—你觉得如何?」经过数小时麻烦的文字输入和图片插入后,分享初稿的时刻你感到非常自豪。但没过多久,你可能就会有打脸的感觉,你的同事给你反馈时进行了大量的编辑。
这些编辑很多只是简单的语法、风格修正或添加引用,这些反馈的小建议并不如论文实质内容那样令人高兴或有价值。例如指出单词拼写错误等操作,最基础的反馈形式已经实现了自动化。但是,那些更复杂的编辑任务能否也实现自动化呢?
特别适合探究该问题的一个领域是源代码编辑(source code editing)。利用先进的控制工具和重构工具,源代码仓库为训练和测试深度学习模型提供大量数据,以研究如何表征、发现和应用编辑。在 ICLR 2019 大会论文《Learning to Represent Edits》中,微软利用这些资源创建无监督深度学习模型,该模型在代码和自然语言领域生成合理编辑过程显示出了良好的前景。
论文:LEARNING TO REPRESENT EDITS
论文链接:https://openreview.net/pdf?id=BJl6AjC5F7
学习编辑表征
深度学习在生成和理解自然语言、源代码等方面已经取得了很多成果,它们在很多方面都达到了当前最优性能。而在微软的这项研究工作中,主要挑战在于设计一种专门编码「编辑(edits)」的方法,以使编辑过程能通过深度学习技术自动处理。
为了理解研究者提出来的方法,我们可以思考下面的类比:
若一台复印机有大量设定,例如黑白或彩印的选择、放大或缩小文本等等。我们可以将这些设定的组合表示为一个向量,这里为简单起见可以表示为Δ,它描述了复印机各种按钮与开关。在配置Δ下复制原文档 x-可以得到新文档 x+,在这过程中会发生很多编辑过程,例如将彩色转换为黑白。编辑本身会应用到复印机上,而Δ只是这些编辑的高级表示。也就是说,Δ编码「输出一份黑白复印」的语义信息,复印机再解码这些编码,并生成底层指令来调整内部引擎。
若将前面的概念转换到源代码或自然语言编辑后,复印机就类比于神经网络,编辑表征Δ就表示提供给神经网路的低维向量。我们可以限制该向量的表示能力,从而鼓励系统学习编码「编辑」的高级语义信息。例如,学习「将输出转化为黑白复印」,而不是学习低维语义信息:「令像素 (0, 0) 为白色、像素 (0, 1) 为黑色...」。
这意味着,给定两个不同的输入文档 x- 和 x-',如下源代码所示,Δ 应该执行相似的编辑:
低维向量Δ的表示能力会受到限制,从而鼓励编辑器或神经网络学习编码「编辑」的高级语义信息。
在这个案例中,Δ表示了语义编辑:「将 v0.projectIds 计数为零的断言(assertion)替换为断言 v0.projectIds 为空(emptiness)」。
到目前为止,我们已经描述了一个编辑器网络,它可以在给定表征向量Δ的情况下完成编辑。但是我们又该如何学会将观察到的编辑转化为高级表征Δ呢?
这类似于学习复印机上的各种按钮与开关,而且还不需要任何开关的标注。为了完成这些过程,研究者收集了一个包含编辑过程的数据集,即原来的 x-与编辑后的 x+。对于源代码编辑,研究者根据 GitHub 上的开源代码 commit 记录,创建了一个新的数据集。对于自然语言编辑,研究者使用的是已存的 Wikipedia edits。
收集这些数据集后,研究者就可以使用第二个神经网络计算编辑表征Δ,它的输入和标注分别是 x-和 x+,这个神经网络被称为编辑编码器。
编辑器和编辑编码器可以联合训练。研究者要求整个系统来计算编辑表征Δ,所以编辑器能使用Δ和 x-重建 tilde x+,重建出来的代码需要基本等同于原始 x+。因此,编辑编码器和编辑器能相互适应,从而通过Δ传递有意义的编辑信息。
为了将观察到的编辑转化为高级表征Δ,研究者需要联合训练两个神经网络,即编辑器网络和编辑编码网络。
探索学习到的表征
既然我们能够在低纬向量空间中表征编辑,则可以开始解决最初的问题了:哪些更复杂的编辑任务可以实现自动化?
回答该问题的第一步是探究我们的系统是否可以学会区分不同种类的编辑。为此,微软的研究者在 90,000 条 C# 代码编辑中训练该系统,之后使用训练的编辑编码器(edit encoder)对 3,000 个特殊标记的编辑进行编码。在标签集中,每个编辑都是从 16 条手写的代码重构规则(被称为 Roslyn fixer)中生成的。
例如,其中模板之一是 RCS1089,其描述为「使用++/– 算子替代运算语句」。当应用时,该 fixer 以「x++」替代「x = x + 1」等语句。我们为每个标记编辑收集编辑编码器生成的编辑表征Δ,并且使用 t-SNE 投影在 2D 中可视化这些向量;在下图中,每个点的颜色表示该点是由哪个 fixer 生成的。
微软观察到,大多数编辑根据应用的代码重构规则正确地聚集在一起,表明该编辑编码器在分配类似表征Δ给类似语义编辑以及区分不同种类的编辑方面表现良好。
编辑编码器利用 16 个手动代码重构规则生成编辑的 tSNE 可视化结果,该编码器能够将类似表征分配给类似语义编辑。每个点的颜色表示该点是由哪个 fixer 生成的。
研究者在自然语言的编辑中也观察到了类似结果。微软的系统将语义上有意义的编辑聚集在一起。例如,当系统在 Wikipedia edits 中进行训练时,其中一个编辑集群表示在句子中添加「on the moon」和「in the market」等介词短语,另一个表示在人名中添加中间名。
应用学习到的编辑
微软认为,当分析了大量的编辑语料库并确定了编辑集群之后,就可以从集群形心中提取出规范的编辑向量,并将其应用到新文档中,从而生成能将编辑过程自动化的建议。为了检验这种想法是否可行,微软再次转向由 Roslyn fixer 生成的编辑数据库。
为了评估将编辑表征迁移到新语境中的效果,研究者考虑了两对编辑:x-和 x+以及 y-和 y+。他们从第一对编辑中计算出一个编辑表征 Δ,然后让编辑器将其应用到 y-中。例如,考虑将「x=x+1」替换为「x++」的编辑,然后尝试将得到的编辑表征应用到「foo=foo+1」。他们在实验中发现,50% 的样本中的编辑结果可以与预期编辑结果相匹配。然而,由于编辑的复杂程度有所差别,匹配的准确率也有很大差异。例如,在 RCS1089 fixer 生成的样本中,匹配准确率是 96%,但在 RCS1197 生成的样本中,准确率只有 5%。
尽管微软的 ICLR 论文已经探索了文本和代码中的编辑表征问题,但他们展示出的方法还只是一个开始。该方法的应用潜力令人振奋:从数万名专业编辑、软件工程师和设计师的作品中学到的文本、代码或图像的自动改进。也许,当你下次再把自己的论文拿给同事编辑的时候,你会感觉非常自豪。
原文链接:https://www.microsoft.com/en-us/research/blog/beyond-spell-checkers-enhancing-the-editing-process-with-deep-learning/