Page 232 - 《软件学报》2021年第7期
P. 232
2150 Journal of Software 软件学报 Vol.32, No.7, July 2021
信息,对于 Source Encoder 和 Code Encoder 来说,提取到的都是源代码的语义信息,而且由于 Code Encoder 使用
分解后的源代码序列,因此 Code Encoder 提取到的语义信息包括了 Source Encoder 提取到的语义信息,并且要
比其丰富.综合以上原因,为了减少冗余,降低干扰,我们将不传递 Source Encoder 的最终隐藏状态向量.
c
ReduceHidden 接受 Code Encoder 和 AST Encoder 的隐藏状态 h 和 h a , 分别简写为 h c 和 h a ,并通过一个线
c T a T
性层进行维度映射,由此得到输入到解码器的初始状态 s 0 ,具体公式如下:
[ ; ]h
s ReLU(Wh b ) (4)
0 h c a h
其中,W h 和 b h 为可学习参数,ReLU(rectified linear unit)为线性整流函数,这里用作激活函数.Reduce Hidden 的输
出作为解码器的初始隐藏状态,可以同时将 Code Encoder 提取到的语义序列信息和 AST Encoder 提取到的结构
信息传递给解码器.
2.4 解码器
CodePtr 使用的是加入了 Attention 机制和指针生成网络的解码器,在介绍 Attention 和指针生成网络前,首
先介绍没有添加 Attention 机制和指针生成网络的解码器.
ReduceHidden 的输出作为解码器的初始状态输入到解码器中,解码器在每个时刻将上一时刻目标序列的
单词向量和上一时刻的隐藏状态作为输入,计算出当前时刻的输出,即
s f dec ˆ (y t 1 ,s t 1 ) (5)
t
其中, f dec 在本文中使用了 GRU 单元, ˆ y t 1 表示目标序列在上一时刻的单词向量,s t1 为解码器上一时刻的隐藏状
态,s t 表示 t 时刻解码器的隐藏状态.编码器在每一时刻,将当前时刻的隐藏状态 s t 通过线性变换和 softmax 层后,
计算出词库中每一个单词的概率,其中概率最高的单词即为当前时刻的输出,即
( p yy t t | , ) softmax(s t W s s t b s ) (6)
其中, p(y t |y<t,s t )表示在 t 时刻之前所有输出单词和当前隐藏状态的条件下,输出词库中每个词的概率,W s 和 b s 为
可学习参数,softmax 表示 softmax 激活函数.解码器每一步都会挑选当前时刻概率最高的单词作为当前时刻的
输出,直到在某个时刻输出停止符号才停止.
2.5 Attention机制
编码器在对输入序列进行编码为固定大小的状态向量时本质上是一个有损压缩的过程,输入序列越长,由
压缩造成的损失就越大,较长的时间序列使得状态向量丢失了很多信息.同时,将不固定长度的输入序列压缩为
一个固定长度的向量,也丢失了输入序列的序列信息.最后,由于解码器得到的仅仅是一个固定长度的状态向
量,其无法直接关注到输入序列中的各种细节信息.出于以上考虑,CodePtr 引入了 Attention 机制.
NLP 领域的 Attention 机制首先由 Bahdanau 等人 [40] 提出,之后,Luong 等人 [20] 对其进行了优化,去掉了部分
冗余,简化了计算,提升了速度.Luong 等人提出了两种类型的 Attention 机制:Global Attention 和 Local Attention,
分别可以使 Attention 机制在整个输入序列中进行,或者在输入序列的局部进行,本文采用了前者.
由于我们的模型有 3 个编码器,需要使用 3 次 Attention 机制,这里,我们先将 Source Encoder 作为例子.在解
码器生成注释的过程中,Attention 机制首先将上一时刻的解码器状态与 Source Encoder 中所有的隐藏状态进行
对比和对齐,得到一个表示 t 时刻对 Source Encoder 的注意力分配权重、长度等于 Source Encoder 输入序列
s
,
长度的向量 a 即
t
a t s (s t 1 ) align(s t 1 ,output s ) (7)
其中,s t–1 表示解码器在上一时刻的状态,output s 为 Source Encoder 在编码时每一步的隐藏状态,align 为对齐函
s
s
数,对于长度为输入序列长度的向量 a 其元素值 a 表示在当前时刻解码器对 Source Encoder 的第 i 个隐藏状
,
ti
t
态的注意力权重,计算方法为
exp(score (s ,output ))
s
a ti align (s t 1 ,output si ) t 1 si (8)
j x T 1 exp(score (s t 1 ,output sj ))