Facebook发布TransCoder:神经网络编译器实现高级编程语言自动转换

作者 |玉英、冬梅

Facebook发布TransCoder:神经网络编译器实现高级编程语言自动转换

最近,Facebook 研究人员表示,他们开发了一种神经网络编译器,可以将代码从一种高级编程语言(例如 C++、Java 和 Python)转换为另一种高级编程语言。

Facebook 正式发布 TransCoder

在过去的IT技术变革历史中,有很多将代码库迁移到主流或更高效的语言(例如Java或C++)的案例,这需要开发人员具备源语言和目标语言的专业知识,而且成本往往非常高。例如,澳大利亚联邦银行在五年内花费了大约 7.5 亿美元将其平台从 COBOL 转换为 Java。超级编译器在理论上可以提供帮助,它们消除了从头开始重写代码的过程,但在实践中它们很难应用,因为不同的语言可能有不同的语法,并且依赖于不同的平台 API、标准库函数和变量类型。

为了简化这个问题,Facebook 推出了 TransCoder,这是一个使用无监督学习在 C++、Java 和 Python 之间转换代码的工具。

论文地址:

据研究人员称,TransCoder 在实验过程中展示了对每种语言特定的语法、数据结构和方法的理解,并在跨编程语言之间正确对齐库,同时适应较小的修改(例如,当输入被重命名时)。虽然它并不完美,例如 TransCoder 在生成时没有考虑某些变量类型,但其性能仍然优于某些框架。

该工具的合著者之一写道: TransCoder 可以轻松推广到任何编程语言,不需要任何专业知识,并且在很大程度上优于商业解决方案。我们的结果表明,通过向解码器添加简单的约束以确保生成的函数在语法上正确,或者使用专门的架构,可以轻松解决该模型所犯的许多错误。

模型

对于 TransCoder,Facebook 考虑了带有注意力机制的 seq2seq 模型,该模型由编码器和带有 Transformer 架构的解码器组成。所有编程语言共享相同的模型,该模型使用 Lample 等人定义的无监督机器翻译的三个原则进行训练,即初始化、语言建模和反向翻译。本节总结了这些原则,并详细介绍了如何在示例中编译编程语言(下面的图 1 给出了该方法的说明)。

交叉编程语言模型预训练

预训练是无监督机器翻译Lample的重要组成部分。它确保具有相似含义的序列被映射到相同的潜在表示,无论它们使用哪种编程语言。最初,预训练是通过使用跨语言词汇表示初始化模型来完成的。在无监督的英语-法语翻译的上下文中,“cat”一词的嵌入与其法语翻译“chat”的嵌入接近。跨语言词嵌入可以通过训练单语言词嵌入并让这些嵌入以无监督的方式进行训练来获得。

随后的工作表明,以跨语言方式预训练整个模型(而不仅仅是词汇表示)可以显着改进无监督机器翻译。特别是,当遵循 Lample 和 Conneau 的预训练原则进行训练时,即使用屏蔽语言建模目标在单语言源代码数据库上预训练跨语言模型(XLM)时,效果尤其明显。

所得模型的跨语言性质来自于跨语言存在的大量共同标记(锚点)。在英法翻译中,锚点基本上由数字、城市和名称组成。在编程语言中,这些锚点通常由常见关键字(例如 for、while、if、try)组成,但也包括源代码中出现的数字、数学运算符和英文字符串。

对于屏蔽语言建模 (MLM) 目标,在每次迭代时,Facebook 都会考虑源代码序列的输入流,随机屏蔽一些标记,并训练 TransCoder 根据上下文预测被屏蔽的标记。在不同语言的批流之间来回切换使模型能够创建高质量、跨语言的序列表示。图 1 显示了 XLM 预训练的示例。

图1

此方法中使用的无监督机器翻译的三个原则的说明。第一个原则是用跨语言掩码语言模型预训练来初始化模型。因此,无论使用哪种编程语言,表达相同指令的代码块都会被映射到相同的表示形式。第二个原理是去噪自动编码,训练解码器始终生成有效序列,即使输入是噪声数据,这可以提高编码器对输入噪声的鲁棒性。最后一个原则是反向翻译,它允许模型生成可用于训练的并行数据。当Python语言模型在转换为C++语言模型时表现更好时,它会为C++ → Python模型生成更准确的数据,反之亦然。

去噪自动编码

Facebook使用上面提到的预训练的XLM模型来初始化seq2seq模型的编码器和解码器。编码器的初始化很简单,因为其架构与 XLM 模型相同。然而,Transformer 解码器有一些与源注意机制相关的附加参数。根据 Lample 和 Conneau 的说法,这些参数是随机初始化的。

XLM 预训练使 seq2seq 模型能够生成高质量的输入序列表示。然而,由于解码器从未经过训练来根据源表示解码序列,因此它缺乏翻译功能。为了解决这个问题,Facebook 的目标是去噪自动编码 (DAE) 来训练模型来编码和解码序列。 DAE 目标的运行方式类似于监督机器翻译算法,可以使用该算法训练模型来预测给定的损坏的标记序列。为了破坏序列,可以使用相同的噪声模型,如 Lample 等人所述。即,随机遮挡、删除和打乱这些输入令牌。

输入到解码器的第一个符号是一个特殊的标记,指示输出的编程语言。在测试时,Python 序列可以由模型进行编码,并使用 C++ 起始符号进行解码,从而生成 C++ 翻译。 C++ 翻译的质量将取决于模型的“跨语言能力”:如果编码器将 Python 函数和有效的 C++ 翻译映射到相同的潜在表示,则解码器将成功生成 C++ 翻译。 DAE 目标还训练模型的“语言建模”能力,这意味着虽然编码器的输出有时有噪声,但 Facebook 总是训练解码器生成有效的函数。此外,这种方法还训练编码器对输入噪声具有鲁棒性,这在反向翻译的背景下非常有用,其中模型是在有噪声的输入序列上进行训练的。图 1 说明了 DAE。

回译

在实践中,仅 XLM 预训练和去噪自动编码就足以生成翻译。然而,这些翻译的质量通常较低,因为模型在测试时(即,将函数从一种语言翻译为另一种语言)时的表现不如预期。为了解决这个问题,Facebook 引入了反向翻译,这是在弱监督场景中利用单语言数据的最有效方法之一。反向翻译最初是为了提高监督环境中机器翻译的性能而引入的。后来发现反向翻译已经成为无监督机器翻译的重要组成部分。在无监督环境中,源到目标模型与并行训练的反向目标到源模型相结合。目标到源模型用于将目标序列翻译成源语言,产生与实际目标序列相对应的噪声源序列。然而,源到目标模型以弱监督的方式进行训练,以从目标到源模型生成的噪声源序列重建目标序列,反之亦然。这两个模型并行训练,直到实现收敛。图 1 显示了反向翻译的示例。

实验

培训详情

Facebook 使用 6 层、8 个注意力头,并将模型维度设置为 1024。对于所有编程语言,我们使用单个编码器和解码器。 XLM预训练期间,在C++、Java和Python之间进行转换,由32个源代码序列、512个token组成。在训练过程中,我们交替使用去噪自动编码器和反向翻译目标,使用多批总共约 6000 个标记。 Facebook 使用 Adam 来优化 TransCoder,学习率为 10^(−4),并使用与 Vaswani 等人相同的学习率调度器。 Facebook 在 PyTorch 中实现了该模型,并在 32 个 V100 GPU 上对其进行训练,使用 float16 运算来加快训练速度并减少模型的内存使用量。

训练数据

Facebook 通过 Google BigQuery4 获取了 GitHub 公共数据集,其中包含超过 280 万个开源 GitHub 存储库,过滤了许可证明确允许重新分发的项目,并选择了其中的 C++、Java 和 Python 文件。理想情况下,转编译器应该能够翻译整个项目。在这项工作中,Facebook决定在功能层面进行转型。与文件或类不同,函数足够短,可以放入单个批次中,并且在函数级别,可以通过单元测试更简单地评估模型。 Facebook 在所有可用的源代码上对 TransCoder 进行预训练,并仅在函数上对自动编码和反向翻译目标进行去噪,以获得有关提取的特征和训练集统计数据的更多详细信息。 Facebook 进行了一项消融研究,以确定是保留还是删除源代码中的评论更好。在源代码中保留注释可以增加跨语言的锚点数量,从而提高整体性能。因此,Facebook 将它们保留在最终的数据集和实验中。

预处理

最近的多语言自然语言处理方法倾向于使用通用标记器和跨所有语言的共享词汇表,这减少了总体词汇量并最大化了语言之间的标记重叠,从而提高了模型的跨语言性质。在这个实验中,通用令牌生成器并不是最佳的,因为不同的语言使用不同的模式和关键字。逻辑运算符 && 和 ||存在于 C++ 中,应单独标记,但不存在于 Python 中。缩进在Python中很重要,因为它们定义了代码结构,但在C++或Java等语言中没有任何意义。 Facebook 使用 Java 中的 javalang 分词器、Python 标准库的分词器以及 C++ 中的 clang 分词器。这些标记器确保代码中无意义的修改(例如,添加额外的新行或空格)不会对标记化序列产生任何影响。 Facebook 学习提取的令牌上的 BPE 代码,并将它们分成子单元。

评价

GeeksforGeeks 是一个在线平台,包含与计算机科学和编程相关的文章。它收集了许多编码问题并提供了多种编程语言的解决方案。 Facebook 从这些解决方案中提取了一组 C++、Java 和 Python 并行函数来创建验证和测试集。这些函数不仅返回相同的输出,而且使用类似的算法来计算结果。下图显示了 C++、Java 和 Python 并行函数的示例,该函数确定字符串表示的整数是否能被 13 整除。

图 2:显示无监督的 Python 到 C++ 转换

大多数源代码转换研究使用 BLEU 来评估生成的函数 [1,10,22,36] 或其他指标(基于翻译和参考中标记之间的重叠)。一个简单的衡量标准是计算参考匹配,即与真实结果的匹配。这些指标的局限性在于它们没有考虑语法的正确性。微小的语法差异可以获得高分,并且它们可能导致完全不同的编译和计算输出。 。相反,具有不同实现的语义等效程序将具有较低的 BLEU 分数。相反,Facebook 引入了一种新的指标,即计算精度,它评估在给定相同输入的情况下,转换后的函数是否会产生与参考函数相同的输出。如果每个输入给出与参考相同的输出,则认为转换是正确的。

验证集和测试集中具有单元测试的函数数量

结果

表 1 报告了测试集的结果。表 2 报告了使用波束搜索进行解码的结果,并将 TransCoder 与现有基线进行了比较。图 2 给出了从 Python 到 C++ 的无监督翻译的示例。

评估指标之间的差异。在表1中,Facebook发现大多数翻译与参考不同,尽管它们成功通过了单元测试,但与参考匹配指标相比,这些翻译被认为是无效的。例如,当从 C++ 翻译为 Java 时,虽然 60.9% 的翻译符合预期,但只有 3.1% 的生成结果与实际参考完全相同。另外,其在BLEU上的表现也一般,与计算精度相关性不大。测试结果表明,该方法与该领域常用的传统参考匹配指标和BLEU指标相比存在一些问题。

波束搜索解码。在表 2 中,Facebook 研究了集束搜索的影响,要么考虑束中通过单元测试的所有假设 (Beam N),要么只考虑具有最高对数概率的假设 (Beam N - Top 1)。与贪婪解码(Beam 1)相比,beam search 显着提高了计算精度,将 Beam 25 Java → Python 的计算精度提高了 33.7%。当模型仅返回具有最高对数概率的假设时,性能会下降,这表明 TransCoder 经常找到有效的翻译,尽管它有时会为不正确的假设提供更高的对数概率。给出了通过波束搜索进行纠错的解释。

表 1:TransCoder 在测试集上的贪婪解码结果。

表2:Beam search解码计算精度总和以及与Baseline的比较

在实际用例中,检查生成的函数在语法上是否正确并已编译,或者从输入函数创建单元测试是比比较对数概率更好的方法。附录中的表 5 显示,当目标语言为 Java 或 C++ 时,编译错误是测试失败的主要原因之一。这表明“Beam N - Top 1”指标可以轻松改进。

与现有基线相比。 Facebook 将 TransCoder 与两种现有方法进行了比较:j2py10,一个从 Java 转换为 Python 的框架;第二个是来自 Tangible Software Solutions11 的商业解决方案,可将 C++ 转换为 Java。这两个系统都依赖于用专业知识手动构建的重写规则。后者处理各种元素的转换,包括核心类型、数组、一些集合(向量和映射)和 lambda。

在表 2 中,Facebook 观察到 TransCoder 在计算精度方面明显优于两个基线。从C++到Java的计算准确率可以达到74.8%,从Java到Python的计算准确率可以达到68.7%。基线在这里 两个变换的计算精度分别为 61% 和 38.3%。 TransCoder 在翻译标准库中的函数时表现尤其出色。在基于规则的编译转换器中,需要为每个标准库函数手动编码重写规则,而 TransCoder 以无监督的方式学习这些规则。下图介绍了几个TransCoder成功的例子,而baseline却无法生成正确的翻译。

图 3:不正确的基线翻译和正确的 TransCoder 翻译的示例

结论

事实上,Facebook 并不是唯一一家开发代码生成系统的组织。在今年早些时候的 Microsoft Build 大会上,OpenAI 展示了一个在 GitHub 存储库上训练的模型,该模型使用英文注释生成完整的功能。两年前,莱斯大学的研究人员创建了一个名为 Bayou 的系统,该系统通过关联公共代码背后的“意图”来实现自主软件编程。

论文地址:

推荐活动

美团点评拥有丰富的吃喝玩乐全场景数据,利用跨场景的数据挖掘、建图、聚合、关联,构建了庞大的生活服务知识图谱——“美团大脑”。这个知识图谱可以促进各场景应用服务的智能化升级。点击“阅读原文”,来到AICon Shanghai 2020,学习如何在新零售场景下构建和实现知识图谱。会议门票限时优惠 20%。欢迎咨询票务小姐:18514549229(微信同号)。

今天的推荐

点击下图阅读

台积电最新回应:若无法向华为出售芯片,将尽快填补订单缺口

你也在“看”吗?

你可能想看:
« 上一篇
下一篇 »

相关推荐

java中什么是冒泡,冒泡算法

2026年09月06日

27阅读

java中冒号,java双冒号

2026年09月06日

25阅读

java中的->,java中的是什么意思

2026年09月06日

24阅读

java中的super用法,Java中super的说明

2026年09月06日

27阅读

java中反射的应用,java中反射的应用场景

2026年09月06日

23阅读

java中开关的定义,Java关键字有哪些

2026年09月06日

25阅读