摘要
随着互联网产业的迅速发展,各式各样的软件出现在了我们的社会中,其中程序开发人员为了开发和维护这些软件花费了大量的时间。据统计,在软件开发周期中,编程的时间占了软件开发过程的 39%-48%。而在近几年中,软件的架构变得越来越复杂,这也给他们带来了极大的研发效率的挑战。因此,一种可以自动的理解代码并辅助他们提高编程效率的工具成为了迫切需求。代码理解模型可以辅助于软件开发的多个过程如代码注释生成可以为代码自动生成注释,缺陷检测帮助判断代码中是否存在漏洞,而代码分类则可以根据代码的功能进行分类,有利于软件的维护过程。 相比于自然语言,代码拥有着丰富的结构信息,如代码的数据流,控制流等。而在现有研究中,大部分代码理解模型直接将代码视作自然语言送入模型中进行预测而忽略了代码中丰富的结构信息。特别是在基于 Transformer 的模型中,如何结合代码的结构信息并没有得到充分的探究。除此之外,以往的工作表明代码理解模型容易受到变量名的误导而预测错误,但是同样代码变量名中也包含了丰富的语义信息,直接做代码抽象丢弃这部分信息会对模型的精度造成较大的损失。针对以上两个问题,本文分别提出了基于结构化注意力机制的代码理解模型和基于反事实推理的鲁棒的代码理解模型。 在基于结构化注意力机制的代码理解模型中,本文基于局部的代码结构信息(如字符和语句)和全局的语法信息(如数据流图)提取了一些程序中符号间的成对的关系,并把它们表示为邻接矩阵的形式加入到了 Transformer 的多头自注意力模块中作为神经网络的归纳偏置。同时为了进一步利用不同类型信息的的层次特征,本文还将局部结构信息和全局结构信息分别分布在低层和高层的注意力头中,让底层的注意力头更多地注意局部的信息,高层的注意力头更多的注意全局的信息。实验表明本文提出的模型相比于现有最好的模型两个常用的数据集上分别提升了 1.4% 和 2.0%。 虽然上一部分的工作可以提高模型的准确性,但模型还面临着鲁棒性差的问题。在基于反事实推理的鲁棒的代码理解模型中,本文通过对代码理解模型的预测过程使用结构因果模型进行建模,提出了一个基于因果推理的框架,用于更好的利用代码理解模型中的变量名的作用。在训练阶段,该框架通过多任务学习区分并捕获变量名对模型预测的直接效应和间接效应。在推理阶段,该框架通过减少预测中的来自变量名的直接效应来消除变量名中误导性信息的影响。实验结果表明,使用了该框架的的模型不仅取得了准确性的提升,也取得了极大的鲁棒性的提升。具体来说 CREAM 在函数命名、缺陷检测和代码分类上将提升了现有模型 0.5%,0.9% 和 0.3% 的准确性 37.9%,8.3% 和 1.9% 的鲁棒性。