【论文笔记】Improving Automatic Source Code Summarization via Deep Reinforcement Learning

Improving Automatic Source Code Summarization via Deep Reinforcement Learning

1 本文背景

软件维护占据软件开发生命周期很大一部分,提供代码执行任务的描述对于软件维护来说是必须的,然而注释代码仍然是一项劳动密集型的任务,使得真实的软件项目很少具备充分的代码文档以减少未来的维护成本。

本文作者提出:一个好的注释论至少应该具备以下特征: a)正确性:正确地阐明代码的意图。b)流利:流畅的自然语言,易于维护者阅读和理解。c)一致性:遵循标准的样式/格式。

代码摘要是一项试图理解代码并直接从源代码自动生成描述的任务。

本文将一个抽象语法树结构以及代码片段的顺序内容合并到一个深度强化学习(DRL)框架中(具体: actor-critic网络)。

2 模型架构

2.1 总体工作流程

【论文笔记】Improving Automatic Source Code Summarization via Deep Reinforcement Learning
a) 离线培训阶段
语料库 → < code,comment> → 深度强化学习模型→ actor network

b) 在线总结阶段
给定一个代码片段,注释经过训练后的actor network生成。

2.2 模型具体框架

【论文笔记】Improving Automatic Source Code Summarization via Deep Reinforcement Learninga) 混合代码表示:将源代码表示为隐藏空间,即编码器。
b) 混合注意力层:在将已编码的隐藏空间译码到注释空间时,利用注意力层对代码片段的token分配不同的权重,以便更好地进行生成。
c) 文本生成:RNN生成网络,根据当前生成的单词生成下一个单词。
d) critic:评估生成词的好坏。

a) 混合代码表示

这一层使用LSTM来表示代码的词法,使用基于AST的LSTM来表示代码的语法。

词法级表示

源代码的词法级表示的关键:注释总是从代码的词法中提取,比如函数名、变量名等等。本文使用LSTM来表示源代码的序列信息。

语法级表示

AST作为一种中间代码,表示程序的层次语法结构。本文从AST嵌入的角度,提出一个基于AST的LSTM来表示源代码的语法层次,公式如下所示:

【论文笔记】Improving Automatic Source Code Summarization via Deep Reinforcement Learning
其中j代表node,l代表l-th child,k=1, …,N,N是child的数量,x是某个node的word embedding,σ是logistic即sigmoid函数,点乘是vector按元素的相乘。
i代表input gate, f代表forget gate, AST-based LSTM有多个forget gate, o代表output gate, u代表更新memory cell的state, c代表memory cell, h代表hidden state。

本文在语法级表示中配合AST使用了树形LSTM的结构,因此每个LSTM有多个子节点的隐藏状态h输入,因而有多个forget gate。
这一结构由子节点数N来控制,当N=1时,就是普通的LSTM结构。
具体如下图所示:
【论文笔记】Improving Automatic Source Code Summarization via Deep Reinforcement Learning

【论文笔记】Improving Automatic Source Code Summarization via Deep Reinforcement Learning
图(a)是基本RNN的结构,图(b)是Tree-RNN结构。

对于不同AST的不同节点,子节点N的数量是不同的。
为了简化,作者将AST转换为二叉树,具体做法:

  • 如果节点有多个child,除了最左边的child,其余child成为新的右child的child。自上而下重复直到每个node的child都不超过2个。
  • 将只有一个child的node与其child结合

b)混合注意力层

注意力层有两个注意力得分,一个用于结构表示????????????????????,另一个用于序列表示????????????????????
在解码过程的第 t 步,????????^{???????????? (????)}^ 和 ???????? ^???????????? (????)^的注意力得分计算如下:【论文笔记】Improving Automatic Source Code Summarization via Deep Reinforcement Learning
st是源码片段加上到 t 步得到的word {x ,y0,y1,…,yt} ,st+1={st,yt+1}。
分别将各自的注意力得分和隐藏状态加权求和:
【论文笔记】Improving Automatic Source Code Summarization via Deep Reinforcement Learning
然后将????_????????????????和????_????????????????连接起来,输入单层线性网络得到上下文向量dt:
【论文笔记】Improving Automatic Source Code Summarization via Deep Reinforcement Learning
再通过一个额外的隐藏层为预测第t+1个词做准备:
【论文笔记】Improving Automatic Source Code Summarization via Deep Reinforcement Learning

c)文本生成

模型利用 softmax 函数预测第t个单词:

【论文笔记】Improving Automatic Source Code Summarization via Deep Reinforcement Learning

d)评论家网络

在解读评论家网络之前,先了解一下什么是强化学习。
【论文笔记】Improving Automatic Source Code Summarization via Deep Reinforcement Learning
强化学习算法基本思路:
上图的大脑代表算法执行个体,对个体操作来做决策,即选择一个合适的动作(Action)At。地球代表研究的环境,它有自己的状态模型,在选择动作At后,环境的状态(State) St会变为St+1,同时得到了采取动作At的延时奖励(Reward)Rt+1
然后个体可以继续选择下一个合适的动作,环境的状态又会变,又有新的奖励值。
模型基本要素:环境的状态S,个体的动作A,环境的奖励R,个体的策略(policy)π,即状态s时采取动作a的概率,采取行动后的价值(value)v,表示当前奖励和后续奖励的期望。

这里只是一个非常简要的介绍,我个人感觉强化学习非常类似GAN,但是在最后的反馈机制上与GAN是不同的计算方式。
更具体的内容可以参考博客:

https://www.cnblogs.com/pinard/p/9385570.html

与actor网络不同,critic network在每个解码步骤上输出一个值(对actor的评价)而不是一个概率分布,actor根据这个评价进行参数调整。
在给定policy π、sample action和reward function的情况下,value function是未来reward累加和的期望, h是代码片段的表示,公式如下:
【论文笔记】Improving Automatic Source Code Summarization via Deep Reinforcement Learning

只有在序列生成过程(或事件)完成后才能得到评价分数(BLEU)。当步长超过最大步长T或生成序列结束(EOS)令牌时,事件终止。因此,reward定义如下:
【论文笔记】Improving Automatic Source Code Summarization via Deep Reinforcement Learning
对critic最小化loss,????^???? (????_????)是目标值, ????_????^???? (????_????) 是critic的预测值:
【论文笔记】Improving Automatic Source Code Summarization via Deep Reinforcement Learning

2.3模型训练

对于整个模型,Loss为????(Θ)=????(????)+????(????) ,前者是actor的Loss ,后者是critic的Loss 。
使用policy gradient来对模型进行优化。
关于actor参数的梯度为:
【论文笔记】Improving Automatic Source Code Summarization via Deep Reinforcement Learning
关于critic的参数梯度为:
【论文笔记】Improving Automatic Source Code Summarization via Deep Reinforcement Learning
最后还用了SGD+AdaGrad

3 实验部分

3.1 数据集

数据收集于github,包含108726个<code, comment>对。
代码和注释的词汇量分别为50400和31350。
训练、测试、验证比例划分为6:2:2。
使用工具ast2lib将Python代码解析为抽象语法树。
用{., “ ’ : ; ) ( ! (space)}来token化代码,{(space)}来token化注释。
大多数代码片段的长度在20到60之间。
几乎所有注释的长度都在5到15之间。
【论文笔记】Improving Automatic Source Code Summarization via Deep Reinforcement Learning

3.2 衡量指标

选择自然语言处理领域的相关评价指标:

指标 计算方式
BLEU 用于分析候选译文中有多少 n 元词组出现在参考译文中
METEOR 利用准确率和召回率的调和平均作评判标准,需要 WordNet 扩充同义词集,同时需要考虑单词词性(比如like、likes都算对)
ROUGE-L 基于最长共有子句共现性精度和召回率 F-measure 统计
CIDER 把每个句子都看作“文档”,将其表示成 tf-idf 向量的形式,然后计算参考caption与模型生成的caption的余弦相似度作为打分。

3.3 实验设置

基线:
Seq2Seq:基于LSTM的经典编码器-解码器框架
Seq2Seq+Attn:Seq2Seq模型的一个衍生版本,具有词对齐的注意层
Tree2Seq:与Seq2Seq相同的体系结构,并采用基于AST的LSTM作为编码器
Tree2Seq+Attn:是带有注意层的Tree2Seq模型的衍生版本。
Hybrid2Seq(+Attn+DRL):代表了本文提出的模型的三个版本,是否有 Attn/DRL 组件。

3.4 实验结果

RQ1:与基线相比

【论文笔记】Improving Automatic Source Code Summarization via Deep Reinforcement Learning

RQ2:组件分析

【论文笔记】Improving Automatic Source Code Summarization via Deep Reinforcement Learning

实验结果——RQ3:参数分析

(1)不同的代码长度
【论文笔记】Improving Automatic Source Code Summarization via Deep Reinforcement Learning(2)不同的注释长度
【论文笔记】Improving Automatic Source Code Summarization via Deep Reinforcement Learning数据集中几乎所有数据的注释长度都小于20,因此缺乏对超过长度的性能分析

定性分析

【论文笔记】Improving Automatic Source Code Summarization via Deep Reinforcement Learning