一种残膜回收机防缠绕挑膜装置的制 一种秧草收获机用电力驱动行走机构

基于代码结构引导的方法名生成方法与流程

2022-03-16 02:54:55 来源:中国专利 TAG:


1.本发明涉及软件工程技术领域,具体地说,涉及一种基于代码结构引导的方法名生成方法。


背景技术:

2.程序的规范化命名在程序开发和维护期间尤为重要。语义描述的方法名可以看成是对程序时序功能的整体概括,其有助于开发人员对程序有一个整体理解,从而提高编程效率和避免方法误用。因为复杂的程序可以根据时序顺序分解为多个子方法,所以一般用驼峰命名法来将这些子方法包含其中。相反,和程序功能不一致的方法名混淆了开发人员对方法的理解,甚至导致对程序的误用,同时对于程序的维护和更新迭代造成了极大的困难。由于人为编写的方法名对代码的语义和结构没有准确地理解,在编写代码初期就有可能没有赋予正确的方法名,或者是在代码更新迭代的过程中,虽然添加了新功能,改变了代码的语法结构,代码名没有及时更新,代码开发的过程中还是会经常出现不规范甚至错误的方法名。为了解决这个问题,很多研究者已经通过不同的方式来根据方法内容来给出合适的方法名。例如,通过构造一些对源码分析的静态规则来给出恰当的方法名。然而,这些基于分析的方法的有效性取决于所构造的规则,这些规则不适用于任意的程序语言。抽象语法树(ast)能够对代码结构和内容进行明确地描述,通过对它的静态分析能够准确地还原源代码。因此,很多研究基于代码ast中的结构相似性来对给出推荐的方法名。但是,基于ast结构相似性的无法处理两大问题。其一,如果方法名中有未出现的词,那么它无法推测出正确的方法名;其二,它无法捕获结构相似较高代码段之间的差异。


技术实现要素:

3.本发明的内容是提供一种基于代码结构引导的方法名生成方法,其能够克服现有技术的某种或某些缺陷。
4.根据本发明的基于代码结构引导的方法名生成方法,其包括以下步骤:
5.一、将代码文本经过处理得到代码标记序列和代码关系图;
6.二、对代码标记序列和代码关系图分别进行编码,将它们根据映射关系对齐后将语义特征和结构特征传入解码器进行方法名生成。
7.作为优选,步骤一中,代码段通过fastast解析工具生成代表图结构的文本形式,然后通过分析优化生成代码关系图。
8.作为优选,编码包括上下文信息编码和代码关系图编码;
9.1)上下文信息编码为:使用基于rnn的seq2seq编码器对上下文向量集进行编码;对于上下文信息序列,用门控递归单元gru对其进行编码;对于代码关系图中的多种类型的边,对于每一种边,先用关系图网络对不同类型的边进行一轮节点间的消息传递和状态更新,再用ggnn对其进行编码;
10.gru的输入序列v
fi
表示一个上下文;每个向量表示上下文中方法名实体名称中的
子标记;对于每个时间步t,将从n个向量中选取向量vi放入到编码器中,得到一个隐藏状态向量h
t
作为这个时间步的输出;通过收集每个时间步的所有输出,得到一个隐藏状态向量的列表hi=[h1,h2,......,hn],这是gru的输出;输入序列v
fi
=[v1,v2,
……
,vn]由编码器学习并转换为隐藏向量h;解码器用于将表示隐藏向量h转换为目标序列y=[y1,y2,
……
,ym];
[0011]ht
=f(v
t
,h
t-1
)
ꢀꢀꢀ
(1)
[0012]h′
x
t=g(y
t-1
,h

t-1
,hi)
ꢀꢀꢀ
(2)
[0013]
p(y
t
|y1,

,y
t-1
,v
fi
)=s(y
t-1
,h
t
,hi)
ꢀꢀꢀ
(3)
[0014]
公式(1)为编码器rnn,h
t
为时间步长中的隐藏状态;函数f表示rnn动态函数;公式(2)是解码器的隐藏状态,h

t-1
是解码器在时间步长t-1的隐藏状态;函数g表示rnn动态函数;公式(3)用于预测:函数s为可能性计算函数;
[0015]
2)代码关系图编码为:用ggnn对代码关系图进行编码;图g=(v,e,x)由节点集合v,边集e=(e1,
……
,ek)和节点嵌入x构成,其中k代表边的类型的数目。对一任意u∈v,其对应于一个节点的嵌入xu∈r
dh
,其中dh表示节点嵌入的维度;具体的消息传递过程如下:
[0016]
2.1.每个节点都需要向其邻居发送消息;每个节点的消息由依赖于边缘类型的函数在其当前隐藏状态上转换;使用一个简单的线性层来表示边类型k在时间步k上的;通过每个节点所对应的节点嵌入xu初始化每个节点的隐藏状态,公式如下:
[0017][0018]
2.2.每一个节点u从他的邻节点通过按对应求和的方式聚合消息;n(u)代表节点u的邻节点,公式如下:
[0019][0020]
2.3.每一个节点u根据聚合的消息来更新它目前时间步的状态,更新函数是门控循环单元gru;
[0021][0022]
消息传递过程在时间步t上展开,并以每个节点u在最后一个时间步处的隐藏状态作为节点表示;通过加权求和所有节点表示,得到全局图状态rg;每个节点的权重是根据节点的隐层表示hu和节点的嵌入xu的级联计算得到的,具体如下:
[0023]
rg=∑
u∈v
σ(wi[hu:xu])

(w
jhu
);
[0024]
是两个可学习的矩阵,σ(
·
)是一个sigmoid函数;然后对两个输出应用对应相乘,最后对所有加权节点表示求和。
[0025]
作为优选,解码过程为:
[0026]
3.1.在任一时间步t,解码器会接收一个用于解码过程的隐藏状态s
t
,同时解码器也会接收编码器传来的隐藏状态向量的列表hi=[h1,h2,......,hn],通过计算内积得到每一步注意力的得分向量ei,公式如下:
[0027]ei
=v
r tanh(w1hi w2s);
[0028]
是权重矩阵,为权重向量;
[0029]
3.2.用softmax函数来注意力权重的概率分布α
t
,公式如下:
[0030]et
=[e1,e2,...,en];
[0031]
α
t
=sof tmax(e
t
);
[0032]
使用α
t
对隐藏状态向量的列表进行加权求和得到注意力模块的输出a
t

[0033][0034]
3.3.将注意力模块输出a
t
和解码器隐藏状态st进行拼接得到[a
t
:s
t
],作为计算解码器端的输出。
[0035]
本发明通过对代码关系图结构进行优化,让代码的结构信息更加丰富合理,更易于模型去获取代码的结构特征。本发明将代码文本标记与代码关系图节点建立映射关系,借此将代码的语义信息和结构信息对齐。本发明修改了序列生成序列模型的解码过程,每一步解码的过程都能接收了代码的语义信息和结构信息,使得通过模型生成的方法名综合考虑了代码的语义和结构。
附图说明
[0036]
图1为实施例1中基于代码结构引导的方法名生成方法的流程图;
[0037]
图2为实施例1中抽象代码序列的示意图;
[0038]
图3为实施例1中输入序列分布图。
具体实施方式
[0039]
为进一步了解本发明的内容,结合附图和实施例对本发明作详细描述。应当理解的是,实施例仅仅是对本发明进行解释而并非限定。
[0040]
实施例1
[0041]
如图1所示,本实施例提供了基于代码结构引导的方法名生成方法,其包括以下步骤:
[0042]
一、将代码文本经过处理得到代码标记序列和代码关系图;
[0043]
二、对代码标记序列和代码关系图分别进行编码,将它们根据映射关系对齐后将语义特征和结构特征传入解码器进行方法名生成。
[0044]
代码上下文信息
[0045]
我们的第一步是从源代码构建上下文信息。对于完整的代码段,可能要分别对内部上下文、同级上下文和封闭上下文构建上下文信息,而我们已经将方法体抽取出来,因此我们直接从方法体本身的文本中的程序实体、返回类型和接口中的类型中提取名称,我们将其称之为抽象代码序列,正如图2所示。考虑到代码中的命名规范,符合名称是不适合做语义提取的,如图2,“putinteger”几乎没有实际意义,而“put integer”代表放入整数这一实际语义,所以复合名称被分解成子标记,这些子标记在源代码中以相同的外观顺序收集到序列中,这些子标记的序列表示上下文信息,图2实例中的第一行代码文本被分解为“preferences put integer stringkey int val”。同时,这些子序列中不包含语义信息的特殊字符将会被删除,比如常用
“”
来分割代码中构成变量名的单词,我们提取完变量名中
的子token后会将
“”
删除。
[0046]
代码上下文信息被表示为向量序列,其中每个向量表示一个子令牌。此步骤的目标是为给定方法生成一个表示,该表示集成了其所有的上下文语义信息。代码关系图经过图神经网络编码也被表示为向量。此步骤的目标是为给定方法生成一个表示,该表示集成了其语法结构信息。通过两种表示的组合便能够得到该方法的总体表示。
[0047]
代码关系图
[0048]
fastast是一种源代码抽象语法树分析工具,它通过保持源代码文件的二进制形式层次的等价性来加速抽象语法树的解析。fast工具提供了一种代码关系图的形式,它是居于语法分析来构建代码关系图,我们用它来从源代码生成对应的代码关系图数据。代码关系图的总体框架是基于抽象语法树构建的,对于其中几种特殊的节点我们做了相应的处理从而来丰富代码关系图的语义。“name”节点代表了名称节点,它包含了类名称、方法名称和参数名称等。我们认为名称节点在代码语义表达中占据了重要地位,同时也会对方法名生成起到关键作用,所以我们保留了名称节点的语义信息,并对这些节点进行了子标记化。同样的,“operator”节点代表了操作节点,它一般代表调用操作和运算操作,比如加法操作“ ”,与操作“&”,调用操作“.”等。因为它对代码语义影响也很大,所以我们也同样保留操作节点的语义信息。“dummy”节点代表了一些常量,比如字符串和整数,对于常量节点,我们将它抽象为常量节点。原因主要有两点,其一,代码中出现的字符串的语义信息对于方法名生成的作用不大;其二,在对源代码中的字符串进行编码时,将字符串丰富语义进行压缩时具有较大的难度。所以,我们对常量节点做以上处理。对于其他节点,我们认为,没有必要将其特殊化。比如,代表作用范围的“block”节点,我们对于“block{”和“block}”不会加以区分,而是全部当成“block”节点,它的作用只是指示了代码的作用域范围信息。对于原始工具中解析的“last-use”边,原始工具中保留了包括符号的最后使用关系,而我们只保留变量的最后使用关系。和子标记序列一样,我们对于变量名称节点也进行了子标记化。除此以外,为了加强实验的严谨性,我们会提前将方法名节点用特殊字符串去掩饰,避免提前暴露方法名的语义信息。总体来看,代码关系图就像一个关系图,刻画了代码中每个节点之间的关系,并且这些关系有多种类型,最终形成一个完整的代码关系图。
[0049]
需要同时对代码的语义信息和语法信息进行混合编码。
[0050]
上下文信息编码
[0051]
使用基于rnn的seq2seq编码器对上下文向量集进行编码;对于上下文信息序列,用门控递归单元gru对其进行编码;对于代码关系图中的多种类型的边,对于每一种边,先用关系图网络对不同类型的边进行一轮节点间的消息传递和状态更新,再用ggnn对其进行编码。
[0052]
gru的输入序列v
fi
表示一个上下文。每个向量表示上下文中方法名实体名称中的子标记。对于每个时间步t,我们将从n个向量中选取向量vi放入到编码器中,我们得到一个隐藏状态向量h
t
作为这个时间步的输出。通过收集每个时间步的所有输出,我们有一个隐藏状态向量的列表hi=[h1,h2,......,hn],这是gru的输出。理论上讲,输入序列v
fi
=[v1,v2,
……
,vn]由编码器学习并转换为隐藏向量h。解码器用于将表示隐藏向量h转换为目标序列y=[y1,y2,
……
,ym]
[0053]ht
=f(v
t
,h
t-1
)
ꢀꢀꢀ
(1)
[0054]h′
x
t=g(y
t-1
,h

t-1
,hi)
ꢀꢀꢀ
(2)
[0055]
p(y
t
|y1,

,y
t-1
,v
fi
)=s(y
t-1
,h
t
,hi)
ꢀꢀꢀ
(3)
[0056]
公式1为编码器rnn,h
t
为时间步长中的隐藏状态;函数f表示rnn动态函数;公式2是解码器的隐藏状态,h

t
是解码器在时间步长t的隐藏状态;函数g表示rnn动态函数;公式3用于预测:函数s可能性计算函数。最后,我们取得hi=[h1,h2,......,hn]和hn。这是编码器的输出,用于注意层。因为上下文中的所有子标记不是都是同等重要的,所以我们的目标是更多关注某些子标记,我们通过注意力机制来实现这一机制。
[0057]
代码关系图编码
[0058]
用ggnn对代码关系图进行编码;与自然语言不同的是,源代码包含复杂且易于获取的结构信息,这些信息可以用ast来表示。传统的序列编码器将源代码视为纯文本,忽略了丰富的结构信息。而图神经网络可以直接应用到输入图中,从而充分捕捉源代码的句法和语义信息。我们的图形编码器基于fernandes等人提出的图形组件,该组件是根据门控图神经网络(ggnn)开发的。图g=(v,e,x)由节点集合v,边集e=(e1,
……
,ek)和节点嵌入x构成,其中k代表边的类型的数目。对一任意u∈v,其对应于一个节点的嵌入xu∈r
dh
,其中dh表示节点嵌入的维度。具体的消息传递过程如下:
[0059]
2.1.每个节点都需要向其邻居发送消息。每个节点的消息由依赖于边缘类型的函数在其当前隐藏状态上转换。在我们的工作中,我们使用一个简单的线性层来表示边类型k在时间步k上的。我们通过每个节点所对应的节点嵌入xu初始化每个节点的隐藏状态
[0060][0061]
2.2.每一个节点u从他的邻节点通过按对应求和的方式聚合消息。n(u)代表节点u的邻节点。
[0062][0063]
2.3.每一个节点u根据聚合的消息m(t)u来更新它目前时间步的状态,更新函数是门控循环单元(gru)。
[0064][0065]
消息传递过程在时间步t上展开,并以每个节点u在最后一个时间步处的隐藏状态作为节点表示。此外,我们还通过加权求和所有节点表示,得到全局图状态rg。每个节点的权重是根据节点的隐层表示hu和节点的嵌入xu的级联计算得到的,具体如下:
[0066]
rg=∑
u∈v
σ(wi[hu:xu])

(w
jhu
);
[0067]
是两个可学习的矩阵,σ(
·
)是一个sigmoid函数。然后我们对两个输出应用对应相乘,最后对所有加权节点表示求和。
[0068]
解码过程
[0069]
seq2seq中,编码器端的末位的隐藏状态是对整个句子的概述,它需要包含整个句
子的信息,但是这时候随着句子的变长,想要包含整个句子的信息往往是很困难的。因此注意力机制采用的方法就是,在解码器端的每一步,都会选择编码器端的某一部分组成上下文信息矩阵,然后再输出每一步的结果。具体实现如下:
[0070]
首先,在任一时间步t,解码器会接收一个用于解码过程的隐藏状态s
t
,同时解码器也会接收编码器传来的隐藏状态向量的列表hi=[h1,h2,......,hn],我们通过计算内积得到每一步注意力的得分向量ei,公式如下:
[0071]ei
=v
t tanh(w1hi w2s);
[0072]
是权重矩阵,为权重向量。
[0073]
接着,我们用softmax函数来注意力权重的概率分布α
t
,公式如下:
[0074]et
=[e1,e2,...,en];
[0075]
α
t
=sof tmax(e
t
);
[0076]
我们使用α
t
对隐藏状态向量的列表进行加权求和得到注意力模块的输出a
t
[0077][0078]
最后,我们将注意力模块输出a
t
和解码器隐藏状态s
t
进行拼接得到[a
t
:s
t
],作为计算解码器端的输出。
[0079]
seq-to-seq方法虽然可以自由的生成文本,但是表现出很多表现不佳的行为,包括不限于不准确地再现事实细节、无法处理词汇表外(oov)单词以及生成重复的单词。指针生成器网络(pgn)有助于通过指针从源文本复制单词,这提高了oov单词的准确性和处理能力,同时保留了生成新词的能力。这个网络可以看作是提取和抽象生成方法之间的平衡。我们还加入了coverage向量,用来跟踪和控制源文件的重复范围。我们证明converage对于消除重复是非常有效的。
[0080]
指针网络
[0081]
在模型中加入指针网络,一方面通过seq2seq模型保持抽象生成的能力,另一方面通过pointernetwork直接从原文中取词,提高摘要的准确度和缓解oov问题。在预测的每一步,通过动态计算一个生成概率pgen∈[0,1],把二者软性地结合起来,具体地,在t时刻:
[0082][0083]
其中,w
h*
,ws,w
x
都是可学参数,s
t
是解码状态,是上下文向量,x
t
是解码器每一个时间步的输入。在解码阶段需要维护一个扩展的词典,即原本词典加上source中出现的所有词语,我们在这个扩展的词典上计算所有token的概率:
[0084][0085]
在这里,如果w是oov,则p
vocab
为0,相同的,如果w没有出现在source中,则后面一项也为0。
[0086]
重复检测
[0087]
重复是seq2seq模型经常出现的问题,我们引入coverage model来解决这个问题。具体实现上,就是将之前所有时间步的注意力权重相加到一个覆盖向量(coverage vector)c
t
上。就是用先前的注意力权重决策来影响当前注意力权重的决策,这样就避免在同一位置重复,从而避免重复生成文本。具体计算如下:
[0088][0089]
然后将覆盖向量添加到注意力权重的计算过程中:
[0090][0091]
这就可以使得在计算注意力权重时,当前的决定是受到历史决定影响的,这样就可以让注意力机制避免重复关注某个位置,也就可以避免生成重复词语。
[0092]
coverage loss的计算方式如下:
[0093][0094]
模型最终的loss为:
[0095][0096]
其中λ为超算数。
[0097]
解码过程在解码器中,我们得到了输入序列每一个时间步最后一层gru的隐层状态h=[h1,h2,......,hn]和每一层gru最后时刻的隐层状态hn,解码器将按时间步接收来自编码器的输入,然后逐步输出生成的序列。此时hn表示输入序列的最终状态,而h表示序列中每一个子标记的状态。为了能够将代码的结构信息融入代表文本信息的子标记序列中,我们将代码关系图最终表示向量和最终状态hn合并,同时将节点表示和状态序列h进行合并。在将图数据输入到图神经网络中时,各节点已经通过消息传递向邻节点进行了信息传递,而代码关系图有比较多的节点每个图都是共享的,所以我们只需要定位到与输入序列中的子标记对应的节点,并获取它们在图神经网络中进行消息迭代迭代后的节点表示,然后将它们并入状态序列h中,这样既过滤掉了其他节点的冗余信息也让模型处理信息时能够将节点和序列能够对应起来。
[0098][0099][0100]
wi∈r
2dn
×1是一个可学习的矩阵。
[0101]
实验分析
[0102]
为了研究代码文本标记序列的长度对于实验结果是否有影响,我们从总样本中随机选择了10k个样本进行分析,发现大部分标记序列长度小于200,还有一小部分集中在[200,400]这一区间,如图3所示。我们在设定不同的最大输入序列长度的情况下进行了实验。
[0103]
为了为代码生成规范化的方法名,模型综合考虑了代码的语义和结构,生成的方法名在符合代码的语义的同时也能够反映出代码的结构特征。我们将整个过程分为两步,首先通过文本摘要手段对代码标记序列进行信息提取,然后通过代码关系图提供的结构信息来帮助解码器进行代码名的生成。同时,我们设计了一个映射机制,来对代码标记序列和节点建立对应关系,从而准确地将代码结构信息传递到解码器中。在未来,我们计划探索更适合处理代码结构数据的模型,从而进一步提高生成的方法名的质量。
[0104]
本实施例提出了一种综合考虑代码语义和结构的代码方法名生成的轻量级模型。为了清晰地表示代码结构,我们构建了一种全新的代码图,称之为代码关系图(crg)。crg在
保留抽象语法树结构和复杂度的同时,融合了数据流等信息,提高了信息密度。在我们的方法中,我们对输入序列进行标记化,并将标记化后的令牌根据匹配关系映射到crg中,借此将代码文本标记与crg中的图节点建立映射关系。我们将这一关系存入映射矩阵,以便能够将对应的图节点信息提取出来。这样做,我们不仅完整保证了代码的结构信息的完整性,而且大幅减小了代码结构信息的冗余程度。在解码过程中,模型同时接收代码的语义特性和结构特性,综合考虑了代码的语义和结构后生成规范化的方法名。为进一步增强模型的解码能力,我们在模型中引入权值共享机制来让编码器和解码器共享词嵌入信息。本实施例在具有700k个样本的公开数据集java-small上证明了所提出方法的有效性,其在rouge度量中比最先进的模型高出1.5%-3.5%。
[0105]
以上示意性的对本发明及其实施方式进行了描述,该描述没有限制性,附图中所示的也只是本发明的实施方式之一,实际的结构并不局限于此。所以,如果本领域的普通技术人员受其启示,在不脱离本发明创造宗旨的情况下,不经创造性的设计出与该技术方案相似的结构方式及实施例,均应属于本发明的保护范围。
再多了解一些

本文用于企业家、创业者技术爱好者查询,结果仅供参考。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

相关文献