Page 212 - 《软件学报》2021年第7期
P. 212
2130 Journal of Software 软件学报 Vol.32, No.7, July 2021
器/解码器.随后基于评论者网络的反馈,对演员网络进行迭代调优,以不断提高生成的注释质量.最后用生成的
注释进行代码检索.Wei 等人 [75] 同时考虑了注释生成和代码生成问题,认为这两个任务之间具有一定的相关性.
他们提出了一种基于对偶学习的方法,通过利用这两个任务间的对偶性来同时训练模型.他们考虑了概率和注
意力权重间的对偶性,并设计了对应的正则化项以约束这种对偶性.
4.2.3 考虑其他信息来源
除了上述研究工作外,一些研究人员尝试着利用其他信息(例如 API 序列信息、与目标代码相似的代码段、
方法的上下文信息等)来进一步提升生成的注释质量.
开发人员经常会通过调用特定的 API 序列来实现某个功能.例如,使用 Java 编程语言实现打开文件这一功
能,就会使用固定的 API 序列.因此,与可能基于不同编码规范实现的代码相比,代码内的 API 序列会更为有规可
循.基于上述观察,Hu 等人 [76] 提出了 TL-CodeSum 方法,该方法首先完成 API 序列总结任务,通过该任务可以构
建出 API 知识与实现的功能描述间的映射.随后将该知识应用于代码的注释生成.
Zhang 等人 [77] 尝试着将基于深度学习和基于信息检索这两类方法进行了融合.具体地,他们提出了 Rencos
方法,该方法首先基于训练语料库训练出编码器-解码器模型.随后从语法(即将代码解析为 AST,并计算 AST 之
间的相似度)和语义(即使用预训练的编码器,将代码编码为语义向量,并计算语义向量之间的相似度)两个角度,
从训练语料库中选出与目标代码段最为相似的两个代码段.最后对输入代码段和检索出的两个相似代码段进
行编码,并在解码生成注释时综合利用了这 3 个代码段的信息.
Liu 等人 [78] 基于需要生成注释的代码和相关代码的调用依赖关系,提出了一种基于深度学习的注释生成方
法.他们从代码中抽取出调用依赖关系,并将其转换成方法名的 token 序列,并通过综合利用代码和调用依赖关
系,基于 seq2seq 模型来生成代码注释.Zhou 等人 [79] 提出了 ContextCC 方法,首先使用程序分析方法,通过解析
AST 来抽取上下文信息(即方法和相关的依赖关系),接着通过预先定义的模板和规则,从上下文信息中过滤掉
无关内容,最后基于 RNN 来生成代码注释.Haque等人 [80] 尝试着利用代码上下文信息来生成注释.他们提出文件
上下文(即处在同一个文件内的其他函数)的概念,所提方法在编码器时考虑了 3 类输入(即代码文本、AST 和文件
上下文包含的其他函数).实验结果表明,使用文件的上下文信息有助于进一步提升生成的代码注释的质量.
4.3 已有工作的对比和评点
我们通过表 4 对所有基于深度学习的方法进行全面的对比,包括代码模块粒度、编程语言、方法类型和主
要特征.不难看出,基于深度学习的方法是当前该研究领域内最为流行的一类方法.早期的研究一般基于传统的
编码器-解码器模型.主要区别是如何对代码进行编码,因为代码与自然语言相比,具有一定的结构性.目前常见
的编码方式包括:将源代码直接转化成序列、将源代码建模为 AST、借助 SBT 方法将 AST 转换成序列、直接
基于 AST 等方式.其次,研究人员在经典方法的基础上,考虑进一步融合其他学习方法,例如图神经网络、强化学
习和对偶学习等.除此之外,除了源代码信息,更多研究人员考虑利用其他信息来提高注释生成的质量,例如考
虑 API 序列信息、代码的上下文信息等.由于这类方法主要基于深度学习,因此这类方法的性能同样离不开高
质量且规模大的语料库.
Table 4 Comparison of deep learning-based generation methods
表 4 基于深度学习的生成方法的对比
相关文献 模块粒度 编程语言 方法类型 主要特征
Iyer 等人 [10] 代码段 C#、SQL 查询 经典编码器-解码器 基于 LSTM 和注意力机制
Allamanis 等人 [54] 方法 Java 经典编码器-解码器 基于 CNN 和注意力机制
Zheng 等人 [55] 代码段 Java 经典编码器-解码器 提出代码注意力机制
Liang 等人 [56] 方法 Java 经典编码器-解码器 基于 Code-RNN 和 Code-GRU
Hu 等人 [13,57] 方法 Java 经典编码器-解码器 基于 SBT 方法将 AST 转换成序列
Kang 等人 [58] 方法 Java 经典编码器-解码器 考虑了预训练的词嵌入
LeClair 等人 [60] 方法 Java 经典编码器-解码器 同时考虑了代码的单词表示和 AST 表示
Ahmad 等人 [61] 代码段、方法 Python、Java 经典编码器-解码器 基于 Transformer