張 欽,鄭 尚,鄒海濤,于化龍,高 尚
(江蘇科技大學(xué) 計(jì)算機(jī)學(xué)院,江蘇 鎮(zhèn)江 212100)
代碼補(bǔ)全已成為集成開發(fā)環(huán)境的關(guān)鍵功能之一,其主要基于開發(fā)人員的輸入和已有程序代碼,實(shí)時(shí)預(yù)測待補(bǔ)全代碼,并為開發(fā)人員提供建議列表,有效地提高了軟件項(xiàng)目的開發(fā)效率.研究表明,在軟件開發(fā)過程中,開發(fā)人員每分鐘都會(huì)使用一次集成環(huán)境的代碼補(bǔ)全插件[1].
近年來,隨著軟件代碼和數(shù)據(jù)規(guī)模不斷擴(kuò)大,智能代碼補(bǔ)全技術(shù)已成為軟件工程領(lǐng)域的熱門研究方向之一.Hindle[2]等人首次將代碼看作自然語言,并且運(yùn)用了N-gram模型處理代碼補(bǔ)全問題.此后,許多研究人員利用N-gram模型研究代碼補(bǔ)全任務(wù)[2-4].然而,由于直接對代碼序列進(jìn)行建模無法生成語法正確的代碼,Liu[5]等人和Li[6]等人通過將目標(biāo)語言生成抽象語法樹(Abstract Syntax Tree,AST)緩解上述問題,Liu和Li等人的工作包含了代碼補(bǔ)全中的類型(type)及值(value)預(yù)測,其為智能代碼補(bǔ)全提供了非常重要的建議.雖然基于自然語言技術(shù)的代碼補(bǔ)全方法不斷改進(jìn)優(yōu)化性能,但是仍無法從根本上解決N-gram模型無法獲取長距離關(guān)系的問題,研究者們?nèi)孕栊碌姆椒ㄈソ鉀Q這個(gè)問題.
近年來,鑒于深度學(xué)習(xí)的成功,循環(huán)神經(jīng)網(wǎng)絡(luò)已經(jīng)被廣泛應(yīng)用于代碼補(bǔ)全,其將代碼表征為AST序列,并按照深度優(yōu)先遍歷順序?qū)⑵湔归_成節(jié)點(diǎn)序列,進(jìn)而構(gòu)建指針網(wǎng)絡(luò)、LSTM等模型捕獲長距離的依賴關(guān)系,最后根據(jù)給定代碼序列,模型通過計(jì)算推薦概率最高節(jié)點(diǎn)完成補(bǔ)全任務(wù).鑒于AST的每一個(gè)節(jié)點(diǎn)有兩種屬性,類別(type)和值(value),因此,多數(shù)基于AST的代碼補(bǔ)全模型是分別單獨(dú)對類別(type)補(bǔ)全和值(value)補(bǔ)全,且屬于單任務(wù)預(yù)測.鑒于此,Liu[7]等人構(gòu)建雙向LSTM獲取路徑信息,以此補(bǔ)充節(jié)點(diǎn)序列缺少的結(jié)構(gòu)信息,并提出一種多任務(wù)學(xué)習(xí)(Multi Tasks Learning,MTL)框架,Liu等人通過手動(dòng)的為兩個(gè)子任務(wù)設(shè)置權(quán)重參數(shù)平衡類別(type)和值(value)的預(yù)測,實(shí)驗(yàn)結(jié)果顯示了多任務(wù)框架的效果要優(yōu)于單獨(dú)訓(xùn)練兩個(gè)模型.
前人工作從多個(gè)角度對代碼補(bǔ)全展開研究并已經(jīng)取得了不錯(cuò)的效果,但是還存在一些問題,主要有如下幾個(gè)方面:
1)模型獲取代碼的上下文信息能力有待提高.
2)多任務(wù)學(xué)習(xí)框架中代碼補(bǔ)全任務(wù)平衡仍有待改進(jìn).
因此,為了緩解上述問題對代碼補(bǔ)全準(zhǔn)確率的影響,本文提出一種新的代碼補(bǔ)全方法.其中,通過借鑒與Liu[7]等人工作,本文利用雙向長短期記憶網(wǎng)絡(luò)增加程序的結(jié)構(gòu)信息,同時(shí)引入形變LSTM,即Mogrifier-LSTM[8],將其與注意力機(jī)制結(jié)合增強(qiáng)代碼上下文信息表示,并改進(jìn)Liu[7]等人的多任務(wù)學(xué)習(xí)框架,使模型在訓(xùn)練過程中能夠自動(dòng)調(diào)整權(quán)重參數(shù),保證代碼補(bǔ)全任同步執(zhí)行.最后,本文方法在預(yù)測時(shí)進(jìn)行了參數(shù)綁定(weight tying)[9]操作,其通過綁定輸出編碼矩陣(input embedding)和輸入編碼矩陣(output embedding),減少模型參數(shù).綜上所述,本文的主要貢獻(xiàn)如下:
1)首次采用Mogrifier-LSTM模型與注意力機(jī)制捕獲代碼中的長期上下文依賴.
2)提出一種新的多任務(wù)學(xué)習(xí)框架自動(dòng)平衡兩個(gè)子任務(wù)的權(quán)重.
3)輸出層使用參數(shù)綁定,減少了模型參數(shù).
本文方法在代碼補(bǔ)全的標(biāo)準(zhǔn)數(shù)據(jù)集上進(jìn)行實(shí)驗(yàn)驗(yàn)證,結(jié)果表明:與最先進(jìn)的模型相比,本文模型達(dá)到了最好的預(yù)測性能.
抽象語法樹(AST)是一種樹形結(jié)構(gòu)的數(shù)據(jù),其包含了源代碼的句法信息.圖1展示了一段Python示例代碼及其抽象語法樹.

圖1 抽象語法樹示例Fig.1 Example of abstract syntax tree
Gabor[8]等人指出,現(xiàn)有神經(jīng)網(wǎng)絡(luò)模型在處理自然語言時(shí)受制于泛化能力有限和樣本的復(fù)雜性.為了提升模型的泛化能力,Gabor等人對長短期記憶網(wǎng)絡(luò)做了改進(jìn).對于給定一個(gè)輸入序列{x1,x2,…,xt},傳統(tǒng)LSTM[10]的計(jì)算過程如下:
in=σ(xnWxi+hhi+bi)
(1)
fn=σ(xnWxf+hn-1Whf+bf)
(2)
on=σ(xnWxo+hn-1Who+bo)
(3)
(4)
(5)
hn=on⊙tanh(cn)
(6)
Wxi,Wxf,Wxo,Wxc,Whi,Whf,Who,Whc是參數(shù)矩陣;bi,bf,bo,bc為偏執(zhí)項(xiàng);xn是第n個(gè)時(shí)刻的輸入,hn-1是上一個(gè)時(shí)刻的隱藏狀態(tài).圖2表示了傳統(tǒng)LSTM的基本架構(gòu).

圖2 長短期記憶網(wǎng)絡(luò)Fig.2 Long-short term memory
鑒于傳統(tǒng)LSTM的輸入和狀態(tài)只在其內(nèi)部進(jìn)行交互,這可能會(huì)導(dǎo)致上下文信息的丟失.Mogrifier-LSTM[8]對傳統(tǒng)LSTM進(jìn)行了改進(jìn),通過進(jìn)行輸入x與隱藏狀態(tài)的交互,增強(qiáng)了模型的泛化能力,具體過程如圖3所示.

圖3 形變長短期記憶網(wǎng)絡(luò)Fig.3 Mogrifier-LSTM
當(dāng)x和h輸入到LSTM之前已經(jīng)進(jìn)行了多輪的交互計(jì)算,這個(gè)計(jì)算過程可通過公式(7)和公式(8)表示:
(7)
其中i為奇數(shù),并且i∈[1,…,r].
(8)
其中i為偶數(shù),并且i∈[1,…,r].
x-1為當(dāng)前時(shí)刻的輸入x,h-1為上一個(gè)時(shí)刻的隱藏狀態(tài)h,Qi和Ri是可學(xué)習(xí)的參數(shù)矩陣,r為超參數(shù),其代表了輸入x與隱藏狀態(tài)之間交互的次數(shù),⊙是哈達(dá)瑪積.經(jīng)前人工作驗(yàn)證,Mogrifier-LSTM比原始的LSTM效果要好.因此,本文將其首次引入代碼補(bǔ)全任務(wù)進(jìn)行上下文信息表示.
注意力機(jī)制[11]在一定程度上提升了神經(jīng)網(wǎng)絡(luò)處理長序列問題的能力,Li[6]等人將指針網(wǎng)絡(luò)和注意力機(jī)制結(jié)合在一起,取得了良好的效果.
鑒于此,本文考慮將注意力機(jī)制與Mogrifier-LSTM進(jìn)行結(jié)合,進(jìn)一步地提升神經(jīng)網(wǎng)絡(luò)捕獲長期上下文依賴的能力.
Press[9]等人通過研究神經(jīng)網(wǎng)絡(luò)語言模型的權(quán)重矩陣,建議綁定輸入嵌入和輸出嵌入,以此減小神經(jīng)翻譯模型的大小,實(shí)驗(yàn)結(jié)果表明在不損害其性能的情況下,模型大小為原始大小的一半,具體的過程如下所述.
當(dāng)詞表中的詞會(huì)被表示為一個(gè)向量v,這個(gè)向量會(huì)被映射到一個(gè)稠密的空間,得到向量v1.
v1=UTv
(9)
其中,UT被稱為輸入編碼矩陣.向量v1經(jīng)過一系列復(fù)雜的運(yùn)算得到向量v2,最終,向量v2會(huì)被映射為向量v3,向量v3就代表了詞表中的詞匯.
v3=Kv2
(10)
其中K被稱作輸出編碼矩陣,在大部分模型中,U和K是兩個(gè)不同的矩陣,參數(shù)綁定強(qiáng)制U=K.
鑒于參數(shù)綁定上述的優(yōu)點(diǎn),本文將其添加到模型輸出,減少所提模型的參數(shù)量.
多任務(wù)學(xué)習(xí)是一種跨任務(wù)進(jìn)行知識(shí)遷移的方法,其通過歸納偏置降低過擬合的風(fēng)險(xiǎn)[12].Liu[7]等人首次將多任務(wù)學(xué)習(xí)引入到代碼補(bǔ)全任務(wù),其通過手動(dòng)分別為type和value的預(yù)測設(shè)置權(quán)重參數(shù),實(shí)驗(yàn)結(jié)果表明多任務(wù)學(xué)習(xí)能夠提升代碼補(bǔ)全的準(zhǔn)確率,但其所提框架不能保證參數(shù)同步,即當(dāng)type預(yù)測的參數(shù)為最優(yōu)時(shí),value預(yù)測的參數(shù)并非最好的.本文受Liebel[13]等人工作的啟發(fā),改進(jìn)了Liu[7]等人所提多任務(wù)學(xué)習(xí)框架的損失函數(shù),自動(dòng)調(diào)整權(quán)重參數(shù),不僅提升了代碼補(bǔ)全任務(wù)的計(jì)算效率,同時(shí)提高了其準(zhǔn)確率.
本文方法的總體框架如圖4所示.主要包含數(shù)據(jù)預(yù)處理、模型構(gòu)建和模型測試3個(gè)工作.其中,數(shù)據(jù)預(yù)處理是將抽象語法樹轉(zhuǎn)換為節(jié)點(diǎn)和路徑序列,模型構(gòu)建主要是根據(jù)處理完的數(shù)據(jù),訓(xùn)練代碼補(bǔ)全模型.在模型驗(yàn)證階段,給定一系列抽象語法樹節(jié)點(diǎn),訓(xùn)練好的補(bǔ)全模型用于預(yù)測下一個(gè)節(jié)點(diǎn)的類型和值.本節(jié)后續(xù)內(nèi)容將分別對各工作進(jìn)行介紹.

圖4 方法總體框架Fig.4 Overall framework of method
數(shù)據(jù)處理過程如表1所示.在數(shù)據(jù)集預(yù)處理過程中,本文遵循Li等人[6]的方法,以圖1的數(shù)據(jù)為例,首先按照深度優(yōu)先遍歷將AST展開成序列,分別得到兩個(gè)由節(jié)點(diǎn)屬性組成的序列,即{Moudle,FunctionDef,…,decorator_list}和{EMPTY,add,…,EMPTY}兩個(gè)序列,其中“EMPTY”代表沒有值屬性的節(jié)點(diǎn),并分別為類別屬性和值屬性建立詞表.鑒于值屬性數(shù)量龐大,所以本文選擇k個(gè)出現(xiàn)次數(shù)最多的值屬性,k={1k,10k,50k},對于未包含的值屬性,使用標(biāo)識(shí)符“unk”表示,對于非葉節(jié)點(diǎn),使用“Empty”表示.其次,提取除根節(jié)點(diǎn)外節(jié)點(diǎn)到根節(jié)點(diǎn)的路徑,并根據(jù)類別屬性的詞表將路徑轉(zhuǎn)換為對應(yīng)的向量形式.重復(fù)上述過程獲取所有類別、值以及路徑的向量形式序列.

表1 數(shù)據(jù)處理步驟Table 1 Data processing steps
對于每個(gè)AST節(jié)點(diǎn)的序列,本文模型將基于前r-1個(gè)節(jié)點(diǎn)預(yù)測其第r個(gè)節(jié)點(diǎn)的類型或值.為了完成上述任務(wù),本文提出圖5所示的代碼補(bǔ)全模型,其主要包含context encoder、path encoder和output layer這3個(gè)部分,下文將逐一描述.

圖5 模型總體架構(gòu)Fig.5 Overall architecture of model
2.2.1 context encoder
context encoder是基于Mogrifier-LSTM和注意力的網(wǎng)絡(luò),本文首先利用word2vector將經(jīng)過數(shù)據(jù)處理后的類別序列{T1,T2,…,Tt}、值序列{V1,V2,…,Vt}分別生成向量序列A、B,并對A、B中的每一個(gè)向量做向量連接,生成向量序列X.然后,本文將序列X{x1,x2,…,xt}輸入Mogrifier-LSTM網(wǎng)絡(luò)中增強(qiáng)代碼上下文信息表示.根據(jù)Mogrifier-LSTM當(dāng)前輸入xi和上一個(gè)時(shí)刻的隱藏狀態(tài)hi-1以及設(shè)置的交互次數(shù)r,進(jìn)而計(jì)算得到當(dāng)前時(shí)刻的隱藏狀態(tài)hi.
A=UtypeT
(11)
B=UvalueV
(12)
X=[A;B]
(13)
hi=MogrifierLSTM(xi,hi-1,r)
(14)
其中Utype為類別輸入編碼矩陣,Uvalue值輸入編碼矩陣,“;”代表向量連接運(yùn)算符.
其次,對于每一個(gè)時(shí)間步i,記錄下前l(fā)個(gè)時(shí)間步的隱藏狀態(tài)Mi=[hi-l,…,hi-1],根據(jù)當(dāng)前隱藏狀態(tài)hi與前l(fā)個(gè)時(shí)間步的隱藏狀態(tài)計(jì)算注意力.
(15)
αi=softmax(atti)
(16)
(17)
其中,Sm,Sh為可訓(xùn)練的參數(shù),softmax為歸一化函數(shù).c為模型抓取的上下文信息向量.
2.2.2 path encoder
path encoder是由雙向長短期記憶網(wǎng)絡(luò)組成,其目的在于利用代碼的結(jié)構(gòu)信息.本文首先將經(jīng)過數(shù)據(jù)處理后的序列{Path1,Path2,…,Patht},然后利用word2vector模型生成向量序列P,并將序列{p1,…,pt}輸入雙向長短期記憶網(wǎng)絡(luò)中,其計(jì)算過程如下.
P=Utypepath
(18)
(19)
(20)
(21)
2.2.3 output layer
本文將context encoder和path encoder的輸出hi,ci,Pi輸入output layer,得到預(yù)測的類別(type)和值(value).
βi=[ci,hi,Pi]
(22)
(23)
typehat=Ktypeβi
(24)
valuehat=Kvalue[βi;typehat]
(25)
其中Ktype為類別輸出編碼矩陣,Kvalue為值輸出編碼矩陣.為了減少模型參數(shù),本層使用參數(shù)綁定強(qiáng)制使類別輸入編碼矩陣等于類別輸出編碼矩陣.
2.2.4 損失函數(shù)
Liu[7]等人使用的多任務(wù)學(xué)習(xí)的損失函數(shù)如下:
(26)
其中N是子任務(wù)的數(shù)量,ck是子任務(wù)的權(quán)重參數(shù),但ck需要人工設(shè)置,不利于計(jì)算效率.受Liebel[13]等人研究工作的啟發(fā),本文將其優(yōu)化的損失函數(shù)引入代碼補(bǔ)全多任務(wù)中,使模型在訓(xùn)練過程中能夠自動(dòng)的優(yōu)化子任務(wù)的權(quán)重參數(shù),優(yōu)化后的損失函數(shù)如下:
(27)
如表2所示,本文選擇前人工作[6,7]所用的Python(PY)和JavaScript(JS)數(shù)據(jù)集,其中每個(gè)數(shù)據(jù)集包含150000個(gè)程序文件和相應(yīng)的AST,實(shí)驗(yàn)選擇了10000程序文件作為訓(xùn)練集,50000個(gè)程序文件作為測試集.

表2 代碼補(bǔ)全數(shù)據(jù)集Table 2 Code completion datasets
根據(jù)2.1節(jié)數(shù)據(jù)預(yù)處理所述,本文根據(jù)k個(gè)出現(xiàn)最頻繁的值構(gòu)建詞表,其中k={1k,10k,50k},最終可得到6個(gè)數(shù)據(jù)集:JS1K,JS10K,JS50K,PY1K,PY10K,PY50K.
本文采用前人工作[6,7]提及的準(zhǔn)確率作為評價(jià)指標(biāo),其描述了正確預(yù)測的類別(type)或者值(value)占總類別(type)或值(value)的比例.
本文實(shí)驗(yàn)所采用的硬件配置為:CPU 11th Gen Intel(R)core(TM)i7-11700k @ 3.60GHz,內(nèi)存DIMM(64G),顯卡Nvidia GeForce RTX 3060;開發(fā)環(huán)境為:Pycharm.
本文將當(dāng)前最先進(jìn)的代碼補(bǔ)全方法作為對比方法,其描述如下.
·vanillaLSTM[5]:此方法將源碼表征為抽象語法樹,并將其輸入長短期記憶網(wǎng)絡(luò)中(Long-short Term Memory)進(jìn)行模型訓(xùn)練.
·ParentLSTM[6]:其對 vanillaLSTM進(jìn)行了提升,計(jì)算了每一個(gè)節(jié)點(diǎn)與父節(jié)點(diǎn)的注意力.
·PoniterMitureNet[6]:其在ParentLSTM的基礎(chǔ)上,計(jì)算了當(dāng)前隱藏狀態(tài)與先前時(shí)間步隱藏狀態(tài)的注意力.
·GRU[14]:采用GRU作為基本模型替代了長短期記憶網(wǎng)絡(luò)(Long-Short Term Memory,LSTM).
·Transformer[15]:此方法使用Transformer模型替代了長短期記憶網(wǎng)絡(luò)(Long-Short Term Memory,LSTM),并且采用雙向LSTM提取AST結(jié)構(gòu)信息.
·Transformer-XL[7]:Liu等人采用了Transoformer-XL[16]和雙向LSTM作為基本模型,并且結(jié)合了多任務(wù)學(xué)習(xí)框架,手動(dòng)設(shè)置兩個(gè)子任務(wù)的參數(shù).
上述Transformer-XL和本文方法屬于多任務(wù)學(xué)習(xí).對于其他方法,值預(yù)測和類型預(yù)測皆是獨(dú)立訓(xùn)練的.
為了公平比較,所有方法的參數(shù)保持一致,其中embedding_size,hidden_size,batch_size大小都為128,adam[17]作為優(yōu)化器,學(xué)習(xí)率為0.001,每一輪迭代后學(xué)習(xí)率乘以0.6.同時(shí),本文中Mogrifier-LSTM層數(shù)默認(rèn)值為2,交互次數(shù)為5.實(shí)驗(yàn)結(jié)果如表3和表4所示.

表3 不同方法在Python數(shù)據(jù)集上的準(zhǔn)確率結(jié)果Table 3 Accuracy results of different methods on the Python datasets

表4 不同方法在 JavaScript數(shù)據(jù)集上的準(zhǔn)確率結(jié)果Table 4 Accuracy results of different methods on the JavaScript datasets
由表3、表4的實(shí)驗(yàn)結(jié)果可知,本文方法的準(zhǔn)確率高于對比方法,且類別(type)預(yù)測較其它方法提高了8%~9%,值(value)預(yù)測較其它方法提高了4.8%~14%.綜上,與單任務(wù)方法相比,本文方法能夠充分利用抽象語法樹的結(jié)構(gòu)信息,更好地捕獲代碼中的上下文依賴關(guān)系;與Transformer-XL多任務(wù)學(xué)習(xí)方法相比,本文所提的多任務(wù)框架效果更優(yōu).
為了闡述本文模型性能較優(yōu)的原因,鑒于Liu等人[7]已討論其所提模型優(yōu)于現(xiàn)有單任務(wù)方法,本文則選擇transformer-xl作為基線方法進(jìn)行分析.圖6展示了兩種方法在訓(xùn)練集和測試集上的損失情況,Transformer-XL方法在測試集上的損失要遠(yuǎn)大于訓(xùn)練集,而本文模型在訓(xùn)練集和測試集上的損失差距情況要好于Transformer-XL方法,這表明基線模型存在過擬合的風(fēng)險(xiǎn).同時(shí),由圖6結(jié)果可知,本文模型在測試集上的每輪迭代的損失都小于基線模型,原因如下:

圖6 所提模型與基線模型在訓(xùn)練集和測試集上的交叉熵?fù)p失Fig.6 Cross-entropy loss on training and test datasets for the proposed model and baseline model
1)本文模型能夠更好地抓取代碼中的上下文信息.
2)本文多任務(wù)學(xué)習(xí)方法更有效地利用了type和value子任務(wù)之間的聯(lián)系.
為了評估提升的成本,本文計(jì)算了模型的參數(shù)量和模型訓(xùn)練所需的時(shí)間.由表5結(jié)果可知,本文模型訓(xùn)練時(shí)間多于其他方法,原因如下:

表5 模型參數(shù)量及訓(xùn)練時(shí)間Table 5 Model parameters and training time
1)本文模型基于Mogrifier-LSTM,需要按照時(shí)間步順序計(jì)算.
2)與單任務(wù)方法相比,多任務(wù)學(xué)習(xí)框架的參數(shù)較多,訓(xùn)練時(shí)間也就更多.
3)雖然本文模型的參數(shù)和時(shí)間高于Transformer-XL多任務(wù),但其所訓(xùn)練的模型并非最優(yōu)結(jié)果,原因在于Transformer-XL的多任務(wù)框架需要手動(dòng)調(diào)參,表5僅單純計(jì)算其模型訓(xùn)練時(shí)間,而尋找參數(shù)的時(shí)間分析可見表9.
此外,本文衡量了各模型每一次補(bǔ)全的計(jì)算成本,結(jié)果如表6所示.同樣地,本文所提方法每次補(bǔ)全所需時(shí)間略高于其他方法,原因如下:

表6 一次補(bǔ)全所需時(shí)間Table 6 Time required for one-time completion
1)本文采用Mogrifier-LSTM作為基本模型,無法并行計(jì)算,并且在計(jì)算時(shí)需要與隱藏狀態(tài)進(jìn)行交互.
2)使用了多任務(wù)學(xué)習(xí)框架,同時(shí)對type和value進(jìn)行補(bǔ)全,在計(jì)算上要比單任務(wù)框架花費(fèi)更多時(shí)間.
然而,由表3和表4的實(shí)驗(yàn)結(jié)果可知,本文所提模型有助于代碼補(bǔ)全準(zhǔn)確率的提高,且可以保證1秒內(nèi)做出預(yù)測,這使其能夠?qū)崟r(shí)地進(jìn)行代碼補(bǔ)全.
為了分析所提模型各個(gè)組件的作用,本文分別以JS10K和PY10K為例進(jìn)行實(shí)驗(yàn)分析,實(shí)驗(yàn)結(jié)果如表7所示.

表7 模型各部件的作用Table 7 Effectiveness of each component in the model
表7中-pe、-wt、-MTL依次代表模型分別去掉path encoder、參數(shù)綁定(weight tying)、多任務(wù)學(xué)習(xí)(Multi-Tasks Learning,MTL)組件,Full表示本文完整的模型.
表7中第1行是本文模型去掉path encoder的準(zhǔn)確率,其較完整模型類別預(yù)測低了4.5%(PY10K),5.5%(JS10K),且值預(yù)測同時(shí)也低了6%(PY10K),5.9%(JS10K),這表明了代碼結(jié)構(gòu)信息的重要性.
表7中第2行是去掉參數(shù)綁定的準(zhǔn)確率,其較完整模型類別預(yù)測低了1%(PY10K),4.1%(JS10K),且值預(yù)測低了2.6%(PY10K),3.9%(JS10K).同時(shí),本文給出了使用參數(shù)綁定前后的參數(shù)數(shù)量.如表8所示,模型參數(shù)在兩個(gè)數(shù)據(jù)集上分別減少1%和3%,這將有助于計(jì)算資源有限的情況.

表8 模型參數(shù)量Table 8 Parameters of the model
表7中第3行為去掉多任務(wù)學(xué)習(xí)準(zhǔn)確率,其中單獨(dú)訓(xùn)練預(yù)測類別(type)的模型時(shí),PY10K上的準(zhǔn)確率達(dá)到了79.58%,較完整模型有0.3%的提升,但值(value)預(yù)測的準(zhǔn)確率較完整模型低了2.4%.然而,多任務(wù)學(xué)習(xí)能夠同時(shí)完成代碼補(bǔ)全類別和值的預(yù)測,其更適用于實(shí)際應(yīng)用.
綜上所述,無論移除本文模型中的任一組件,代碼補(bǔ)全準(zhǔn)確率整體均有下降,這充分地證明了本文模型中各部件的重要性和必要性.
最后,由于Liu等人在訓(xùn)練時(shí)也使用了多任務(wù)學(xué)習(xí),為了進(jìn)一步驗(yàn)證本文多任務(wù)學(xué)習(xí)框架的優(yōu)勢,本文保證其他組件不變,選擇Liu等人提出的多任務(wù)學(xué)習(xí)框架替代本文的多任務(wù)學(xué)習(xí)框架,并進(jìn)行了實(shí)驗(yàn),實(shí)驗(yàn)結(jié)果如表9所示.

表9 兩種多任務(wù)學(xué)習(xí)對比Table 9 Comparison of two kinds of multi tasks learning
從表9的結(jié)果看出,本文基于Liu等人的多任務(wù)框架下類別和值的最好結(jié)果并不是同一組參數(shù)訓(xùn)練得到,且準(zhǔn)確率與本文所提多任務(wù)框架相比,PY10K的類別(type)預(yù)測的準(zhǔn)確率低了0.2%、值(value)預(yù)測的準(zhǔn)確率提了0.3%;而JS10K的類別(type)預(yù)測低了0.92%、值(value)預(yù)測的準(zhǔn)確率低了2.79%.同時(shí),實(shí)驗(yàn)中基于Liu等人的多任務(wù)框架訓(xùn)練耗時(shí)11h,而基于本文所用多任務(wù)框架訓(xùn)練耗時(shí)3.5h.
綜上所述,各個(gè)組件均有助于本文模型的提高代碼補(bǔ)全多任務(wù)的準(zhǔn)確率,同時(shí)有效地降低了多任務(wù)學(xué)習(xí)的總體時(shí)間.
前人工作已在代碼補(bǔ)全任務(wù)取得了很大的突破,但其對代碼上下文表示和多任務(wù)學(xué)習(xí)中子任務(wù)平衡處理仍需改進(jìn),本文提出了一種融合注意力機(jī)制的形變LSTM智能代碼補(bǔ)全方法,此方法利用雙向長短期記憶網(wǎng)絡(luò)學(xué)習(xí)抽象語法樹的代碼結(jié)構(gòu)信息,同時(shí)結(jié)合Mogrifier-LSTM與注意力機(jī)制提升模型對代碼上下文的表示能力,并設(shè)計(jì)一種新的多任務(wù)學(xué)習(xí)框架自動(dòng)尋找最優(yōu)參數(shù).最后,本文在輸出層使用了參數(shù)綁定,降低了模型規(guī)模.實(shí)驗(yàn)結(jié)果顯示,本文方法在Python和JavaScript數(shù)據(jù)集上的性能優(yōu)于當(dāng)前的最先進(jìn)方法.
在未來工作中,本文將進(jìn)一步優(yōu)化所提模型,研究圖神經(jīng)網(wǎng)絡(luò)在代碼補(bǔ)全中的應(yīng)用,并在更多的真實(shí)數(shù)據(jù)集上進(jìn)行驗(yàn)證,以及考慮利用遷移學(xué)習(xí)技術(shù)解決小樣本代碼補(bǔ)全問題.