余天賜,高 尚
(江蘇科技大學(xué)計(jì)算機(jī)學(xué)院,江蘇 鎮(zhèn)江 212100)
代碼注釋用于描述程序中關(guān)鍵代碼的功能、注意事項(xiàng)和約束條件等,幫助開發(fā)人員更好地理解代碼的實(shí)現(xiàn)意圖和工作原理,在軟件開發(fā)和維護(hù)過程中起到重要作用?,F(xiàn)如今,隨著軟件規(guī)模不斷增大,很多軟件項(xiàng)目存在著代碼注釋缺失、描述不清晰等情況,導(dǎo)致開發(fā)人員需要花費(fèi)更多的時(shí)間和精力去閱讀和理解代碼,從而降低了開發(fā)和維護(hù)效率。代碼注釋自動(dòng)生成通過機(jī)器學(xué)習(xí)的方法構(gòu)建編程語言到自然語言注釋的映射模型,訓(xùn)練好的模型可以分析代碼的語法結(jié)構(gòu)、標(biāo)識(shí)符名稱、函數(shù)參數(shù)和返回值等元素,自動(dòng)生成高質(zhì)量的代碼注釋,不僅可以提高開發(fā)人員的編碼效率,還提高了代碼的可讀性、可維護(hù)性和可重用性。
代碼注釋生成研究中存在2個(gè)主要問題,一是代碼的表示,二是注釋生成。不同的源代碼表示將直接影響抽取源代碼信息的質(zhì)量,從而影響生成注釋的質(zhì)量?,F(xiàn)有的研究方法主要用抽象語法樹AST(Abstract Syntax Tree)一種結(jié)構(gòu)信息表示代碼,沒有考慮代碼其他類型的結(jié)構(gòu)信息,例如數(shù)據(jù)流和控制流,使得模型生成的注釋存在準(zhǔn)確率低和可讀性差的問題。
為了提升模型生成注釋的質(zhì)量,本文提出一種融合多結(jié)構(gòu)信息的代碼注釋生成模型,模型先將AST處理為特定格式的序列,使用Transformer編碼器對(duì)AST序列進(jìn)行編碼,捕獲全局信息。使用圖神經(jīng)網(wǎng)絡(luò)GNN(Graph Neural Network)[1]對(duì)數(shù)據(jù)流圖進(jìn)行特征提取,提供變量之間的計(jì)算依賴關(guān)系等信息,然后使用跨模態(tài)注意力機(jī)制(Crossmodal Attention)融合抽象語法樹和數(shù)據(jù)流2種特征,經(jīng)過Transformer解碼器生成相應(yīng)的注釋。通過使用Java和Python編程語言的代碼-注釋數(shù)據(jù)集驗(yàn)證了本文模型性能優(yōu)于6種主流對(duì)比模型,消融實(shí)驗(yàn)也驗(yàn)證了融合抽象語法樹和數(shù)據(jù)流圖2種特征的有效性。
近年來,研究人員設(shè)計(jì)出不同的基于深度學(xué)習(xí)的代碼注釋生成模型,這些模型采用了不同的代碼表示方法和不同的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu),但它們普遍使用序列到序列(Sequence-to-Sequence)的框架。在代碼注釋生成模型中有2個(gè)重要環(huán)節(jié):代碼表示和注釋生成。代碼注釋生成過程通??梢苑譃?個(gè)階段:數(shù)據(jù)處理階段、模型訓(xùn)練階段和模型測(cè)試階段。代碼表示模型是代碼注釋自動(dòng)生成中的核心問題,根據(jù)代碼的不同表現(xiàn)形式,可將現(xiàn)有的代碼表示模型分為3類。
第1類是基于詞元(token)序列的代碼表示模型。在這些模型中,代碼的變量名、方法名和標(biāo)識(shí)符被看作普通文本。Haiduc等[2]采用信息檢索技術(shù)對(duì)源代碼進(jìn)行分析處理,從中找出合適的詞語,生成由關(guān)鍵詞組成的代碼注釋。Zheng等[3]提出的模型利用注意力機(jī)制配合編碼器獲取代碼語義信息,模型識(shí)別代碼中的循環(huán)、選擇等重要結(jié)構(gòu),并將其中的關(guān)鍵字嵌入表示為詞向量,作為編碼器的輸入。Hu等[4]利用應(yīng)用程序編程接口API(Application Programming Interface)序列輔助模型生成代碼注釋。
第2類是基于抽象語法樹的代碼表示模型。Alon等[5]提出的模型將代碼表示為AST的多條路徑集,利用LSTM對(duì)每個(gè)路徑序列進(jìn)行編碼,在注意力機(jī)制的配合下解碼生成代碼注釋。Zhang等[6]將AST拆分成一系列小型語句樹,并通過捕獲代碼語句的詞匯和語法知識(shí)將語句樹編碼為向量。該方法解決了AST結(jié)構(gòu)復(fù)雜的問題,提高了計(jì)算性能。Hu等[7]利用2種編碼器分別編碼代碼序列和AST序列,在注意力機(jī)制的幫助下融合2種特征,最后使用解碼器生成代碼注釋。
第3類是基于圖的代碼表示模型。這類模型利用圖結(jié)構(gòu)表征程序的AST、數(shù)據(jù)流和控制流等信息。戎珂瑤等[8]利用異質(zhì)圖結(jié)構(gòu)和圖神經(jīng)網(wǎng)絡(luò),將源代碼的抽象語法樹、控制流圖和數(shù)據(jù)流圖等融合并構(gòu)建為具有多種節(jié)點(diǎn)和邊的異質(zhì)表示圖,提出了基于多維度異質(zhì)圖結(jié)構(gòu)的代碼注釋自動(dòng)生成模型。LeClair等[9]使用圖卷積神經(jīng)網(wǎng)絡(luò)處理圖結(jié)構(gòu)表征的AST,并將基于圖卷積神經(jīng)網(wǎng)絡(luò)的編碼器輸出與基于代碼token序列編碼器的輸出相結(jié)合。模型可以學(xué)習(xí)到代碼結(jié)構(gòu)與序列間的關(guān)系。Allamanis等[10]設(shè)計(jì)了一種基于門控圖神經(jīng)網(wǎng)絡(luò)的代碼表示模型。模型使用圖表示代碼的AST和數(shù)據(jù)流信息。訓(xùn)練好的模型可以為給定代碼段預(yù)測(cè)變量名。與前2類代碼表示模型相比,基于圖的代碼表示模型更適合表示源代碼的結(jié)構(gòu)信息。
本文利用抽象語法樹和數(shù)據(jù)流圖可以表示代碼中不同類型的結(jié)構(gòu)信息,提出一種融合多結(jié)構(gòu)信息的代碼注釋生成模型。
代碼注釋生成任務(wù)可以形式化為有監(jiān)督機(jī)器學(xué)習(xí)問題。本文使用C={c1,…,ci}表示代碼片段,S={s1,…,si}表示與代碼對(duì)應(yīng)的注釋句子,構(gòu)建由(C,S)對(duì)組成的訓(xùn)練集,通過對(duì)模型訓(xùn)練,得到注釋生成模型f,當(dāng)輸入代碼片段ci時(shí),模型f可以自動(dòng)生成注釋si。
本文提出的融合多結(jié)構(gòu)信息的代碼注釋生成模型結(jié)構(gòu)如圖1所示,模型主要包含以下3部分:抽象語法樹編碼器、數(shù)據(jù)流圖編碼器和解碼器。抽象語法樹編碼器將原始的AST序列轉(zhuǎn)換為一個(gè)固定維度的向量,以捕捉AST中的語義和結(jié)構(gòu)信息。數(shù)據(jù)流圖編碼器使用圖神經(jīng)網(wǎng)絡(luò)將代碼數(shù)據(jù)流圖轉(zhuǎn)換成固定維度的向量,以捕捉代碼數(shù)據(jù)流中的變量依賴關(guān)系等關(guān)鍵信息。解碼器接收跨模態(tài)注意力機(jī)制生成的中間向量表示,然后將其解碼為代碼注釋序列。其中,抽象語法樹編碼器由N個(gè)相同的編碼器層堆疊而成,解碼器由N個(gè)相同解碼器層堆疊而成。
Figure 1 Structure of the proposed model
3.3.1 抽象語法樹編碼器
抽象語法樹AST是由節(jié)點(diǎn)和邊組成的樹狀結(jié)構(gòu),每個(gè)節(jié)點(diǎn)表示代碼中的一個(gè)語法結(jié)構(gòu)。AST的非葉節(jié)點(diǎn)主要表示代碼中的各種語句,例如循環(huán)、判斷語句以及聲明語句。而葉子節(jié)點(diǎn)表示標(biāo)識(shí)符等,例如變量名、參數(shù)名和函數(shù)名。本文使用Transformer[11]的編碼器來提取代碼抽象語法樹的上下文信息。為了使AST能夠作為編碼器的輸入,需要將AST轉(zhuǎn)換為特定格式的序列,本文參考文獻(xiàn)[12]的方法,處理過程如下:從根節(jié)點(diǎn)開始,首先使用一對(duì)括號(hào)來表示樹結(jié)構(gòu),并將根節(jié)點(diǎn)本身放在右括號(hào)后面。然后,遍歷根節(jié)點(diǎn)的子樹,并將子樹的所有根節(jié)點(diǎn)放入括號(hào)中。如此遞歸遍歷,直到遍歷完所有節(jié)點(diǎn),得到最終序列。
圖2表示一段Java代碼,其對(duì)應(yīng)的抽象語法樹如圖3所示。
Figure 2 Java code
Figure 3 Abstract syntax tree of Java code in figure 2
將如圖3抽象語法樹轉(zhuǎn)換成序列可以表示為:(MethodDeclaration(int)int(minNum)minNum(parameters)parameters(BlockStmt(…))BlockStmt)MethodDeclaration。使用這種格式的序列,可以使模型從AST中學(xué)習(xí)到代碼的語義和語法信息。
抽象語法樹編碼器使用X={x1,…,xl}表示某一代碼片段的AST序列,l表示序列長度,X∈Rl×dAST,dAST表示嵌入的維度。獲得AST序列嵌入表示后,利用位置編碼捕獲序列的位置信息。
PE(i,2m)=sin(i/100002m/dAST)
(1)
PE(i,2m+1)=cos(i/100002m/dAST)
(2)
其中,i表示序列X中token的位置,m是位置編碼的維度索引,2m表示偶數(shù)維度,2m+1表示奇數(shù)維度,當(dāng)位置編碼維度為偶數(shù)時(shí)使用式(1)計(jì)算,當(dāng)位置編碼維度為奇數(shù)時(shí)使用式(2)計(jì)算。
將序列嵌入向量和位置編碼相加后,可以得到AST序列的輸入特征Xinput,如式(3)所示:
Xinput=X+PE
(3)
(4)
A=[a1,a2,…,ah]
(5)
Z=LayerNorm(Xinput+AWO)
(6)
XAST=LayerNorm(Z+FFN(Z))
(7)
其中,dr表示矩陣Qj和Kj的維度,h表示注意力頭的個(gè)數(shù)。LayerNorm(·)表示歸一化操作,WO表示權(quán)重矩陣,FFN(·)表示前饋神經(jīng)網(wǎng)絡(luò)。抽象語法樹編碼器由N個(gè)相同編碼器層堆疊而成。
3.3.2 數(shù)據(jù)流圖編碼器
數(shù)據(jù)流圖DFG(Data Flow Graph)以圖的形式記錄了代碼段中變量的賦值和傳播過程。其中,圖的節(jié)點(diǎn)表示變量,邊表示變量的來源。這種圖結(jié)構(gòu)為代碼理解提供了關(guān)鍵的代碼語義信息。圖4表示圖2中Java代碼的數(shù)據(jù)流圖。
Figure 4 Data flow graph of Java code in figure 2
數(shù)據(jù)流圖編碼器使用圖神經(jīng)網(wǎng)絡(luò)GNN[1]提取數(shù)據(jù)流圖特征,GNN通過聚合鄰居節(jié)點(diǎn)的信息來更新節(jié)點(diǎn)的特征表示,最終得到數(shù)據(jù)流圖的嵌入表示。數(shù)據(jù)流圖是一種有向圖,為了使圖神經(jīng)網(wǎng)絡(luò)在處理有向圖時(shí)不丟失方向信息,需要同時(shí)從節(jié)點(diǎn)的傳入和傳出方向進(jìn)行消息傳遞。數(shù)據(jù)流圖編碼器具體計(jì)算過程如下:使用G=(V,E)表示數(shù)據(jù)流圖,V表示變量節(jié)點(diǎn)的集合,E表示邊的集合。圖中節(jié)點(diǎn)的連接關(guān)系使用鄰接矩陣A∈RN×N表示,N表示節(jié)點(diǎn)個(gè)數(shù)。vi∈V表示節(jié)點(diǎn),(vi,vj)∈E表示從節(jié)點(diǎn)vi指向vj的一條有向邊,1≤i,j≤N。用N├(v)={u∈V|(v,u)∈E}表示節(jié)點(diǎn)v所有前向鄰居的集合,即v指向的節(jié)點(diǎn)。用N┤(v)={u∈V|(u,v)∈E}表示節(jié)點(diǎn)v所有后向鄰居的集合,即指向v的節(jié)點(diǎn)。使用xv表示節(jié)點(diǎn)v經(jīng)過嵌入后的文本特征向量,矩陣Xnode∈RN×dnode存儲(chǔ)所有節(jié)點(diǎn)的文本特征向量,其中dnode表示特征向量的維度。圖4中變量x1的一階前向鄰居為x5和x8,二階前向鄰居為z7,z7的一階后向鄰居為x8。圖神經(jīng)網(wǎng)絡(luò)主要通過聚合節(jié)點(diǎn)K階鄰居的信息來更新節(jié)點(diǎn)特征。圖神經(jīng)網(wǎng)絡(luò)主要計(jì)算過程如下:對(duì)所有節(jié)點(diǎn),先初始化節(jié)點(diǎn)的前向表示和后向表示為其文本特征向量,如式(8)所示:
(8)
(9)
其中,AGGREGATE(·)表示聚合操作。
(10)
其中,σ(·)表示非線性激活函數(shù),Wk表示權(quán)重矩陣。
同理,將相同的過程應(yīng)用于后向表示。
(11)
(12)
本文使用均值聚合方法。
(13)
經(jīng)過K次聚合過程,拼接節(jié)點(diǎn)最終的前向表示和后向表示得到向量Zv,作為節(jié)點(diǎn)v的特征向量。
(14)
最后將節(jié)點(diǎn)的特征向量傳入一個(gè)前饋神經(jīng)網(wǎng)絡(luò),并使用最大池化方法得到數(shù)據(jù)流圖的特征向量XDFG,如式(15)所示:
XDFG=max({σ(WZv+b),v∈V})
(15)
其中,W表示權(quán)重矩陣,b表示偏置向量。
本文使用一個(gè)跨模態(tài)注意力模塊Crossmodal attention[13]來融合抽象語法樹特征和數(shù)據(jù)流圖特征,這樣可以使抽象語法樹編碼器接收數(shù)據(jù)流圖編碼器的信息。
本文使用XAST∈RTα×dα表示抽象語法樹特征,XDFG∈RTβ×dβ表示數(shù)據(jù)流圖特征,其中,T(·)表示特征序列長度,d(·)表示特征的維度。分別定義查詢矩陣Qα,索引矩陣Kβ和值矩陣Vβ。經(jīng)過下列計(jì)算可得融合后的特征ZFusion。
Qα=XASTWQα
(16)
Kβ=XDFGWKβ
(17)
Vβ=XDFGWVβ
(18)
(19)
其中,WQα∈Rdα×ds,WKβ∈Rdβ×ds,WVβ∈Rdβ×dv為權(quán)重矩陣。其中,ds和dv分別表示權(quán)重矩陣對(duì)應(yīng)的維度。
本文使用Transformer的解碼器來生成代碼注釋。解碼器部分由N個(gè)解碼器層堆疊而成,每個(gè)解碼器層由3個(gè)子層連接組成,第1個(gè)子層包括帶掩碼的多頭自注意力機(jī)制、殘差連接以及規(guī)范化層。使用帶掩碼的多頭自注意力機(jī)制可以確保預(yù)測(cè)僅依賴于已生成的輸出詞元。第2個(gè)子層包括連接融合特征和解碼器的多頭注意力機(jī)制、殘差連接以及規(guī)范化層。其中的多頭注意力機(jī)制與之前抽象語法樹編碼器中多頭注意力機(jī)制不同,查詢來自前一個(gè)解碼器層的輸出,而鍵和值來自于融合特征,這樣能夠使解碼器捕獲到抽象語法樹序列和數(shù)據(jù)流圖特征信息。第3個(gè)子層包括前饋神經(jīng)網(wǎng)絡(luò)、殘差連接以及規(guī)范化層。經(jīng)過N個(gè)解碼器層的計(jì)算后,使用線性層得到指定維度的向量。最后經(jīng)過softmax層得到概率向量,模型選擇具有最高概率的單詞作為輸出。
本文使用交叉熵?fù)p失函數(shù)來訓(xùn)練模型,損失函數(shù)如式(20)所示:
(20)
其中,n表示整個(gè)輸出序列的長度,yt表示模型預(yù)測(cè)第t時(shí)間步的token。訓(xùn)練過程中,通過最小化損失函數(shù)得到模型參數(shù)。
為了有效評(píng)估本文模型,實(shí)驗(yàn)數(shù)據(jù)集采用CodeXGLUE(General Language Understanding Evaluation benchmark for Code)中Java和Python語言代碼-注釋數(shù)據(jù)集[14]。Java語言數(shù)據(jù)集包含181 061對(duì)代碼-注釋對(duì)。其中,164 923對(duì)數(shù)據(jù)用于訓(xùn)練模型,10 955對(duì)數(shù)據(jù)用于測(cè)試模型,5 183對(duì)數(shù)據(jù)作為驗(yàn)證集。Python語言數(shù)據(jù)集包含280 652對(duì)代碼-注釋對(duì)。其中,251 820對(duì)數(shù)據(jù)用于訓(xùn)練模型,14 918對(duì)數(shù)據(jù)用于測(cè)試模型,13 914對(duì)數(shù)據(jù)作為驗(yàn)證集。
在模型訓(xùn)練之前,需要對(duì)代碼和注釋數(shù)據(jù)進(jìn)行預(yù)處理,將其轉(zhuǎn)換為可以作為模型輸入的數(shù)據(jù)結(jié)構(gòu)。
本文使用開源工具tree-sitter為Java和Python代碼構(gòu)建抽象語法樹。tree-sitter是一個(gè)生成解析器的工具。它可以為多種語言的代碼構(gòu)建語法樹。生成抽象語法樹的主要步驟如下:首先,對(duì)代碼進(jìn)行詞法分析,將其分割成多個(gè)詞法單元,例如關(guān)鍵字、標(biāo)識(shí)符和操作符等。然后進(jìn)入語法分析階段,語法分析器按照不同編程語言的語法規(guī)則,對(duì)詞法單元進(jìn)行分析和組織,最后構(gòu)建出一棵抽象語法樹。為了方便模型訓(xùn)練,在構(gòu)建抽象語法樹的過程中,需要?jiǎng)h除節(jié)點(diǎn)數(shù)超過1 000以及因語法錯(cuò)誤導(dǎo)致構(gòu)建抽象語法樹失敗的數(shù)據(jù)集,最后將處理好的數(shù)據(jù)存儲(chǔ)在JSONL格式文件中。
數(shù)據(jù)流圖的構(gòu)建主要參考文獻(xiàn)[15]中使用的方法,具體構(gòu)建步驟如下:根據(jù)抽象語法樹中的葉子節(jié)點(diǎn)來識(shí)別變量序列,這些變量序列中的每一個(gè)元素都會(huì)成為數(shù)據(jù)流圖中的一個(gè)節(jié)點(diǎn)。然后根據(jù)抽象語法樹中變量之間的依賴關(guān)系,生成數(shù)據(jù)流圖的有向邊。以集合形式存儲(chǔ)變量節(jié)點(diǎn),使用鄰接矩陣表示節(jié)點(diǎn)間的連接關(guān)系。
實(shí)驗(yàn)包含基本參數(shù)設(shè)置。抽象語法樹編碼器中編碼器層數(shù)N為6,多頭注意力機(jī)制頭的個(gè)數(shù)h為8,嵌入維度dAST為512。數(shù)據(jù)流圖編碼器中節(jié)點(diǎn)嵌入維度dnode為512,聚合節(jié)點(diǎn)鄰居階數(shù)K為2。解碼器中解碼器層數(shù)N為6,帶掩碼的多頭注意力機(jī)制頭的個(gè)數(shù)為8。使用Adam優(yōu)化器訓(xùn)練模型,初始學(xué)習(xí)率設(shè)置為0.001。
實(shí)驗(yàn)采用BLEU(BiLingual Evaluation Understudy)[16]、METEOR(Metric for Evaluation of Translation with Explicit ORdering)[17]和ROUGE(Recall-Oriented Understudy for Gisting Evaluation)[18]3種評(píng)估指標(biāo)來評(píng)估模型生成代碼注釋的質(zhì)量。
BLEU是一種基于n-gram精確度的評(píng)估指標(biāo),可以自動(dòng)分析模型生成注釋與參考注釋之間的相似度。BLEU分?jǐn)?shù)的取值范圍是0到1,越接近1表示模型生成注釋的質(zhì)量越好。
METEOR在評(píng)估中加入召回率來反映模型生成注釋與參考注釋的相似程度。分?jǐn)?shù)越高表示模型生成注釋越接近參考注釋。與BLEU不同的是,METEOR將模型生成注釋與參考注釋進(jìn)行對(duì)齊,以便更好地評(píng)估模型生成注釋的質(zhì)量。
ROUGE是一種基于召回率的文本摘要質(zhì)量評(píng)估指標(biāo)。它含有4種指標(biāo):ROUGE-L、ROUGE-S、ROUGE-N以及ROUGE-W。在代碼注釋質(zhì)量評(píng)估中常使用ROUGE-L,它是基于最長公共子序列的召回率和精確度來計(jì)算的。
為了驗(yàn)證模型有效性,本文選用以下幾種相關(guān)代碼注釋生成模型進(jìn)行對(duì)比分析。
(1)Tree2Seq[19]:使用基于樹的LSTM作為編碼器捕獲AST的結(jié)構(gòu)信息。
(2)code2seq[20]:使用AST的多條隨機(jī)路徑集表示代碼片段,通過LSTM編碼AST路徑,在注意力機(jī)制的配合下解碼生成代碼注釋。
(3)Code-NN[21]:將代碼表示為token序列,然后利用LSTM和注意力機(jī)制生成代碼注釋。
(4)DeepCom[11]:對(duì)代碼AST進(jìn)行結(jié)構(gòu)遍歷得到可以作為模型輸入的特定格式序列,這種序列可以更好地表示代碼的結(jié)構(gòu)信息。
(5)CodeGNN[8]:包含2個(gè)編碼器,一個(gè)使用GRU編碼源代碼序列,另一個(gè)使用圖神經(jīng)網(wǎng)絡(luò)編碼代碼的AST。
(6)Transformer[22]:使用多頭注意力機(jī)制編碼輸入和解碼輸出,并利用位置編碼學(xué)習(xí)代碼序列中token的位置關(guān)系。
4.6.1 對(duì)比實(shí)驗(yàn)
表1展示了本文模型和對(duì)比模型在CodeXGLUE中Java和Python語言代碼-注釋數(shù)據(jù)集上的實(shí)驗(yàn)結(jié)果。通過表1可以看出,本文提出的融合多結(jié)構(gòu)信息的代碼注釋生成模型在2個(gè)數(shù)據(jù)集上的BLEU-4、METEOR和ROUGE-L 指標(biāo)均優(yōu)于對(duì)比模型。
Table 1 Results of different models on Java and Python datasets
具體地,基于代碼token序列的Code-NN模型,僅考慮了代碼的語義信息,從代碼中抽取關(guān)鍵字,沒有充分利用代碼結(jié)構(gòu)特征,因此模型生成的注釋質(zhì)量較低?;诔橄笳Z法樹的代碼注釋生成模型,例如Tree2Seq、code2seq和DeepCom,這類模型通常用AST的節(jié)點(diǎn)序列、路徑集合來表示源代碼。因?yàn)槌橄笳Z法樹可以表示代碼的抽象句法結(jié)構(gòu),所以這類模型可以學(xué)習(xí)到代碼的結(jié)構(gòu)信息,生成的注釋質(zhì)量也比基于代碼token序列的注釋生成模型要高。使用圖神經(jīng)網(wǎng)絡(luò)的注釋生成模型CodeGNN利用圖結(jié)構(gòu)表征代碼的AST。由于圖更適合表示代碼的結(jié)構(gòu)信息,所以CodeGNN與基于AST序列的模型相比,BLEU、METEOR和ROUGE-L的得分更高。Transformer能捕獲長距離依賴關(guān)系,因此使用Transformer的注釋生成模型3種指標(biāo)分?jǐn)?shù)要高于Code-NN模型。本文模型利用Transformer和圖神經(jīng)網(wǎng)絡(luò)的優(yōu)點(diǎn),融合抽象語法樹和數(shù)據(jù)流圖2種特征來表示代碼,能更全面地覆蓋代碼所包含的語義和結(jié)構(gòu)等信息。模型生成的注釋的BLEU、METEOR和ROUGE-L分?jǐn)?shù)均高于對(duì)比模型。
4.6.2 消融實(shí)驗(yàn)
為了進(jìn)一步分析抽象語法樹編碼器和數(shù)據(jù)流圖編碼器的作用,以及圖神經(jīng)網(wǎng)絡(luò)中聚合節(jié)點(diǎn)鄰居階數(shù)和特征融合方式對(duì)模型性能的影響,本文設(shè)計(jì)了消融實(shí)驗(yàn)。在Java和Python數(shù)據(jù)集上的消融實(shí)驗(yàn)結(jié)果如表2所示,加粗表示最優(yōu)的結(jié)果。AST only表示只有抽象語法樹編碼器,DFG only表示只有數(shù)據(jù)流圖編碼器。其中,K表示聚合節(jié)點(diǎn)鄰居階數(shù),concat表示在特征融合時(shí)使用拼接操作,CM attention表示在特征融合時(shí)使用跨模態(tài)注意力機(jī)制。
Table 2 Results of ablation experiments on Java and Python datasets
由表2中結(jié)果可知,圖神經(jīng)網(wǎng)絡(luò)聚合數(shù)據(jù)流圖節(jié)點(diǎn)鄰居階數(shù)會(huì)影響模型性能。在只有數(shù)據(jù)流圖編碼器的實(shí)驗(yàn)中,當(dāng)K=2時(shí),模型在Java和Python數(shù)據(jù)集上BLEU-4、METEOR和ROUGE-L 3種評(píng)估指標(biāo)分?jǐn)?shù)最高,增加聚合節(jié)點(diǎn)鄰居階數(shù)會(huì)出現(xiàn)過平滑問題,即經(jīng)過多次鄰居節(jié)點(diǎn)特征的聚合,所有節(jié)點(diǎn)的特征會(huì)變得相似,模型不易學(xué)習(xí)到節(jié)點(diǎn)的特征,從而導(dǎo)致模型性能下降。在特征融合時(shí),不同的融合方式也會(huì)影響模型性能,從表2中數(shù)據(jù)可知,使用跨模態(tài)注意力機(jī)制的模型在Java和Python數(shù)據(jù)集上BLEU-4、METEOR和ROUGE-L 3種評(píng)估指標(biāo)分?jǐn)?shù)都要高于使用拼接操作融合2種特征的模型,驗(yàn)證了跨模態(tài)注意力機(jī)制的有效性。另外,只使用抽象語法樹編碼器或者數(shù)據(jù)流圖編碼器會(huì)降低注釋生成模型的性能。抽象語法樹和數(shù)據(jù)流圖都是代碼的結(jié)構(gòu)化表示形式,將2種特征融合可以幫助模型更全面地理解代碼的結(jié)構(gòu)和行為。具體來說,AST中含有代碼的語法結(jié)構(gòu)信息,而DFG可以描述代碼中的數(shù)據(jù)流和計(jì)算依賴關(guān)系,其中包含變量的定義、使用以及傳遞過程。使用跨模態(tài)注意力機(jī)制融合AST和DFG 2種特征的注釋生成模型在Java數(shù)據(jù)集上BLEU-4、METEOR和ROUGE-L 3種指標(biāo)得分分別為20.36%,15.79%和36.73%,在Python數(shù)據(jù)集上3種指標(biāo)得分分別為22.49%,14.96%和32.58%。
消融實(shí)驗(yàn)結(jié)果表明,融合代碼的抽象語法樹和數(shù)據(jù)流圖2種特征可以提升模型生成注釋的質(zhì)量。
4.6.3 案例展示
本節(jié)主要展示模型生成注釋的案例。從數(shù)據(jù)集中隨機(jī)抽取2段Java和Python代碼,其參考注釋和模型生成的注釋如表3所示。從表3中可以看出,模型生成的注釋可以準(zhǔn)確描述代碼功能,且具有良好的可讀性。
Table 3 Cases of code summarization
本文提出了一種融合多結(jié)構(gòu)信息的代碼注釋生成模型,模型在代碼抽象語法樹的基礎(chǔ)上,增加了數(shù)據(jù)流圖結(jié)構(gòu)信息來表示代碼。模型使用Transformer編碼器對(duì)AST序列進(jìn)行編碼,捕獲代碼全局信息。使用圖神經(jīng)網(wǎng)絡(luò)對(duì)數(shù)據(jù)流圖進(jìn)行特征提取,提供變量之間的計(jì)算依賴關(guān)系等信息,然后使用跨模態(tài)注意力機(jī)制融合抽象語法樹和數(shù)據(jù)流2種特征,最后經(jīng)過Transformer解碼器生成相應(yīng)的注釋。對(duì)比實(shí)驗(yàn)結(jié)果表明,本文模型的性能要優(yōu)于6種主流注釋生成模型。消融實(shí)驗(yàn)也驗(yàn)證了融合抽象語法樹和數(shù)據(jù)流2種特征的有效性。在未來工作中,一是需要設(shè)計(jì)更適合抽取代碼結(jié)構(gòu)信息的模型,提高模型學(xué)習(xí)能力。二是需要探究多種方法融合的注釋生成算法。三是提升模型的泛化能力,可以將注釋生成模型應(yīng)用到不同的代碼語言中。