无监督方法实现C++、Java、Python 代码转换,程序员:出了bug怎么办,两种语言都要看吗?

Facebook 提出的无监督代码转换方法 TransCoder 能够以高准确率实现 C++、Java 和 Python 三种编程语言之间的函数转换。只需单语源代码,无需任何源语言或目标语言的专业知识。看起来很不错,不过也有人吐槽:出了 bug 怎么办?两种语言都要看吗?(瑟瑟发抖……

机器之心报道,参与:魔王。

想使用之前写的代码库但忧虑编程语言过时,想重写又嫌麻烦,怎么办?源到源编译器似乎是不错的选择。

transcompiler 系统,又称源到源编译器,可以将编程语言(如 C++ 或 Python)写成的源代码转换成另一种语言。此类工具主要为了提升互操作性,将用过时或废弃语言(如 COBOL、Python 2)写成的代码库移植到现代语言。它们通常依赖于手动编写的重写规则,并应用于源代码抽象语法树。

但是,transcompiler 存在一些缺陷,如转换结果通常缺乏可读性,无法遵循目标编程语言的规范,需要人类程序员进行手动修改才能准确运行。整个转换过程不仅耗时,还需要专家掌握源语言和目标语言的专业知识,因此这类代码转换项目的成本很高。

在自然语言翻译领域中,神经模型的性能大大超过基于规则的模型,但由于缺乏平行数据,神经模型在编程语言转换领域中的应用比较有限。那么,能否将自然语言翻译中的神经模型借鉴到编程语言转换中呢?近,Facebook AI 研究院做了一些尝试。

Facebook 研究人员利用无监督机器翻译方法,训练出一种无监督神经 transcompiler——TransCoder。TransCoder 基于 GitHub 开源项目中的源代码训练而成,能够以高准确率实现 C++、Java 和 Python 三种编程语言之间的函数转换。

如下图所示,TransCoder 将 Python 代码转换成了 C++ 代码:

TransCoder 成功地将 Python 输入函数 SumOfKsubArray 转换成了 C++。TransCoder 推断出参数、变量的类型和函数的返回类型,将 Python deque() 转换成了 C++ 中的 deque<>。此外,它还准确地转换了 Python 的 for loop 和 range 函数。

下图展示了 C++ 和 Java 之间的转换:

还有 Python 与其他语言之间的转换:

该方法具备以下特点:

  • 仅需单语源代码即可实现编程语言转换,无需任何源语言或目标语言的专业知识;
  • TransCoder 能够成功掌握每种语言的特定复杂模式,并将其迁移至其他语言;
  • 这一完全无监督方法在性能上大幅超过利用规则方法和编程知识的商业化系统。

此外,研究人员还构建和发布了一个包含 852 个平行函数的测试集,以及用于检查转换结果准确性的单元测试。研究人员表示,相关代码和预训练模型将开源。

测试集中的平行函数示例。

无监督编程语言转换神器——TransCoder

TransCoder 使用的是带注意力的 seq2seq 模型,由编码器、解码器和 transformer 架构组成。研究人员表示,对于所有编程语言,一个模型足矣

在训练方面,研究人员遵循 Lample 等人 [32] 提出的无监督机器翻译三原则,即初始化、语言建模和回译,如下图 1 所示:

图 1:TransCoder 使用的无监督机器翻译三原则图示。

原则一:初始化

个原则,即利用跨语言遮蔽语言模型预训练进行模型初始化。由此,将表达相同指令的代码段映射至相同的表示,而不用在意是何种编程语言。

原则二:语言建模

第二个原则利用去噪自编码(Denoising Auto-Encoding,DAE),训练解码器使之总能生成有效的序列,即使输入数据带有噪声也是如此。也就是说增强编码器对输入噪声的稳健性。

回译

第三个原则回译,即令模型生成可用于训练的平行数据。

举例来说,当 Python → C++ 模型质量不错时,用它为 C++ → Python 模型生成更的数据,反之亦然。

下图展示了训练后获得的跨语言嵌入表示:

图 5:跨语言 token 嵌入空间。

TransCoder 效果如何?

研究者进行了一系列实验,来评估 TransCoder 的效果。

具体而言,他们使用具备 6 个层、8 个注意力头的 transformer 架构,并将模型维度设置为 1024。此外,对所有编程语言均使用同一个编码器和解码器。

在跨语言语言模型预训练过程中,研究人员在 C++、Java 和 Python 这三种语言的批次中交替进行,它们由 32 个源代码序列构成,每个序列包含 512 个 token。

在训练阶段,研究人员和在去噪自编码和回译目标中交替进行,使用批大小约为 6000 个 token。

至于模型优化,研究人员使用的是 Adam 优化器,学习率为 10^−4,学习率调度器与 Vaswani 等人 [45] 相同。

在实验中,研究人员使用 PyTorch 实现模型,并在 32 块 V100 GPU 上进行训练;使用 16 位浮点运算,以加速模型训练,降低模型内存占用。

实验结果

该研究使用三个评估度量指标:BLEU 值、参考匹配(reference match)和计算准确率。BLEU 值用于评估生成函数的质量;参考匹配用于评估转换结果完美匹配真值参考的比例;计算准确率用于评估当输入相同时,假设函数是否生成与参考相同的输出。

下表 1 展示了 TransCoder 在测试集上的结果,模型使用了贪婪解码(集束大小为 1)。

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

下表 2 展示了使用束搜索解码后的结果,并对比了 TransCoder 和现有基线方法的性能。

看起来,效果很不错。

不过,也有程序员吐槽:

简直是 debug 的地狱,出了问题程序猿两种语言的代码都得看……


参考内容:

arxiv.org/abs/2006.0351

相关文章