Page 210 - 《软件学报》2021年第7期
P. 210

2128                                     Journal of Software  软件学报 Vol.32, No.7,  July 2021

                 (out of vocabulary)问题,即需要生成的注释可能含有未在代码中出现的单词.(2)  代码注释的可读性问题,使用
                 贪心或者束搜索(beam search)策略进行解码时,其生成的句子可能会出现不通顺的问题.(3)  代码注释和代码的
                 长度并不相等,通常来讲,代码注释的长度要远小于代码的长度.

                 4.2   已有工作的分析
                 4.2.1  基于经典编码器-解码器模型的方法
                    当前这类方法主要基于编码器-解码器结构(encode-decoder structure),有时又被称为序列到序列模型
                 (sequence to sequence model).具体来说,编码器的作用是将源代码编码为固定长度的向量表示,解码器的作用是
                 将源代码的向量表示进行解码,并生成代码注释.不同的编码器-解码器的主要区别在于代码的输入形式和神经
                 网络的结构.一般来说,常见的结构包括:CNN(convolutional neural network)和 RNN(recurrent neural network).其
                 中,LSTM(long short term memory)是最常见的一种 RNN 网络,其考虑了 3 个门控,即输入门控、遗忘门控和输出
                 门控.主要是为了解决长序列训练过程中的梯度消失和梯度爆炸问题.GRU(gated recurrent unit)可以缓解 LSTM
                 中存在的结构复杂和实现复杂的问题,并可以有效地减少模型训练时所需的时间开销.GRU 仅考虑了两个门控,
                 即更新门控和重置门控.同时,研究人员还会在 RNN 上进一步考虑注意力机制(attention mechanism),其可以为
                 编码器/解码器的相关序列中更为相关的词素赋予更高的权重取值,以进一步缓解长序列训练中存在的相关
                 问题.
                    Iyer 等人 [10] 首次对这类方法展开研究,并提出 CODE-NN 方法,在编码和解码时均基于 LSTM 和注意力机
                 制.在 Allamanis 等人 [54] 提出的方法中,编码器使用 CNN 和注意力机制,解码器使用 GRU.通过使用卷积操作,有
                 助于检测出局部时序不变(local time-invariant)特征和长程主题注意(long-range topical attention)特征.Zheng 等
                 人 [55] 提出一种新颖的注意力机制,即代码注意力(code attention)机制.该机制通过利用代码段的领域特征(例如
                 symbols 和标识符)来理解代码结构.通过关注这些具体领域特征,代码注意力机制可以更好地理解代码段的结
                 构信息.Liang 和 Zhu [56] 基于 Code-RNN 进行编码,从代码中抽取特征并构建向量表示.在解码时使用 Code-GRU.
                    Hu 等人  [13] 提出 DeepCom 方法,该方法通过抽象语法树(abstract syntax  tree,简称 AST)来分析 Java 方法的
                 结构和语义信息,随后将 AST 转换成序列.为了更好地表示 AST 内的结构信息,且确保转换后的序列没有歧义,
                 他们提出一种新的 AST 遍历方法 SBT(structure-based traversal).SBT 将节点包含的子树包含在一对括号内.借
                 助括号可以有效地表示出 AST 的结构,并且可以无歧义地将转换后的序列恢复成转换前对应的 AST.除此之外,
                 为了进一步解决 OOV 问题,他们提出一种表示未知词素的新方法.在他们分析的 AST 转换后的序列中包含 3
                 类节点:终端节点、非终端节点和括号.其中,未知词素隶属于终端节点,因此,该方法使用未知词素的类型来代替
                 之前使用的通用词素值UNK.随后,他们基于 DeepCom 方法             [57] ,进一步提出 Hybrid-DeepCom 方法,该方法主要
                 进行了 3 方面的改进,首先综合使用了代码信息和 AST 转换后的序列信息,其次基于驼峰命名规范,通过将标识
                 符进一步细分为多个单词来缓解 OOV 问题.最后,该方法使用束搜索来生成代码注释.Kang 等人                             [58] 在 Hu 等
                 人 [13] 研究工作的基础上,分析了使用预训练的词嵌入是否能够提升模型的性能.他们发现,使用基于 code2vec                           [47]
                 或 GloVe [59] 的预训练的词嵌入并不一定能提升性能.
                    LeClair 等人 [60] 提出了 ast-attendgru 方法,该方法考虑了两类代码信息:基于单词的表示(即将代码简单视为
                 文本)和基于 AST 的表示.他们考虑的模型包括两个单向的 GRU 层:其中一层用于处理代码中的单词,另一层用
                 于处理 AST.随后,借助注意力机制来识别出这两层中的重要单词.之后,合并基于注意力机制输出的向量,以创
                 建上下文向量.最后,基于该上下文向量生成代码注释.
                    Ahmad 等人  [61] 利用 Transformer 模型来生成代码注释.Transformer 模型是一种基于多头自注意力的序列到
                 序列模型,它可以有效地捕获长程依赖(long-range dependencies).
                    已有的针对代码变更生成提交消息的方法                [21,29] 在生成的提交消息内仅包含代码变更的内容和变更位置,
                 并且生成的提交消息较为冗长,除此之外,这些方法对代码变更的提交原因关注得较少,而这一类信息可以通过
                 分析已有的代码变更来获取.
                    Loyola 等人 [62] 首先初步证实了这种类型方法的可行性.Jiang 等人           [46,63] 针对代码变更来生成提交消息,他们
   205   206   207   208   209   210   211   212   213   214   215