在軟件開發(fā)過程中,經(jīng)常需要進行代碼搜索。然而,現(xiàn)有的代碼搜索方法大都將代碼視作文本,依賴源代碼和自然語言查詢的文本相似性。由于缺乏對查詢和源代碼的語義的理解,在某些場景下,無法返回期望的結(jié)果。
例如,下面這段代碼讀取xml文檔:
publicstatic < S > S deserialize(Class c, File xml) {
try {
JAXBContext context = JAXBContext.newInstance(c);
Unmarshaller unmarshaller = context.createUnmarshaller();
S deserialized = (S) unmarshaller.unmarshal(xml);
return deserialized;
} catch (JAXBException ex) {
log.error("Error-deserializing-object-from-XML", ex);
returnnull;
}
}
然而,由于代碼中并不包含“讀取”(read)一詞,因此現(xiàn)存的方法可能無法成功返回這一代碼片段。
有鑒于此,HKUST和微軟研究院的研究人員顧小東、Hongyu Zhang、Sunghun Kim最近發(fā)表論文,使用深度神經(jīng)網(wǎng)絡(luò),學(xué)習(xí)源代碼和自然語言查詢的統(tǒng)一向量表示,以支持代碼語義搜索。
CODEnn
研究人員將其新提出的深度神經(jīng)網(wǎng)絡(luò)模型命名為CODEnn(Code-Description Embedding Neural Network,代碼-描述嵌入神經(jīng)網(wǎng)絡(luò))。CODEnn的主要思路是將代碼片段和自然語言查詢聯(lián)合嵌入一個統(tǒng)一的向量空間,使查詢嵌入和相應(yīng)的代碼片段嵌入為相近的向量(可以通過向量相似度匹配)。
聯(lián)合嵌入
首先讓我們簡單溫習(xí)一下聯(lián)合嵌入的概念。
聯(lián)合嵌入(joint embedding),又稱多模態(tài)嵌入(multi-modal embedding),可以將異構(gòu)數(shù)據(jù)嵌入統(tǒng)一的向量空間,使得模態(tài)不同而語義相似的概念在空間中占據(jù)相近區(qū)域。形式化地表述為:
其中,φ、ψ為嵌入函數(shù),J衡量相似度。
在CODEnn中,φ為源代碼嵌入網(wǎng)絡(luò)(CoNN),ψ為自然語言描述嵌入網(wǎng)絡(luò)(DeNN),J為余弦相似度。
具體架構(gòu)
具體而言,CODEnn的嵌入網(wǎng)絡(luò)主要使用了循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)和最大池化,架構(gòu)如下:
從上圖我們可以看到,正如我們之前提到的那樣,網(wǎng)絡(luò)架構(gòu)分為三個模塊。下面我們將從上往下,從右向左地依次說明這三個模塊:
相似度模塊
DeNN
CoNN
相似度模塊
這是最簡單的模塊,將代碼和相應(yīng)描述轉(zhuǎn)換為向量后,通過這一模塊衡量兩者的相似度。具體而言,使用的是余弦相似度:
DeNN
DeNN將自然語言描述嵌入為向量。DeNN使用循環(huán)神經(jīng)網(wǎng)絡(luò)(tanh激活)和最大池化完成嵌入:
CoNN
由于代碼不是簡單的純文本,包含多種結(jié)構(gòu)性信息。因此,CoNN的架構(gòu)要比DeNN復(fù)雜。
CoNN考慮代碼的三個方面:
方法名
API調(diào)用序列
代碼中包含的token
從每個代碼片段中提取以上三方面的信息后,分別嵌入,然后融合成單個向量表示。
上式中,c為整個代碼片段的向量表示,m、a、t分別為方法名、API調(diào)用序列、token的嵌入向量表示。
方法名的嵌入和DeNN類似,同樣使用循環(huán)神經(jīng)網(wǎng)絡(luò)(tanh激活)和最大池化:
API調(diào)用序列的嵌入同理:
token的嵌入有所不同。因為并不在意token的順序,也就是說,不把token作為序列數(shù)據(jù),所以就不使用循環(huán)神經(jīng)網(wǎng)絡(luò)了。使用的是多層感知器(MLP),也就是普通的全連接層。不過仍然搭配了tanh激活和最大池化:
模型訓(xùn)練
CODEnn接受代碼、描述作為輸入,預(yù)測其嵌入表示的余弦相似度。具體而言,每個訓(xùn)練樣本為一個三元組(C, D+, D-),其中C為代碼片段,D+為正面樣本(C的正確描述),D-為負(fù)面樣本(隨機選取的不正確描述)。訓(xùn)練時,CODEnn預(yù)測(C, D+)和(C, D-)的余弦相似度,并最小化以下?lián)p失:
上式中,θ為模型參數(shù),P為訓(xùn)練數(shù)據(jù)集,c、d+、d-為C、D+、D-的嵌入向量,ε為邊緣常數(shù),在研究人員的試驗中,ε的值定為0.05. 從直覺上說,最小化以上損失,將鼓勵代碼片段和正確描述的余弦相似度提高,代碼片段和錯誤描述的余弦相似度下降。
下面是一些實現(xiàn)的細(xì)節(jié):
循環(huán)神經(jīng)網(wǎng)絡(luò)選用的是雙向LSTM,每個雙向LSTM在每個方向上有200個隱藏單元。
詞嵌入維度為100.
嵌入token的MLP有100個隱藏單元。
融合代碼片段不同方面的MLP有400個隱藏單元。
優(yōu)化算法為mini-batch Adam,batch大小為128.
詞匯量限制為10000(10000個訓(xùn)練集中最常用的單詞)。
模型基于Keras構(gòu)建。
在單塊Nvidia K40 GPU上,訓(xùn)練耗時約50小時(500個epoch)。
收集訓(xùn)練語料
CODEnn模型需要大規(guī)模的訓(xùn)練語料,語料包括代碼元素和相應(yīng)的描述,即(方法名, API調(diào)用序列, token, 描述)元組。
研究人員利用GitHub上的開源項目準(zhǔn)備語料:
下載了GitHub上所有創(chuàng)建于2008年8月至2016年6月的Java項目。
排除所有未加星的項目,以移除玩具項目和試驗性項目。
選取帶有文檔注釋的Java方法(Java中的文檔注釋以/**開始,以*/收尾)。
最終收集到了18233872個Java方法。
Java方法名的提取很簡單,根據(jù)駝峰原則解析即可,例如,listFiles將被解析為list和files。
API調(diào)用序列的提取要復(fù)雜一點。研究人員使用Eclipse JDT編譯器解析了AST,并根據(jù)如下規(guī)則生成API調(diào)用序列:
new C()->C.new
o.m()->C.m(o為類C的實例)
方法調(diào)用作為參數(shù)傳入時,傳入的方法調(diào)用在前:o1.m1(o2.m2(), o3.m3())->C2.m2-C3.m3-C1.m1
提取語句序列s1;s2;...;sN中每個語句si的方法調(diào)用序列ai,并連接:a1-a2-...-aN
條件語句的調(diào)用序列包括所有分支:if (s1) {s2;} else {s3}->a1-a2-a3
循環(huán)語句:while (s1) {s2;}->a1-a2
token提取,同樣根據(jù)駝峰原則解析方法主體,并移除重復(fù)token。同時也移除了一些停止詞(例如the、in)和Java關(guān)鍵字,因為這些詞在源代碼中頻繁出現(xiàn),區(qū)分性不好。
描述提取,也用到了Eclipse JDT編譯器,從AST提取JavaDoc注釋。根據(jù)Javadoc指導(dǎo)原則,JavaDoc注釋的第一句話通常是方法的概述,因此研究人員將JavaDoc注釋的第一句話作為描述。
一個提取的例子
DeepCS
研究人員基于CODEnn模型創(chuàng)建了一個代碼搜索工具DeepCS。給定自然語言查詢,DeepCS會建議最相關(guān)的K個代碼片段。DeepCS系統(tǒng)包含三個主要階段:
離線訓(xùn)練
離線代碼嵌入
在線代碼搜索
DeepCS事先將代碼庫中的所有代碼片段嵌入為向量(使用訓(xùn)練好的CODEnn模型的CoNN模塊)。在線搜索時,當(dāng)開發(fā)者輸入自然語言查詢時,DeepCS首先使用訓(xùn)練好的CODEnn模型的DeNN模塊將查詢嵌入為向量,然后估計查詢向量和所有代碼向量的余弦相似度,并返回相似度最高的K個(比如,10個)代碼片段作為搜索結(jié)果。
試驗
試驗設(shè)置
為了更好地評估模型的表現(xiàn),研究人員使用了不同于訓(xùn)練語料的獨立代碼庫。研究人員選取了GitHub上至少有20星的Java項目。和訓(xùn)練語料不同,測試數(shù)據(jù)集包含所有代碼(包括那些沒有Javadoc注釋的代碼)??偣彩占?950個項目,從中得到了16262602個方法。
研究人員從Stack Overflow問答網(wǎng)站中選取了得票最高的Java編程問題,并手工檢查了這些問題,確保其符合標(biāo)準(zhǔn):
這個問題關(guān)于一項具體的Java編程任務(wù)。研究人員剔除了描述含糊抽象的問題,比如“加載JNI庫失敗”,“StringBuilder和StringBuffer的區(qū)別是什么?”,“為什么Java有transient域?”
接受的答案包含Java代碼片段。
不與之前的問題重復(fù)。
評估指標(biāo)
兩個開發(fā)者獨立地查看搜索結(jié)果,并標(biāo)注其相關(guān)性。接著互相討論不一致的標(biāo)簽,并重新標(biāo)注。重復(fù)這一過程,直到達成共識。
研究人員使用了4個常用的指標(biāo)衡量代碼搜索的有效性。其中2個指標(biāo)衡量單次代碼搜索查詢的有效性:
FRank首個命中結(jié)果在結(jié)果列表中的位置。由于用戶從上往下查看結(jié)果,因此較小的FRank值意味著找到所需結(jié)果需要花費的精力較少。
Precision at k衡量k個返回結(jié)果中相關(guān)結(jié)果所占的比例。
Precision at k很重要,因為開發(fā)者經(jīng)常會查看多個結(jié)果,良好的帶嗎搜索引擎應(yīng)該避免給開發(fā)者過多的噪聲。Precision at k越高,代碼搜索的表現(xiàn)就越好。研究人員評估了k值為1、5、10時的Precision at k.
另外兩個指標(biāo)衡量一組查詢的表現(xiàn):
SuccessRate at k衡量在前k個結(jié)果中命中結(jié)果的比例。
其中,Q為查詢集合,δ函數(shù)在輸入為真時返回1,否則返回0. SuccessRate at k越高,代碼搜索的總體表現(xiàn)就越好。和Precision at k一樣,研究人員評估了k值為1、5、10時的SuccessRate at k.
MRR是一組查詢中FRank倒數(shù)的平均數(shù)。MRR越高,代碼搜索的總體表現(xiàn)就越好。
評測對比
研究人員對比了CodeHow(當(dāng)前最先進的代碼搜索引擎)和Lucene(許多代碼搜索工具使用的流行文本搜索引擎)的表現(xiàn):
上表中,NF表示未找到,LC表示Lucene,CH表示CodeHow,DCS表示DeepCS。
從上表我們可以看到,一般來說,相比Lucene和CodeHow,DeepCS能返回更相關(guān)的結(jié)果。統(tǒng)計數(shù)據(jù)也證實了這一點。
例子
為了演示DeepCS的優(yōu)勢,研究人員提供了一些具體的例子。
上面的兩個查詢中,第一個queue是動詞(加入隊列),第二個queue是名詞(隊列)。普通的文本搜索引擎很難區(qū)分兩者,而DeepCS成功理解了兩者的不同。
上面這個例子展示了DeepCS的魯棒性。CodeHow返回了很多與查詢中不太重要的單詞(比如specified和character)相關(guān)的結(jié)果,而DeepCS可以成功識別不同關(guān)鍵詞的重要性,理解查詢的關(guān)鍵點。
這個例子展示了DeepCS能夠理解查詢的語義。盡管代碼片段中不包含查詢中的關(guān)鍵詞“read”(讀取)和“song”(歌曲),DeepCS仍然找到了語義相關(guān)的結(jié)果,“deserialize”(反序列化)和“voice”(聲音)。
當(dāng)然,DeepCS有時可能會返回不夠精確的結(jié)果。
上圖中的查詢語句為“生成md5”,精確結(jié)果在返回結(jié)果列表中排在第7,而部分相關(guān)的結(jié)果(生成校驗值)卻排在結(jié)果列表的前面。研究人員打算以后在模型中加入更多代碼特征(例如上下文環(huán)境),以進一步提升表現(xiàn)。
-
神經(jīng)網(wǎng)絡(luò)
+關(guān)注
關(guān)注
42文章
4785瀏覽量
101275 -
源代碼
+關(guān)注
關(guān)注
96文章
2947瀏覽量
67013 -
自然語言
+關(guān)注
關(guān)注
1文章
291瀏覽量
13410
原文標(biāo)題:ICSE 2018:港科大、微軟研究院提出深度學(xué)習(xí)代碼搜索模型
文章出處:【微信號:jqr_AI,微信公眾號:論智】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
從AlexNet到MobileNet,帶你入門深度神經(jīng)網(wǎng)絡(luò)
深度神經(jīng)網(wǎng)絡(luò)是什么
如何構(gòu)建神經(jīng)網(wǎng)絡(luò)?
基于深度神經(jīng)網(wǎng)絡(luò)的激光雷達物體識別系統(tǒng)
卷積神經(jīng)網(wǎng)絡(luò)模型發(fā)展及應(yīng)用
深度神經(jīng)決策樹:深度神經(jīng)網(wǎng)絡(luò)和樹模型結(jié)合的新模型
深度神經(jīng)網(wǎng)絡(luò)模型的壓縮和優(yōu)化綜述
![<b class='flag-5'>深度</b><b class='flag-5'>神經(jīng)網(wǎng)絡(luò)</b><b class='flag-5'>模型</b>的壓縮和優(yōu)化綜述](https://file.elecfans.com/web1/M00/EA/7D/pIYBAGBzsJGARy7KAAG3pofuQI4613.png)
評論