Why My Code Summarization Model Does Not Work: Code Comment Improvement with Category Prediction论文阅读

在这里插入图片描述

目录

摘要

代码摘要旨在生成给定源代码块的代码注释,通常通过在现有代码块-注释对上训练机器学习算法来执行。代码注释在实践中有不同的意图。例如,一些代码注释可能解释方法是如何工作的,而另一些注释解释为什么要编写某些方法。以前的工作已经表明,在代码块和与其关联的注释类别之间存在关系。在本文中,我们的目标是研究我们可以在多大程度上利用这种关系来提高代码汇总性能。我们首先将注释分为六个意图类别,并手动标记20,000个代码-注释对。这些类别包括“什么”、“为什么”、“如何使用”、“如何完成”、“属性”和“其他”。基于此数据集,我们进行了一个实验来研究不同的最先进的代码摘要方法在类别上的性能。我们发现不同代码汇总方法的性能在不同的类别中有很大的不同。此外,对于不同的模型,代码摘要模型表现最好的类别是不同的。特别是,在六个类别中,没有模型对“为什么”和“属性”注释表现得最好。我们设计了一种复合方法来证明注释类别预测可以提高代码摘要以达到更好的结果。该方法利用分类代码-类别标记数据来训练分类器来推断类别。然后为推断的类别选择最合适的模型并输出合成结果。我们的复合方法优于其他不考虑评论类别的方法,在ROUGE-L和BLEU-4得分方面分别获得了8.57%和16.34%的相对改进。

1 INTRODUCTION

高质量的描述性文档,或代码摘要,对于软件开发和维护来说总是必不可少的,因为程序员平均花费58%的时间在源代码理解上[69]。软件文档,尤其是代码注释,在帮助开发人员理解源代码方面起着至关重要的作用。然而,记录源代码是一项劳动密集型任务[10,25],这增加了自动或半自动方法的必要性。

代码摘要生成源代码的自然语言描述,可以帮助开发人员获得高级概述,并帮助开发人员不必阅读整个源代码就能理解一段代码。总结代码可以看作是一种文档扩展[66],好的代码总结不仅可以在软件维护中保持代码和注释的一致性[23],还可以提高使用自然语言查询进行代码搜索的性能。

大多数代码摘要方法是基于学习的[2,8,9,20,22,24,63]或基于检索的[11,44,53,68],它们在通常由方法级源代码片段和相应注释组成的大型数据集上构建模型[3,8,20,21,63]。这种模型构建的方式假设一个足够大的数据集可以使模型在不同的场景下工作。

因此,他们追求代码-注释关系的一般表示,并对不同类型的注释使用相同的处理来执行代码汇总。然而,注释在实践中是复杂的。一方面,注释可以关注特定方面,而不是代码的完整描述。另一方面,注释不仅可以描述功能,还可以描述基本原理。例如,一些注释解释了业务逻辑而不是代码本身,描述了为什么要编写特定的代码段。然而,据我们所知,还没有关于不同类型的注释对代码总结的影响的调查。

为了探索不同类别的注释对代码摘要方法性能的影响,我们对从9714个项目中抓取的开源代码摘要数据集进行了实证研究[21]。我们将数据集分成三个数据集:训练数据用于训练代码摘要模型,验证数据用于验证注释分类对代码摘要的影响,测试数据用于自动评估我们的组合方法。我们调查的研究问题(RQ)如下。

首先,我们对验证数据进行手动注释分类。文献中对代码注释进行分类有几个标准[49,50,72]。我们遵循一个清晰而丰富的代码注释分类法,它由六个类别组成:“什么”(功能描述),“为什么”(为什么提供代码或代码的设计原理),“如何使用”(用法描述),“如何完成”(功能的实现细节),“属性”(解释代码的属性)和“其他”[72]。我们根据提出的分类标准手动标记由20,000个代码注释对组成的验证数据。我们按照编码程序[55]来保证标签的质量。贴标签过程是劳动密集型的;每小时,参与者平均可以标记57对。然后使用Fleiss Kappa值[13]来衡量参与者之间的一致性。Fleiss Kappa值为0.79,表明参与者的意见基本一致。通过这样的注释分类,我们可以进行代码汇总实验,探索类别之间的差异。

RQ1:不同的注释类别如何影响代码摘要性能?

然后,我们研究了衍生类别的六个最先进的总结模型,其中四个在SE文献中,两个在自然语言处理(NLP)文献中。为了公平比较,在使用相应作者提供的源代码检查可重复性之后,我们在上述相同的训练数据上训练所有模型。然后,我们分别评估每个类别的结果。我们发现每个类别之间存在显著差异。每个模型对特定评论类别的偏好是不同的。特别是,对于“为什么”和“属性”注释,没有模型表现得最好。此外,我们观察到没有模型在所有评论类别中占主导地位,这表明有可能结合不同模型的优势。

RQ2:我们如何使用注释类别来提高代码摘要的性能?

我们的目标是证明,通过对不同类别的注释进行不同的处理,我们可以提高代码摘要的性能。由于模型对不同的类别具有不同的性能,因此我们可以在推断评论类别的帮助下结合模型的优点。例如,如果推断的类别是“如何使用”,我们选择对该类别执行最好的模型来生成注释。因此,我们需要一个分类器来执行注释类别预测,它起着选择合适的代码汇总模型的作用。为此,我们基于我们的标记数据集(即验证数据)构建了几个分类器,包括Random Forest, LightGBM, Decision Tree, Naive Bayes,以及一个基于深度神经网络的分类器,其中Random Forest在10倍交叉验证中获得F1得分的最佳分数。然后,分类器选择应该用于特定类型评论的最佳模型。

通过对源代码进行分类,设计了一个复合模型来提高代码汇总性能。我们评估了复合模型在测试数据上的有效性,测试数据是未标记的,与验证数据和训练数据没有重叠。我们的复合模型优于其他不考虑评论类别的基本方法,并且在ROUGE-L方面获得了8.57%的相对改进,ROUGE-L已被证明与人类对摘要文本质量的评估高度相关[30],在BLEU-4分数方面获得了16.34%的相对改进,BLEU-4分数被广泛用于评估摘要质量。考虑到训练数据和测试数据的数据分布(例如,代码标记和自然语言单词的平均值和中位数)相似,我们还将我们的方法应用于外部数据集,该数据集建立在1,500个高质量Java项目上[67],并且具有不同的数据分布。结果表明,我们的模型也优于外部数据集的基线。

通过这种方式,我们证明了注释类别预测可以通过与当前方法相结合来提高代码摘要,从而达到更好的结果。

据我们所知,这项工作是第一个利用注释类别预测来提高源代码摘要的工作。综上所述,我们的贡献如下:

  • 我们将代码注释分为六类,并对其进行六种代码总结方法的实验,探讨注释类别对代码总结的影响
  • 我们设计了一个复合模型来提高代码摘要模型的性能,证明了注释类别预测对代码摘要任务的帮助。
  • 我们的研究表明,注释类别预测可以使代码总结在真实的开发场景中变得切实可行。

2、SET UP

2.1 Approach Overview

在这里插入图片描述

图1显示了RQ1中实证研究的概述和我们在RQ2中的复合方法。在这项工作中,我们采用Hu等[21]提供的数据集(训练数据、验证数据和测试数据)和Wen等[67]提供的数据集(外部数据,数据分布不同)。

对于RQ1,我们手动对由20,000个代码注释对组成的验证数据进行分类,并使用开放编码过程为它们标记类别。然后,我们在训练数据上训练不同的代码摘要模型,并进行实证研究,考察不同类别对代码摘要性能的影响。

对于RQ2,利用经验研究和标记数据,我们训练一个分类器来决定源代码片段的类别。分类器的工作是执行评论类别预测。然后,我们在相同的训练数据上训练代码汇总模型。根据每个模型在验证数据上的表现(即,哪个模型在特定类别中表现最好),我们的模型选择相应的模型来总结源代码。在这里,验证数据不仅扮演验证代码摘要模型的角色,而且还扮演为评论类别预测任务调优复合模型的角色。最后,我们在测试数据和外部数据上评估我们的组合模型,其中组合模型通过组合生成的注释并输出最终结果来工作。

2.2 Problem Formulation

代码总结是一项旨在总结源代码功能的任务。我们将这种映射形式化地描述为C→S,其中C是输入源代码,S是输出的自然语言摘要。

注释分类是对代码注释进行分类的过程,有助于提高程序的可理解性[49,50,72]。在本文中,我们将注释称为源代码的“摘要”,它是对该部分源代码的简短自然语言描述[42]。注释分类可以手动完成,也可以自动完成。

注释类别预测利用注释分类的结果来构建分类器并预测给定一段源代码的注释类别。它是软件工程中研究的一种源代码分类任务[7,35,60,61],它通过学习数据集中的源代码与注释类别之间的关系来构建模型

代码摘要的机制是挖掘现有代码注释对的信息,生成一般的注释。目前的方法是基于学习的[2,8,9,20,22,24,63]或基于检索的[18,53,68]。但是,它们对不同类别的注释使用相同的处理方法。因此,代码摘要模型如何处理不同类型的注释在文献中并没有被探讨。

2.3 Dataset Setup

我们使用Hu等人[21]提供的Java数据集,该数据集由GitHub中的9714个开源项目组成。数据由方法及其相应的注释(即成对的↓code,comment↔)组成,这些数据使用JDT1提取,并且粒度是方法级的。我们保留原始数据的分割方式;Hu等随机选取了20000对作为测试数据和验证数据,剩余的445,812对作为训练数据(三个数据集不是来自同一个项目)。以往的研究表明,同一项目的不同文件中经常存在重复的方法[3],这可能会导致数据从训练数据泄漏到测试数据的风险(即数据泄漏[26])。因此,训练数据、验证数据和测试数据不是来自同一个项目,彼此之间没有重叠。

在本文中,如图1所示,训练数据、验证数据、测试数据和外部数据的用途如下:训练数据用于训练代码汇总模型;验证数据用于识别注释类别,并验证这些类别的代码汇总模型(在第3节中描述);测试数据和外部数据用于在不同的数据分布上评估我们的复合模型(在第4节中描述)。

数据集的基本特征如下:我们把预处理源代码的基本单位称为标记,把摘要的基本单位称为字。表1描述了这三个数据的代码标记数、代码行数和自然语言单词数此外,我们计算数据集的统计数字(即最小值、第一季度、中位数、第三季度、最大值、标准差和平均值)。如表2所示,统计结果表明,数据集之间没有显著差异,这意味着拆分保证了每个数据集分布的一致性。此外,评论是精确的,因为中位数只有10。摘要词的标准差仅为6.9,远低于代码符号的标准差。

考虑到训练数据和测试数据的数据分布相似,我们还构建了一个数据分布不同的外部数据集来验证我们方法的性能。外部数据集基于1500个高质量的Java项目[67](与Hu等人的数据集无任何重叠)。我们使用相同的方法提取代码注释对,对其进行预处理,并随机选择与测试数据集具有相同编号的20,000对。表3显示了外部数据集的对、令牌、代码行和注释字数的计数。外部数据集的统计信息如表4所示。由于两个数据集的项目不同,我们可以看到外部数据集的代码和注释(即NL)的数据分布在统计度量(均值、标准差等)上与训练数据、验证数据和测试数据不同。

在本文中,我们执行手动代码注释分类,以探索其对代码摘要的影响,它输出代码注释类别的标记数据集,分类结果见第3.2节。

3 IMPACT OF COMMENT CLASSIFICATION ON CODE SUMMARIZATION

3.1 Motivation

实际上,代码注释是复杂的。在编写源代码文档时,开发人员会关注代码的特定方面,而不是彻底地描述它。例如,一些注释描述了设计原理(例如,为什么编写代码)或解释了实现细节(例如,如何实现功能)。这种多样性导致了不同种类的评论。

然而,当前的方法对不同类型的注释是不可知的(也就是说,它们使用相同的策略为不同类型的注释生成注释)。目前,不同类型的注释(即注释分类)对代码摘要的影响尚不清楚。因此,我们的目标是研究注释分类对代码摘要的影响,并探索这些技术如何从注释分类中获益

3.2 Comment Classification

3.2.1 Categories of Code Comments(代码注释的分类)

代码注释的复杂性在于不同的开发人员从不同的角度描述不同的代码实体。受到Zhai等人的启发,我们将评论分为六类:“什么”、“为什么”、“怎么做”、“属性”、“如何使用”和“其他”。表5显示了每个注释类别的描述和示例:“what”类别给出了方法功能的描述(例如,“一个辅助函数”,“一个主进程函数”)。“为什么”类别解释了提供该方法的原因或该方法的设计原理(例如,“获取地图的副本(用于诊断)”)。

“如何使用”类别描述了方法的用法、预期的设置或环境(例如,“应该在使用对象之前调用”)。“如何完成”类别描述了该方法的实现细节(例如,“将字节[]转换为密钥”)。“属性”类别断言方法的属性,包括方法的前置条件或后置条件,其中前置条件表示方法的先决条件,后置条件表示使用该方法的结果[72]。例如,注释“wait until seqno大于或等于期望值,或者我们超过了超时”解释了前置条件(即参数“seqno”),它应该满足条件(≥期望值)才能使方法正常工作。“其他”类别包括不符合上述任何类别的评论(例如,“实现棒极了”)。

有很多方法可以从不同的角度对代码注释进行分类。由于我们的目的是探索代码注释对代码总结的影响,这种代码注释的分类不仅从开发人员意图的角度(例如,“为什么”类别)考虑,而且从程序分析的角度考虑代码属性(例如,“属性”类别)[72]。在本文中,我们研究了几种基于深度学习的代码摘要模型。一方面,这些模型将代码序列和自然语言单词作为输入。这可以帮助模型学习关于语义和意图的信息,这与“什么”和“为什么”的类别有关。另一方面,一些深度神经网络也会考虑源代码的语法信息。例如,DeepCom将序列化代码方法的抽象语法树(AST),而Code2Seq将对AST的路径进行采样并将其序列化为序列。然后将序列化后的序列输入到神经网络中学习句法信息。这个特征可以帮助获取代码结构信息,这些信息与“如何使用”、“如何完成”和“属性”的类别相关。因此,我们选择这种清晰的评论分类方式。

3.2.2 Procedure of Classifying Comments

总共有三位熟悉Java的程序员参与了开放编码过程。我们手动对验证数据进行分类,该数据由20,000个code组成,注释↔对(参见第2.3节对数据集分割的描述)。具体而言,我们采用开放编码程序[55]对数据进行分类和标记。开放编码在软件工程中广泛用于生成类别或标签数据[37,54,72]。在我们的开放编码过程中有三个步骤。

Step 1. Individual classification.

三个编码员独立读取数据。对于每一对,每个编码员阅读注释和源代码,根据定义决定类别。最后,三位编码员对2万对数据进行了分类。表6显示了原始分类结果的统计信息。

Step 2. Discuss and merge conflicts
在第一步(个人分类)之后,三位编码员一起工作以达成最终协议。我们通过澄清类别之间的范围边界和澄清误解来合并冲突。例如,如表6所示,“如何使用”和“如何完成”这两个类别产生了大多数冲突。编码员讨论了这两种注释,他们最终就“如何使用”和“如何完成”这两类的范围边界达成了共识。例如,所有描述特定功能目的的注释,如“检查变量是否是内置的”,都被归类到“如何使用”类别中。通过澄清所有类别的范围边界,我们减少了冲突的数量,如表7所示。除了澄清类别的范围边界之外,编码员还通过澄清讨论中的误解来合并冲突。如果讨论后没有最终的共识,那么我们遵循多数投票。编码员参与了所有的讨论,讨论了所有的冲突,每次讨论持续约30分钟。

Step 3. Iterate and revisit

在步骤1(合并冲突)和步骤2(处理问题)中,在澄清了类别之间的范围边界或澄清了误解之后,三位编码人员再次迭代了这些步骤,并重新访问了相应的注释,以确定最终的类别。这样,我们保证了所有的数据对都是由三个编码器按照相同的标准进行分类的。经过几次讨论,我们又去了一次,解决了矛盾。总的来说,我们按照上面提到的过程重新访问了整个数据集两次,并解决了冲突。当我们无法发现任何新的冲突或问题时,这个过程就结束了。我们没有遇到过这样的情况,即三个编码员坚持使用三个不同的标签,以便多数投票可以导致最终结果。表8展示了重新访问后的结果,表9显示了最终结果。

贴标签过程是劳动密集型的;一个编码员平均一个小时可以标记57个代码注释对(阅读源代码、注释和确定类别)。我们开发了工具去监控完成这个任务所花费的时间;只有当编码员在阅读和标注时,才能计算时间。讨论、合并冲突和重访的时间不包括在内。
最后,我们使用Fleiss Kappa值[13]来衡量三个编码器之间的一致性。

我们根据最后一轮的结果计算Fleiss Kappa。Fleiss Kappa值在[0.01,0.20]、(0.20,0.40)、(0.40,0.60)、(0.60,0.80)和(0.80,1)范围内分别对应轻微、一般、中等、相当和几乎完全一致。总体Kappa值为0.79,表明参与者的意见基本一致。

手工分类的最终结果如表9所示。分布显示,“如何使用”注释几乎与一半的注释相对应。“为什么”的评论占评论的10%以上,而“属性”的评论只占一小部分。‘

3.3 Experiment Setup

在本文中,我们对不同类别的评论评估了六个模型。为了保持所有模型在同一数据集上的变量,我们排除了不支持Java的方法。所有的模型都是在相同的训练数据上训练的,它们分别应用于每个类别。在我们的实验中,CodeNN[24]、DeepCom[21]和Code2Seq[3]是代码汇总模型。

- NNGen模型

NNGen[33]是一种直观且鲁棒的基于检索的模型。两层双向编码器LSTM (Two-layer BiLSTM)[36]和Transformer[62]是基线。我们选择方法的标准是基于它们是最先进的(例如,DeepCom),它们是经典的代码总结模型(例如,CodeNN是第一个将神经网络应用于代码总结的模型),还是基于流行的NMT框架(例如,Transformer)。模型的描述和实现细节如下。

早期的研究只使用词汇层面的表征[2,24]。换句话说,它们只像在NLP中一样将源代码视为令牌序列。

- CodeNN模型

CodeNN是第一个在这一领域使用神经网络的公司。它利用具有注意力的RNN,直接将评论的单词分发给代码令牌。我们使用CodeNN的源代码,并采用他们的预处理程序。

 最近,最先进的研究结合了词汇级和句法级的表征。由于不同级别源代码的实现是不同的(特别是将AST转换为序列的方式),我们选择了两个模型,Code2Seq[3]和DeepCom[21],它们同时利用源代码令牌和AST。

- Code2Seq模型

我们使用作者提供的源代码运行Code2Seq。Code2Seq通过采样树结构内部的路径将AST转换为序列[3]。特别是,Code2Seq模型旨在执行“极端代码摘要”,即生成方法名称而不是自然语言的句子(即摘要)。在作者的帮助下,我们修改了模型的相应部分,并将方法名称替换为摘要。

- DeepCom模型

我们使用作者提供的DeepCom源代码进行实验。DeepCom通过在特定的遍历算法中遍历AST将AST转换为序列[21]。在预处理中,我们使用相同的源代码来执行标记化过程,以及使用相同的算法解析、提取和遍历ast。

- NNGen模型

NNGen是一种基于信息检索的方法,用于生成新差异的提交消息,它也是一种从代码信息到自然语言的映射,类似于代码摘要[32]。NNGen以与CloCom相同的方式工作[68],它具有直观的实现。NNGen使用最近邻算法根据代码重用适当的现有注释。

- NMT Baselines

两个基线:Transformer和BiLSTM被证明是NLP和软件工程生成任务中的强大基线,它们将输入源代码作为令牌流读取。具有全局关注的双层双向编码器-解码器LSTMs[36]是经典的神经网络和Transformer[62],它们在翻译任务中取得了最先进的结果。

- Hyperparameter setting

如上所述,我们使用作者提供的源代码,并保留原始的超参数(如模型结构和训练策略)来重现实验。具体来说,对于CodeNN、DeepCom和NNGen,我们遵循了原始的预处理方法和原始的实验设置。对于Code2Seq,我们在作者的帮助下使用改进的预处理方法执行代码汇总任务,并遵循原始实验设置。对于NMT基线,我们遵循OpenNMT的默认实验设置。

我们进行实验的设备是4个Nvidia 2080ti GPU(总共48 G内存)和Intel Xeon Gold 6226 CPU, 12核。对于所有方法,我们使用相同的训练数据来构建具有类似早期停止策略的模型。我们使用训练好的模型分别评估不同的类别。

3.4 Evaluation Metric

 我们使用BLEU(1至4)[48]和ROUGE[30]的NMT度量来评估模型,它们被广泛用于翻译和代码摘要任务[22,24,62,63]。我们将这些指标介绍如下。

- BLEU指标

 BLEU指标是被广泛用于评估软件工程师的摘要质量[22,24,62,63]。它是精度度量的一种变体,通过计算候选句子与参考句子的n-gram精度来计算相似度,并对过短的长度进行惩罚[48]。

在这里插入图片描述
其中N = 1, 2, 3, 4, wn = 1 N。BP代表短句罚,将短句惩罚指标为:
在这里插入图片描述
 cand和ref分别表示候选句子和参考句子的长度。特别是,我们经常关注BLEU-4,因为它可以反映1到4的加权结果。

- Rouge指标

 Recall-oriented Understudy for Gisting Evaluation[30]的缩写,被广泛用于评价总结任务[34,63]。ROUGE的准确率、召回率和F1分数计算如下:
在这里插入图片描述
 特别是,
在这里插入图片描述
 指ref和cand中匹配的n-gram短语。直观地说,Rrouдe−n测量参考句子中与候选句子匹配的n-gram的百分比,Prouge−n表示候选句子中“正确”n-gram(即参考句子中匹配的n-gram)的百分比。F1rouge−n是精度和召回率的调和平均值。ROUGE-L的准确率、召回率和F1分数的计算方法相同,但它们使用候选句子和参考句子之间的最长公共子序列[30]。我们报告了ROUGE的F1分数,它平衡了准确性和召回率。

 我们通过Sharma等人提供的包计算了代码总结的所有NMT度量。

3.5 Results and Analysis

RQ1 How do different comment categories impact the code summarization performance?

实验结果见表10。据我们所知,我们选择的方法是经典的(CodeNN是第一个将深度学习生成技术应用于代码摘要的公司)或最先进的(例如DeepCom)。ROUGE和BLEU的最先进性能约为30%,这是通过我们在本文中复制的实验实现的。我们的观察结果如下:

对于每种代码汇总方法,不同类别之间的性能差异很大。表中向上箭头(结果)表示在此类别中,该模型在统计学上显著优于其他模型。我们使用比较语言生成任务的工具compare-mt[46]对ROUGE和BLEU进行统计显著性检验。因此,这些差异表明注释分类(即以不同的方式对待注释)可能会影响代码摘要的性能。

不同的代码汇总方法对不同的类别表现最好。结果表明,DeepCom、CodeNN和NNGen在“what”注释方面表现最好,Code2Seq在“how-to-use”注释方面表现最好,Transformer和双层BiLSTM在“how-it-is-done”注释方面表现最好。在六个类别中,没有一个模型在“为什么”和“属性”评论方面表现最好。

对这种差异的一个可能解释是,代码总是高度结构化的。例如,流程的“如何完成”注释通常与源代码对应。它们不涉及方法粒度以上的知识,因此模型在源代码和自然语言之间建立了相对紧密的关系。

Code2Seq和DeepCom表示代码在语法水平,更好地利用了源代码的结构特征,而NLP技术不考虑代码结构信息。在DeepCom和Code2Seq中如何使用AST是不同的:Code2Seq通过采样AST中的路径来利用AST,而DeepCom将整个AST转换为序列。这种机制差异导致了不同的偏好。此外,对“属性”注释性能的一种可能解释是,“属性”注释旨在描述源代码的一部分,如特定的参数或变量。代码摘要训练模型根据先验条件(例如,前一个单词)最大化下一个单词的可能性。然而,决定哪一部分值得评论涉及一个更复杂的过程,这更像是对问题进行分类和推荐。因此,这一类别的结果并不理想。

利用代码信息是必要的,但对所有类型的注释来说还不够。特别是,所有模型在“为什么”类别中都表现不佳。“为什么”注释通常涉及复杂的业务逻辑或背景知识。由于粒度是方法级的,这种知识超出了源代码的范围。为什么要设计代码(即设计原理)通常超出了代码的实现细节。因此,该模型在该类别中无法达到优异的性能。在我们的实验中,基于检索的NNGen模型的性能相对较好,这表明对于“为什么”注释,目标代码本身之外的外部信息(即其他类似的方法及其注释)也起着至关重要的作用。例如,NNGen检索到一条注释:“这个需要在其他任何东西之前调用,因为我们需要媒体工厂。”它解释了设计原理(即Java中的工厂模式),这很难从源代码中推断出来。

4、COMPOSING COMMENT CLASSIFICATION INTO CODE SUMMARIZATION

4.1 Motivation and Insight

-RQ2 How can we improve the code summarization performance using the comment categories?

-RQ2 我们如何使用注释分类来提高代码摘要的性能?

 如表10所述,我们发现不同的代码总结方法对不同的类别表现最好,这意味着模型从源代码中提取信息的能力是不同的。这种差异来自不同模型的机制或实现。因此,将在不同评论类别中表现最佳的模型的优点结合起来可能是有益的。我们的目标是证明注释分类可以提高代码汇总,从而达到更好的结果。

Insight

根据我们之前的发现,对于每个类别,都存在一种表现最好的方法。此外,没有一个模型可以支配所有的类别,这意味着我们可以设计一个组合方法来利用不同的方法。具体来说,根据我们的实验,Code2Seq最适合“如何使用”注释;DeepCom最擅长“什么”、“怎么做”和“属性”评论;NNGen最适合“为什么”和“其他人”的评论。通过使用最合适的方法对每个类别执行代码汇总,我们可以覆盖所有类别。在这个意义上,我们将不同的代码总结模型结合起来,我们称之为复合方法。这样的组合方法可能会有更好的表现验证数据集中的基线。然而,它不能证明这种复合方法只能在验证数据集上提高结果,因为获得的关于哪种方法在特定类别上表现最好的先验知识可能不适用于新的数据集。因此,复合方法应该在我们不知道这种先验知识的新数据集(即测试数据集)上进行评估。

但是,如果应用于新数据集,则复合方法与新源代码片段的类别无关。由于我们已经手动标记了20,000个代码-注释对,因此标记的数据集构建了源代码和注释类别之间的关系。我们可以利用这样的数据集来构建分类器。该任务可以看作是一种源代码分类任务,在软件工程中有研究[7,35,60,61]。已有研究表明,源代码语料库具有与自然语言语料库相似的统计特性[1],表明源代码与注释之间具有一致性。此外,Louis等人使用源代码和相应的标签来训练分类器,并预测开发人员是否会对给定的一段代码进行注释[35];Chen等人成功地使用代码分类来提高代码摘要[7]。这些研究表明,在我们的标记数据集的帮助下预测类别是可行的。我们称这个任务为“代码注释类别预测”。

注意,这个任务并不是我们复合方法的最终目标。分类器扮演着选择器的角色,根据分类选择合适的代码汇总模型,并将结果进行组合。考虑到一段代码在不同的程序中可能具有不同的功能,这可能会影响我们的发现,我们计算了数据集中重复的源代码。只有1.66%的源代码是重复的,只有0.23%的情况是相同的源代码有不同的注释。通过这种方式,我们可以利用注释分类的结果并将其组合到代码摘要中。

4.2 Comment Category Prediction by Source Code

4.2.1 Comment Category Prediction

 该任务利用注释分类的结果来构建分类器并预测给定一段源代码的注释类别。在第3节中,我们手动对由20,000个代码注释对组成的验证数据进行分类和标记。利用这些标记数据,我们构建分类器来进行自动分类。我们利用源代码(拆分令牌)和相应的标签训练几个分类器。在构建分类器后,我们通过10倍分层交叉验证对每个分类器进行评估并相互比较。10倍交叉验证将数据集分成10个连续的折叠(即每个折叠中有2000对);然后,每个折叠使用一次进行评估,而剩下的9个折叠形成训练集(即18,000对)。

 在评估分类器之后,整个标记数据集用于训练分类器。然后,我们将分类器应用于测试数据,以获得每个代码片段的类别。

4.2.2 Experimental Settings

 在本文中,我们研究了五种技术,即随机森林[5],LightGBM[27],决策树[6],多项朴素贝叶斯[38]和基于深度神经网络的分类器。这些技术在软件工程中的评论分类中被证明是有效的[49,50,72]。

 对于随机森林、LightGBM、决策树和多项朴素贝叶斯,我们不仅考虑源代码的文本特征,而且考虑源代码的语法特征。对于文本特征,在对源代码进行标记化后,我们提取标记的双元词频率,这可以为源代码的一个片段提取数十个文本特征。

 这种技术是在软件工程文献中广泛使用的一种传统的源代码特征提取方法[31,60,61]。对于语法特征,我们提取源代码的代码行(LOC)、令牌数和变量数作为统计特征;我们提取源代码的方法名和方法参数作为标识符特征。这些特性在以前的软件工程文献中也有使用。

 我们构建了一个用于分类的LSTM(双向)网络模型,用于源代码分类[35]。我们将源代码的标记序列数字化(即,将标记序列映射到数字索引)。然后,我们使用嵌入层来嵌入每个标记并将它们连接为模型的输入序列。对于每个序列,BiLSTM网络接受令牌的嵌入,并将它们输入到具有两个连接LSTM(即双向LSTM)的层中。该层利用这些层的时间序列的最后状态。然后,模型将张量输入到一个完全连接的层,并通过一个softmax层来获得输出标签。

 我们用50个epoch训练模型,模型随机选择5%的数据进行训练内验证。我们采用提前停止策略,即如果训练内验证停止增加3个epoch,模型将停止训练。

4.2.3 Metrics for Evaluating Classifiers

 为了评估我们的自动技术对代码注释进行分类的有效性,我们使用了众所周知的信息检索指标来衡量结果的质量,这些指标称为Precision、Recall和F1分数:

在这里插入图片描述
 其中,真阳性(TP)表示被正确分类到相应类别的评论数量;假阳性(FP)表示被错误分类到这一类的评论的数量;False Negative (FN)表示被错误地分类到其他类别的评论的数量。这里的Precision, Recall和F1分数是针对某些类别的。我们使用加权结果评估分类器(即,计算每个类别的指标,并通过每个类别的数量找到它们的加权平均值)。

1)多个分类任务的评估

 在本文中,分类任务是一个多类分类,因为有六个类别(即,“什么”、“为什么”、“如何使用”、“如何完成”、“属性”和“其他”)。考虑到支持度(即不同类别的数量)不同,我们计算了精度、召回率和F1分数的加权结果。形式上,我们计算它们为:
在这里插入图片描述
在本文中,我们使用交叉验证来评估分类器,并报告所有折叠的Precisionweiдhted、Recallweiдhted和F 1weiдhted的平均结果。

我们报告了实验的标准差。有两种标准差。对于交叉验证,我们报告了所有折叠的标准差:
在这里插入图片描述
为了评估我们的方法和基线,考虑到基于学习的方法的随机性,我们运行了10次实验并报告了标准差。

4.3 Composite Approach with Comment Category Prediction

在这里插入图片描述

 从表10的结果可以看出,表中向上箭头(结果)表明该模型在此类别中优于其他模型。基于我们上面提到的观察和见解,我们选择Code2Seq、DeepCom和NNGen作为基本模型。例如,Code2Seq在“如何使用”注释中具有最好的性能,因此当分类器确定给定源代码的“如何使用”类别时,我们使用Code2Seq进行代码汇总。以同样的方式提出了复合方法。然后,该方法结合所有生成的注释并输出最终结果。

 然而,请注意,我们不能在用于验证代码摘要模型的相同验证数据中评估方法,因为我们已经获得了在该验证数据中“哪个模型在特定类别中表现最好”的先验知识。回想一下,测试数据是未标记的,与验证数据和训练数据没有重叠(参见第2.3节)。我们在测试数据中评估了我们的复合方法。最后,根据生成的评论和参考评论计算评价指标。没有分类器辅助的三种方法被视为基线。我们在相同的测试数据上评估每个模型并分别得到输出。

4.4 Experimental Results

表11显示了分类器的结果。在几个候选分类器中,最佳分类器是Random Forest,在10倍交叉验证中达到76.91%。它优于其他分类器,在我们的复合方法中用作选择器。据我们所知,没有其他方法可以通过源代码执行注释类别预测。随后的实验结果如表13所示,表明Random Forest在自动分类评论方面是有用的。

表12给出了不同分类器的六类结果(均值±标准差)。我们可以观察到,一般来说,所有的分类器在“什么”和“如何使用”的类别中表现最好。“property”和“others”的表现相对较低,而他们的标准偏差很大,因为属于这两类的对的数量相对较少,影响了结果的稳定性。

表13显示了我们的复合方法在测试数据上的结果。由于测试数据和验证数据的差异,三个基线的性能略有不同,Code2Seq在测试数据中表现更好,而DeepCom在验证数据中表现更好。NNGen具有相对较高的BLEU-3和BLEU-4,因为作为一种基于检索的方法,一旦检索到句子,结果更容易准确匹配。

我们的复合方法在测试数据中优于当前的方法。其中ROUGE-L评分相对改善8.57%(绝对改善2.76),BLEU-4评分相对改善16.34%(绝对改善2.80)。我们使用比较语言生成任务的工具comparmt[46]对ROUGE和BLEU进行统计显著性检验。结果表明,我们的方法与基线之间的差异是显著的。此外,我们的改进不仅仅是在ROUGE方面Code2Seq对DeepCom的改进,以及在BLEU-4方面NNGen对Code2Seq的改进。结果表明,该分类器成功地融合了分类信息。我们的实验表明,注释分类可以提高代码摘要,达到更好的结果。

4.4.1 Influence of the classifiers

虽然我们使用随机森林作为最终选择器,但我们报告了使用不同分类器的复合方法的结果。如表14所示,应用LightGBM、决策树、朴素贝叶斯和基于dnn的分类器的结果低于应用随机森林的结果。就ROUGE-L而言,我们使用所有分类器的复合方法优于基线;就BLEU-4而言,我们使用随机森林、LightGBM和BiLSTM分类器的方法优于基线。我们可以观察到,在F1分数方面,分类器的性能与复合方法的结果近似正相关(即,除了LightGBM和BiLSTM之外,近似F1分数越高,我们的方法越好)。如果我们能够清楚地了解源代码注释的意图类别,那么代码摘要将具有更好的性能。

4.4.2 Performance on the external dataset with different data distribution

表15显示了我们的复合方法的结果和外部数据的基线。由于外部数据的数据分布不同,模型得分相对较低。尽管如此,我们的模型在具有来自训练数据和测试数据的不同数据分布的外部数据集中优于基线。

4.5 Qualitative Analysis

仅报告ROUGE和BLEU分数并不能直观地反映类别的影响,并且它留下了我们的方法如何工作的开放性问题。我们用两个例子来说明。虽然我们不愿过度解读所选的例子,但我们观察到这些例子与许多其他例子是一致的。第一个例子是展示类别的影响。我们选择DeepCom并选择引用和生成的评论,以说明“什么”、“为什么”、“如何使用”、“如何完成”和“属性”类别中的不同性能。

在这里插入图片描述

在第一种情况下,该方法确定了方法的角色,但没有总结出它是一个“助手”函数。技术上的原因是单词“helper”缺乏上下文,这导致模型生成单词“helper”的概率很低。

在这里插入图片描述

第二个案例旨在使用“reachability”这个词来描述意图。但这种方法无法总结它,因为这个词很少见,而且缺乏上下文。相反,他只总结了当前输入在源代码中的作用。

在这里插入图片描述

第三种情况强调变量的变化,该方法成功地总结了“如何使用”,尽管就评估逐字结果的NMT指标而言,性能并不高。
在这里插入图片描述

第四个案例评论了该方法如何删除视频,以及该方法如何成功捕获关键信息(即id)。
在这里插入图片描述

第五种情况解释了方法的参数,而该方法只捕获变量的类型(即字节数组)。如3.3节所述,DeepCom输入源代码的AST序列和令牌序列,目前许多方法都遵循这个框架。

在这里插入图片描述

一方面,示例显示了DeepCom这种框架的局限性,即当前输入不足以总结源代码之外的外部信息(例如,第一种情况不能总结信息“helper”,第二种情况不能总结意图)。另一方面,该示例说明了该方法更倾向于检索信息,以便仅使用源代码总结功能。
在这里插入图片描述

第二个示例是通过观察AST结构来展示复合的工作原理和过程。如图3所示,源代码首先被分类为“为什么”注释,因为我们的分类器在标记的验证数据中捕获了类似的代码模式。

在确定类别之后,回想一下,NNGen在“为什么”类别中效果最好,复合模型使用NNGen来生成评论。为了与未选择的模型进行比较,我们还调用DeepCom和Code2Seq来生成注释。根据人类的评估,DeepCom成功地描述了功能,但以一种复杂的方式。如图3所示,它捕获带下划线的关键字,并以可读的方式输出它们。然而,它描述的方式是复杂的,这是从它的AST序列派生出来的。DeepCom将整个AST转换成序列并输出数值向量.注释反映了AST序列的复杂性(121递归结构,对于5语句的方法来说是非常大的),但是句子的复杂性也导致了较低的分数。

在这里插入图片描述
在这里插入图片描述

至于Code2Seq,它无法描述这种情况下的功能。如图3所示,Code2Seq对AST的路径进行采样以构建路径,但在这种情况下,它未能捕获关键节点“double”,从而导致结果的偏差。

因此,分类器在这个评论类别中选择了一个更好的模型,避免了模型过于复杂或有偏差的缺点。这个案例说明了评论分类的结果如何在微观粒度上帮助复合方法。

5 DISCUSSION

5.1 Implication

5.1.1对实践的启示

 总的来说,很难找到一种通用的方法来解决自动代码汇总问题。实践中的代码总结问题涉及到很多方面。

 在本文中,我们将问题限制为六类注释,并评估当前模型的执行情况。然而,即使在这样一个简化的情况下,我们的实验结果表明,没有一个模型可以在每个类别中都表现良好,并且在其他所有模型中都占主导地位。因此,为特定领域构建模型比为通用领域构建模型更为可行。虽然单个简单案例的贡献是有限的,但这些情况的组合可以在帮助中发挥重要作用(例如,API提示技术很简单,但对开发人员有很大帮助[45])。

 在本文中,我们将利用评论类别的影响。为了在实践中利用结果,开发人员可以利用带有注释类别预测的代码摘要来更好地识别开发或维护阶段的意图。通过这种方式,将注释划分为特定的类别可以提高程序的可理解性,并有助于更好地维护源代码。

 此外,随着对注释类别的认识,从业者可以将新兴的代码摘要技术应用于更合适的场景(例如,期望总结“什么”注释比“为什么”注释更合理)。

 在本文中,我们的实验表明,当前的代码总结模型并不适用于所有类型的代码注释。同时,在实践中,没有必要为每个代码编写各种各样的注释。因此,自动代码摘要的一个先决问题是确定需要哪种注释。我们用观察到的一个典型现象来说明这一论点。例如,我们观察到一些模型可以正确地生成类似于“TODO:在将来实现这个”的注释,因为它们是根据一些未完成源代码的特定模式生成的。然而,这样的生成很难有用,即使根据NMT度量(例如,BLEU)进行评估是正确的,因为在实践中,开发人员有他们自己的时间表来解决他们自己的“TODO”。因此,我们声称将所有类型的代码注释视为相同的自然语言是过于粗糙的,因此这种“TODO”可以被视为噪声,或者应用于适当的场景(例如,技术债务预测)而不是注释生成。在将来,关注具有特定类型代码注释的实际场景(例如,“how to use”)是有益的。

5.1.2 研究意义

1) 考虑上下文信息和更多种类的评论

在我们的实验中,所有模型在“为什么”和“属性”注释中都表现不佳。这表明,尽管对于基于学习或基于检索的方法来说,使用方法级的代码注释对是可行的,但仅考虑方法级的代码注释信息是远远不够的。在典型的软件工程项目中,考虑分层的项目-文件夹-文件-类-方法信息是有益的。在本文中,我们对方法级注释进行了分类,但是考虑类级或文件级注释也是有益的。

具体来说,“why”类别和“property”类别是有区别的。对于“why”注释,一方面,它们可以被认为是更高级别的注释,需要更多的信息来推断。因此,前面提到的类级、文件级注释和其他上下文可以被认为是模型的输入。另一方面,“why”注释通常与业务逻辑相关。例如,注释解释了为什么应该添加用户配置文件的业务逻辑。这样的业务增加了推理的难度,因为与其他注释(例如,“如何完成”)不同,即使在源代码的大数据集中,业务逻辑也不是通用的。这样的业务逻辑也很难单独从软件项目中获得。因此,这类注释需要更多定制的和业务逻辑相关的信息。对于“property”注释,代码汇总模型不能完全满足实际情况。例如,与属性相关的一种典型注释是解释源代码的变量。在某种程度上,模型可以通过最大化这些标记的概率来捕获应该注释的变量的模式(即,神经网络在训练期间给予这些变量更多的权重)。然而,考虑到不同的环境,结果仍然不那么理想。对于解释代码属性的“property”注释,考虑程序分析技术(例如,考虑代码的控制流和数据流)将是有益的。

2)为自动代码摘要提供注释分类知识

我们的组合方法证明,使用一个简单和基本的分类器,我们可以提高代码摘要的性能。然而,我们的实验只是为了证明,我们可以利用评论分类的信息作为来源的参考。一方面,针对特定类型的评论构建模型比针对一般评论构建模型更可行。另一方面,它可以提高对研究问题的理解,特别是对复杂的问题。例如,在本文中,我们发现“what”注释获得了最好的性能,因此鼓励进一步的研究在这方面进行,并且我们进行了更深入的研究以提高对编程的理解。

在评论分类的指导下,重新考虑数据集的预处理和结果的评价是有益的。当前的预处理程序专注于遵循典型NLP惯例的自然语言(例如,简单地删除停止词和词干提取)。这种方法在考虑程序分析的方面是有用的。类似地,评估标准也遵循NLP领域中采用的标准(例如,“BLEU”和“ROUGE”)。这些神经机器翻译指标只强调字面和流畅的结果,但在评估代码摘要模型的质量时,没有从软件开发人员的角度考虑结果的有用性(例如,哪些类型的注释是需要的,并且对提高可读性有用)。

5.2 Threats to Validity

5.2.1 Internal Validity

对内部效度的威胁与不同模型的偏差有关。不同模型的实现是有差异的,这些差异包括环境、模型结构,特别是预处理方法。例如,虽然所有选择的方法都支持Java,但所提供的预处理方法仅限于特定的Java版本。另外,有些只需要源代码的令牌,而有些则需要提取源代码的AST。这些差异增加了重复实验的难度。

在本文中,我们使用原作者提供的源代码。为了执行我们的实验(即,在同一数据集上运行多个实验),我们通过电子邮件或GitHub问题与作者保持联系,以解决可再现性问题(例如,解决语言解析工具如:java parser的兼容性)。因此,在原作者的帮助下,我们认为内部有效性几乎没有威胁。

其他对有效性的威胁与研究人员在数据集手动分类时的个人看法有关,因为本文的作者参与了标记过程(请参阅第3节)。为了减轻这种威胁,我们邀请了第三个非作者程序员作为编码员参与开放编码过程。在共同讨论之前,三位编码人员分别使用分类的参考标准独立地遍历整个数据集[72],此类威胁缓解措施(即非作者参与或独立标注)已在以前的作品中采用[64,70,72]。编码人员在Java编程方面的经验(2年、3年和2年)也对有效性构成威胁。因此,作者参考了文献中关于评论分类的研究[49,50,72],研究了Zhai等人[72]的分类方法,并研究了如何对Pascarella等人[49,50]的数据集中的评论进行标注,相信先前的研究可以帮助减轻这种威胁。在未来,我们将通过邀请更有经验的程序员对注释进行分类来进一步减少威胁。

5.2.2 External Validity

对外部有效性的威胁与数据集的可生成性有关。所提出的方法在不同的目标系统上会显示出不同的结果。为了减少这种限制,我们使用Hu等人[21]提供的数据集,该数据集来自GitHub中的9714个java项目,也被广泛使用[3,35,66]。为了判断该方法的可通用性,我们采用跨项目验证的方法来模拟实际情况。在未来的工作中,如果考虑跨语言进行验证相信也会很有趣。

5.2.3 Construct Validity

结构效度的威胁涉及样本效度和分类效度。首先,对样本有效性的威胁是,存在一个潜在的风险,即有偏见的项目样本可能会提供错误的知识。我们选择一个被研究人员广泛使用和检验的可信数据集。数据集中的项目广泛分布在不同的领域,是具有成熟生态系统和开发环境的项目的代表。

其次,对分类法有效性的威胁是,分类法能否提供一种详尽而有效的方式来组织源代码注释。在本次实验中,使用了由三位经验丰富的开发人员参与的编码程序,分别推导了分类,最终,Fleiss Kappa值为0.79,表明参与者的意见基本一致。此外,实验结果也证实了不同评论之间的差异,证明了标签的有效性。

CONCLUSION

在本文中,我们手动将20,000个代码注释对标记为六个类别:“what,” “why,”“how-to-use,” “how-it-is-done,” “property,” 和 “others.”。基于此数据集,我们进行了一个实验来研究不同的最先进的代码摘要方法在类别上的性能。我们发现不同代码汇总方法的性能在不同的类别中有很大的不同。此外,对于不同的模型,代码摘要模型表现最好的类别是不同的。每个模型对特定评论类别的首选项是不同的。受此发现的启发,我们设计了一种复合的两步方法来分析方法并输出总结该方法的注释:(1)我们的方法预测可能伴随特定代码段的代码注释的类别,(2)我们的方法然后选择对推断类别执行最佳的代码摘要方法,并使用它来生成相应的注释。我们的方法在不考虑评论分类的情况下优于其他方法,在ROUGE-L方面获得了8.57%的相对改进,在BLEU-4评分方面获得了16.34%的相对改进。我们的研究强调,通过结合自动推断的代码注释类别,我们可以提高代码摘要任务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值