汶東震,張 帆,劉海峰,楊 亮,徐 博,林 原,林鴻飛
大連理工大學(xué),遼寧 大連 116024
開(kāi)發(fā)人員在面對(duì)日常工作任務(wù)時(shí)會(huì)進(jìn)行大量搜索行為,從公共資源庫(kù)(包含開(kāi)源社區(qū)、論壇博客等)或私有資源庫(kù)(內(nèi)部軟件倉(cāng)庫(kù)、源代碼平臺(tái)、社區(qū)等)搜索可復(fù)用的代碼片段、特定問(wèn)題的解決方案、算法設(shè)計(jì)、軟件文檔以及軟件工具等內(nèi)容,以充分利用已有的軟件開(kāi)發(fā)資源和經(jīng)驗(yàn),在提高軟件復(fù)用性的同時(shí),降低開(kāi)發(fā)成本并提升開(kāi)發(fā)效率。Singer等人[1]于1997年針對(duì)軟件開(kāi)發(fā)者行為進(jìn)行跟蹤調(diào)研,相關(guān)研究結(jié)果表明代碼搜索(code search)已成為軟件開(kāi)發(fā)活動(dòng)中最為常見(jiàn)活動(dòng)。
而Sadowski等人[2]研究表明,開(kāi)發(fā)者平均每個(gè)工作日會(huì)構(gòu)造12條查詢語(yǔ)句對(duì)遇到的問(wèn)題進(jìn)行搜索??梢钥吹?,代碼搜索在軟件開(kāi)發(fā)活動(dòng)中重要性日益提高。
Liu等人[3]針對(duì)代碼搜索工具相關(guān)工作進(jìn)行了文獻(xiàn)總結(jié)。作者從代碼倉(cāng)庫(kù)組織、查詢文本、檢索模型以及評(píng)價(jià)方法角度,針對(duì)代碼搜索工具建立分類體系進(jìn)行歸類。
代碼搜索從搜索形式可分為,基于自然語(yǔ)言查詢的代碼搜索、基于測(cè)試用例的代碼搜索[4]、面向缺陷檢測(cè)的代碼搜索、代碼克隆檢測(cè)、應(yīng)用程序接口搜索等[5]。其共同點(diǎn)在于從用戶需求出發(fā),結(jié)合信息檢索、程序理解以及機(jī)器學(xué)習(xí)等技術(shù)對(duì)符合用戶需求的代碼文件或片段進(jìn)行定位。
其中,基于自然語(yǔ)言查詢的代碼搜索更為貼近開(kāi)發(fā)者實(shí)際需求,是目前代碼搜索研究中的熱點(diǎn)。代碼搜索任務(wù)和傳統(tǒng)Ad-hoc任務(wù)類似,但代碼搜索任務(wù)還具有以下難點(diǎn):
(1)跨模態(tài)匹配問(wèn)題。代碼搜索任務(wù)中查詢和文檔分別處于不同模態(tài)。其中查詢主要以自然語(yǔ)言形式表達(dá),而目標(biāo)文檔則是程序語(yǔ)言語(yǔ)法約束的源代碼文本,在計(jì)算匹配時(shí)需要考慮跨模態(tài)語(yǔ)義鴻溝問(wèn)題。
(2)查詢意圖理解問(wèn)題。代碼搜索任務(wù)中查詢所表達(dá)的意圖較為多樣。其包括用戶開(kāi)發(fā)需求、實(shí)現(xiàn)特定技術(shù)路線的構(gòu)造性需求以及使用特定接口的API需求等,在構(gòu)建檢索模型對(duì)用戶查詢需求進(jìn)行理解時(shí)需要將軟件工程領(lǐng)域知識(shí)與語(yǔ)義理解模型結(jié)合。
(3)程序理解問(wèn)題。代碼搜索模型首先需要建立對(duì)檢索對(duì)象源代碼片段的理解。其包括代碼基礎(chǔ)語(yǔ)法語(yǔ)義、API功能信息、代碼結(jié)構(gòu)特征以及代碼功能特性等。其中標(biāo)識(shí)符和程序結(jié)構(gòu)是構(gòu)建程序理解的核心。
可以看到,當(dāng)前代碼搜索研究主要面臨的問(wèn)題是如何理解程序功能以及基于程序理解的查詢意圖匹配,即基于程序理解對(duì)自然語(yǔ)言和代碼片段進(jìn)行聯(lián)合建模。本文則從程序理解視角出發(fā),針對(duì)近期代碼搜索研究進(jìn)展進(jìn)行梳理。
程序理解是軟件工程中的關(guān)鍵活動(dòng),1968年召開(kāi)的北約軟件工程會(huì)議明確了程序理解在軟件工程中的重要性[6]。軟件工程師在進(jìn)行軟件重用、維護(hù)、遷移、逆向工程等任務(wù)時(shí)都依賴對(duì)于程序的理解[7]。
在協(xié)作開(kāi)發(fā)場(chǎng)景下,開(kāi)發(fā)者需要了解軟件架構(gòu)以及接口設(shè)計(jì)模式,進(jìn)而對(duì)軟件功能進(jìn)行開(kāi)發(fā)和實(shí)現(xiàn);而在軟件維護(hù)中,維護(hù)者需要了解已有項(xiàng)目中的主要功能和實(shí)現(xiàn)方法,以此為基礎(chǔ)才能進(jìn)一步進(jìn)行缺陷檢查以及修復(fù)?!袄斫狻北举|(zhì)上是通過(guò)學(xué)習(xí)的手段,建立從理解的對(duì)象(如文本、源代碼等)所屬的概念域,到理解的主體(人、模型)所熟悉的概念域的(概念)映射[6]。
程序理解的主體是整個(gè)軟件系統(tǒng)或者部分軟件系統(tǒng),旨在研究其如何運(yùn)行[8]。
程序理解任務(wù)包括構(gòu)建從代碼模型到應(yīng)用領(lǐng)域問(wèn)題各抽象層次上的模型[9];利用領(lǐng)域知識(shí)理解軟件,構(gòu)建軟件制品與使用場(chǎng)景之間的認(rèn)知模型[10];通過(guò)閱讀源代碼判斷其作用以及與其他構(gòu)件之間的關(guān)系等。其最終目的在于支撐軟件維護(hù)、演化和再工程。
按照實(shí)現(xiàn)方式分類,程序理解可分為基于分析和基于學(xué)習(xí)兩種主要方法?;诜治龅某绦蚶斫夥椒ㄊ忠蕾嚪治稣叩膫€(gè)人知識(shí)和經(jīng)驗(yàn),構(gòu)建程序理解模型等價(jià)于手動(dòng)構(gòu)造相關(guān)特征集。這類方法往往和具體軟件系統(tǒng)耦合,相關(guān)經(jīng)驗(yàn)規(guī)則較難遷移到其他項(xiàng)目中。同時(shí),隨著軟件規(guī)模的增大,分析所需資源會(huì)隨之加升高,效率會(huì)隨之降低。
互聯(lián)網(wǎng)上大量開(kāi)源代碼的出現(xiàn)為基于學(xué)習(xí)的程序理解方法提供了充分的數(shù)據(jù)保證[11]。而近期Hindle等人[12]和Allmanis等人[13]研究表明,程序源代碼具有和自然語(yǔ)言相似的特性,這種自然性(naturalness)為結(jié)合統(tǒng)計(jì)模型尤其是深度模型進(jìn)行源代碼分析理解提供了理論依據(jù)。Tu等人[14]針對(duì)源代碼局部性(localness)對(duì)統(tǒng)計(jì)建模的影響進(jìn)行了深入分析。Chen等人[15]則對(duì)深度源代碼建模中的進(jìn)展和挑戰(zhàn)進(jìn)行了詳細(xì)梳理。
基于深度學(xué)習(xí)的程序理解框架如圖1所示。其主要包含兩個(gè)階段,首先根據(jù)任務(wù)不同構(gòu)建源代碼文本的對(duì)應(yīng)表示形式,在此基礎(chǔ)上通過(guò)深度模型構(gòu)建源代碼特征向量并應(yīng)用于具體任務(wù)中。
圖1 基于深度神經(jīng)網(wǎng)絡(luò)的代碼理解框架Fig.1 Framework of source code comprehension on basis of deep neural network model
具體而言,程序源代碼首先會(huì)根據(jù)任務(wù)被轉(zhuǎn)換為字符序列(char sequence)、詞序列(token sequence)、API序列(API sequence)、抽象語(yǔ)法樹(shù)(abstract syntax tree,AST)、函數(shù)調(diào)用圖(function call graph,F(xiàn)CP)以及控制流圖(control flow graph)等多種形式。
在此基礎(chǔ)上,源代碼不同表示通過(guò)神經(jīng)網(wǎng)絡(luò)轉(zhuǎn)換為特征向量后被用于具體任務(wù)。
源代碼不同表示形式特點(diǎn)以及適用任務(wù)如表1所示?;谠~的表示[16]的程序建模和自然語(yǔ)言理解模型建模類似,實(shí)現(xiàn)簡(jiǎn)單易于遷移。但由于開(kāi)發(fā)者自定義標(biāo)識(shí)符情況的存在[17-18],基于詞的代碼建模方法往往會(huì)受到詞表外詞(out of vocabulary,OOV)問(wèn)題困擾。基于字符序列的建模能夠解決OOV問(wèn)題,但是基于字符符號(hào)的表示方式難以學(xué)習(xí)到詞義,因此在表示能力方面較弱。代碼中包含的API往往設(shè)計(jì)規(guī)范,同時(shí)用詞較為固定,因此針對(duì)API序列進(jìn)行學(xué)習(xí)在代碼搜索和摘要任務(wù)上都有著良好的效果[19]。
表1 代碼理解中間形式Table 1 Intermediate representation for source code comprehension
可以看到,單純使用詞序列作為源代碼的表示形式存在表示能力不足的問(wèn)題,因此結(jié)合多模態(tài)方法[20]建模源代碼逐漸走入研究者的視野?;谡Z(yǔ)法樹(shù)的代碼建模能夠改善序列建模中對(duì)于程序結(jié)構(gòu)學(xué)習(xí)不充分的問(wèn)題。但現(xiàn)有研究大多采用序列采樣的方式[21-22]從語(yǔ)法樹(shù)中獲取節(jié)點(diǎn)序列進(jìn)行表示,對(duì)于樹(shù)結(jié)構(gòu)的利用尚不充分。Wang等人[23]提出一種改進(jìn)方法用于將語(yǔ)法樹(shù)信息融合代碼表示方法,語(yǔ)法樹(shù)作為代碼序列的平行語(yǔ)料,在與源代碼序列對(duì)齊的基礎(chǔ)上與自然語(yǔ)言片段進(jìn)行建模,提高了源代碼搜索任務(wù)效果。
而圖神經(jīng)網(wǎng)絡(luò)在自然語(yǔ)言文本結(jié)構(gòu)上的建模能力也激發(fā)了其在代碼建模上的探索[24]。源代碼數(shù)據(jù)相比于自然語(yǔ)言文本更易構(gòu)建圖表示形式,因此結(jié)合圖結(jié)構(gòu)的程序理解模型有著較好的前景[25]。
可以看到,深度代碼理解研究是眾多軟件工程任務(wù)的基礎(chǔ),不同表示形式所帶來(lái)的特征向量能夠?yàn)榇a搜索任務(wù)提供充足的特征信息。下一章則從深度程序理解視角針對(duì)代碼搜索任務(wù)進(jìn)行定義。
代碼搜索是信息檢索和程序理解的交叉研究,與文檔搜索技術(shù)類似,二者在諸如查詢理解、文檔索引、文檔排序等多種技術(shù)中有著較多共性。但從搜索對(duì)象來(lái)看,由于源代碼自身特性,對(duì)于代碼的理解包括兩個(gè)方面,即代碼的使用場(chǎng)景以及代碼算法原理。
以“冒泡排序”為查詢,文檔搜索和代碼搜索的結(jié)果示例如表2所示。可以看到,文檔搜索結(jié)果中往往包含原始關(guān)鍵詞以及圍繞關(guān)鍵詞展開(kāi)的一系列概念介紹和組合。而在代碼搜索結(jié)果中,則重點(diǎn)關(guān)注這一算法的具體實(shí)現(xiàn)以及代碼的正確性。
表2 代碼搜索與文檔搜索異同Table 2 Differences between code search and documents search
二者的核心差異在于如何實(shí)現(xiàn)文檔(代碼)的理解。同時(shí),基于源代碼功能特點(diǎn)、應(yīng)用場(chǎng)景、功能實(shí)現(xiàn)方式等特性將代碼與用戶意圖匹配,是兩種搜索方式最大差異。
從形式化角度看,此處記Q為查詢文本,C為源代碼片段。如公式(1)所示,RQ(Q)為查詢文本的表示模型,將用戶查詢轉(zhuǎn)化為向量形式的中間表示。
相應(yīng)的如公式(2)所示,RC(C)為程序理解模型,其將輸入的代碼片段轉(zhuǎn)化為特征向量,進(jìn)而對(duì)代碼結(jié)構(gòu)和語(yǔ)義進(jìn)行表示。
查詢文本和代碼片段分別通過(guò)RQ和RC被表示為中間形式φ,從這兩種特征向量出發(fā)計(jì)算二者匹配性質(zhì)。如公式(3)所示,M(φQ,φC)表示相關(guān)度計(jì)算模型,結(jié)合向量距離等方式計(jì)算查詢和代碼片段匹配程度。
相關(guān)性分?jǐn)?shù)ψ越大表明當(dāng)前代碼片段樣本與用戶意圖匹配程度越高。如公式(4)所示,假定有Ca和Cb兩個(gè)代碼片段,Oa和Ob分別表示文檔在結(jié)果列表中的順序。則代碼片段Ca和Cb與查詢文本Q之間的相關(guān)性分?jǐn)?shù)大小ψa和ψb關(guān)系決定排序位置,相關(guān)性分?jǐn)?shù)越大,則在結(jié)果列表中的位置越靠前。
可以看到,代碼搜索任務(wù)難點(diǎn)在于建立對(duì)源代碼片段的理解,在此基礎(chǔ)上實(shí)現(xiàn)用戶查詢意圖和代碼片段功能語(yǔ)義之間的匹配。
傳統(tǒng)的基于信息檢索模型的方法中,通常將代碼視為普通的自然語(yǔ)言文檔,在簡(jiǎn)單分詞、去除停用詞以及詞干化[26]處理之后,結(jié)合自然語(yǔ)言模型對(duì)用戶查詢和代碼文檔進(jìn)行向量化,最后計(jì)算二者的相似性。
Lucia等人[27]提出基于文本正規(guī)化的方法進(jìn)行代碼和文檔之間的溯源。Hill等人[28]將方法名信息引入檢索模型中增強(qiáng)代碼檢索結(jié)果表現(xiàn)。Lv等人[29]則結(jié)合API理解改進(jìn)基于信息檢索的代碼搜索系統(tǒng),其實(shí)現(xiàn)簡(jiǎn)單明了,是常用的研究基線。
Arwan等人[30]將主題模型和Tfidf模型[31]結(jié)合引入源代碼和查詢表示,提升了查詢和代碼匹配的準(zhǔn)確性。Bajracharya等人[32]重新歸類了代碼搜索特征,并按照語(yǔ)義類別不同重新分配了特征權(quán)重,提高了檢索效果。Niu等人[33]提出結(jié)合排序?qū)W習(xí)的代碼搜索方法。Jiang等人[34]在此基礎(chǔ)上對(duì)代碼搜索特征體系進(jìn)一步擴(kuò)充,并將其與排序?qū)W習(xí)結(jié)合。
深度代碼搜索研究則結(jié)合深度程序理解研究構(gòu)建檢索模型。Jiang等人[35]率先研究了源代碼和自然語(yǔ)言之間的語(yǔ)義鴻溝問(wèn)題。如圖2所示,查詢文本和代碼片段通過(guò)自然語(yǔ)言模型和程序理解模型獲得特征表示。獲取特征向量后,通過(guò)深度模型構(gòu)建匹配關(guān)系。
圖2 深度代碼搜索研究框架Fig.2 Research framework of deep code search
自然語(yǔ)言模型部分,詞表示方面,常用word2vector模型[35]、glove模型[36]以及fasttext模型[37]進(jìn)行表示;上下文表示方面常用Elmo模型[38]、Bert模型[39]等直接對(duì)句子建模獲取表示。
匹配模型部分,Mitra等人[40]和Xu等人[41]研究了將排序?qū)W習(xí)訓(xùn)練目標(biāo)與深度模型相結(jié)合,即神經(jīng)信息檢索模型。Wang等人[42]針對(duì)神經(jīng)檢索模型中的損失函數(shù)進(jìn)行了總結(jié),對(duì)比學(xué)習(xí)排序(contrastive learning)、三元排序(triplet loss)等方法逐漸受到關(guān)注。Wang等人[43]則結(jié)合強(qiáng)化學(xué)習(xí)改進(jìn)查詢理解,進(jìn)而提高檢索效果。
程序表示模型部分,Allamanis等人[44]進(jìn)行了較為詳細(xì)的總結(jié)和歸類。早期研究將代碼片段看作普通文本,結(jié)合自然語(yǔ)言建模方法,對(duì)詞序列[45]和API序列進(jìn)行建模;隨后一些工作逐漸重視代碼結(jié)構(gòu)特性,提出結(jié)合抽象語(yǔ)法樹(shù)[46-48]的代碼結(jié)構(gòu)建模方法;而源代碼較強(qiáng)的圖結(jié)構(gòu)使得近期結(jié)合圖神經(jīng)網(wǎng)絡(luò)源代碼建模研究正逐步受到重視。
本章從深度程序理解模型角度對(duì)當(dāng)前代碼搜索研究進(jìn)展進(jìn)行梳理。
如表3所示,在論文選擇依據(jù)方面,本文使用code search、code retrieval作為關(guān)鍵字進(jìn)行搜索,涵蓋軟件工程、自然語(yǔ)言處理、神經(jīng)計(jì)算等領(lǐng)域。最終,在相關(guān)會(huì)議、期刊以及預(yù)發(fā)表平臺(tái)Arxiv上收集到與深度代碼搜索相關(guān)的研究共40余篇論文。在此基礎(chǔ)上,針對(duì)本文剔除了案例研究型論文、系統(tǒng)設(shè)計(jì)型論文以及沒(méi)有明確評(píng)價(jià)指標(biāo)的研究論文,最終留下27篇進(jìn)行匯總。
表3 深度代碼搜索模型對(duì)比Table 3 Comparison between deep code search models
分析維度包括源代碼表示形式、深度模型結(jié)構(gòu)、模型評(píng)估所使用數(shù)據(jù)集以及評(píng)價(jià)指標(biāo)四個(gè)部分。源代碼表示形式從深度程序理解視角出發(fā)規(guī)劃,主要包括詞序列表示、API序列表示、樹(shù)結(jié)構(gòu)(主要是抽象語(yǔ)法樹(shù))和圖結(jié)構(gòu)(函數(shù)調(diào)用圖、語(yǔ)法樹(shù)子圖等)。深度模型結(jié)構(gòu)方面包括卷積網(wǎng)絡(luò)(CNN)、循環(huán)網(wǎng)絡(luò)(LSTM)、Transformer、注意力機(jī)制等。
Gu等人[19]對(duì)深度代碼搜索進(jìn)行了早期探索,其首先對(duì)API的搜索和生成進(jìn)行了研究,并在此基礎(chǔ)上提出了深度代碼搜索模型CodeNN,奠定了深度代碼搜索模型的基礎(chǔ)框架。而Li等人[16]則結(jié)合詞向量以無(wú)監(jiān)督方式對(duì)源代碼進(jìn)行建模,代碼文本被處理為詞序列后通過(guò)詞向量構(gòu)建篇章表示并在此基礎(chǔ)上實(shí)現(xiàn)匹配檢索。Chen等人[15]在此基礎(chǔ)上進(jìn)一步詳細(xì)研究了自然語(yǔ)言和API之間的語(yǔ)義鴻溝問(wèn)題。而Liu等人[3]則結(jié)合Li等人方法為代碼搜索工具增添模糊查詢能力。
從Gu等人工作出發(fā),一系列嘗試將不同深度模型架構(gòu)應(yīng)用于代碼搜索任務(wù)中。Li等人[50]初步嘗試了將注意力機(jī)制引入代碼匹配計(jì)算中。Wang等人[53]則使用CNN構(gòu)造多層注意力網(wǎng)絡(luò)捕獲源代碼深度語(yǔ)義。Sinha等人[54]則將孿生網(wǎng)絡(luò)應(yīng)用于代碼搜索任務(wù)中以增強(qiáng)查詢和代碼之間的匹配能力。Ling等人[22]將關(guān)鍵詞匹配和句法模式學(xué)習(xí)相分離,提出在新的代碼庫(kù)上泛化性更強(qiáng)的自適應(yīng)深度代碼搜索模型。Zhao等人[61]則將對(duì)抗學(xué)習(xí)應(yīng)用于訓(xùn)練過(guò)程中,提升了代碼與查詢文本的匹配度。
單純序列建模方法難以利用源代碼的結(jié)構(gòu)信息,Haldar等人[58]和Sun等人[56]使用抽象語(yǔ)法樹(shù)來(lái)信息增強(qiáng)代碼表示能力。Gu等人[62]在此基礎(chǔ)上結(jié)合語(yǔ)法樹(shù)建模源代碼中的語(yǔ)義依賴。Fang等人[66]則首次將自注意力網(wǎng)絡(luò)用于代碼搜索,Wang等人[23]在此基礎(chǔ)上結(jié)合自注意力網(wǎng)絡(luò)對(duì)源代碼序列信息和結(jié)構(gòu)信息進(jìn)行統(tǒng)一建模。
圖是源代碼中普遍存在的結(jié)構(gòu),Ling等人[52]從語(yǔ)法樹(shù)出發(fā)構(gòu)建子圖以對(duì)代碼中不同節(jié)點(diǎn)之間關(guān)系進(jìn)行建模。之后使用關(guān)系圖卷積網(wǎng)絡(luò)建模對(duì)查詢和代碼特征向量進(jìn)行相互增強(qiáng),最后提高檢索效果。Wan等人[45]則將源代碼不同表示方法視為多模態(tài)任務(wù),將代碼序列、語(yǔ)法樹(shù)以及圖三者融合對(duì)代碼進(jìn)行語(yǔ)義建模表示。最終結(jié)果取得了SOTA效果,證實(shí)融合序列和結(jié)構(gòu)語(yǔ)義在代碼理解任務(wù)上具有實(shí)際效果。
而在預(yù)訓(xùn)練模型方面,隨著B(niǎo)ert[67]等基于Transformer預(yù)訓(xùn)練模型在自然語(yǔ)言處理領(lǐng)域各項(xiàng)任務(wù)上取得SOTA結(jié)果。部分研究者也開(kāi)始關(guān)注源代碼的預(yù)訓(xùn)練效果。Feng等人[59]結(jié)合對(duì)比學(xué)習(xí)訓(xùn)練范式,在代碼文本上進(jìn)行Bert模型訓(xùn)練。Kanade等人[68]則聚焦于Python代碼進(jìn)行了Bert模型訓(xùn)練,并提出CuBert模型。Guo等人[25]將代碼結(jié)構(gòu)加入與訓(xùn)練過(guò)程中,提出GraphCodeBert,結(jié)合圖結(jié)構(gòu)增強(qiáng)了Transformer在預(yù)訓(xùn)練代碼時(shí)的表達(dá)能力。而Ishtiaq等人[69]則在CodeBert等模型基礎(chǔ)上通過(guò)代碼搜索任務(wù)對(duì)與訓(xùn)練模型在具體代碼理解任務(wù)上的效果進(jìn)行了實(shí)際驗(yàn)證。結(jié)果表明,基于Transformer的預(yù)訓(xùn)練語(yǔ)言模型在代碼理解任務(wù)上同樣具備良好效果。
代碼搜索任務(wù)評(píng)價(jià)指標(biāo)和信息檢索任務(wù)一致,主要考慮結(jié)果的兩個(gè)方面,即檢索結(jié)果的相關(guān)性以及相關(guān)結(jié)果的排名次序。
精確度P@K計(jì)算方法如公式(5)所示,衡量檢索結(jié)果中相關(guān)文檔數(shù)量占檢索結(jié)果的比重,其中K表示一次檢索過(guò)程中得到的文檔數(shù)目。
召回率R@K計(jì)算方法如公式(6)所示,其主要衡量檢索結(jié)果中相關(guān)文檔數(shù)目占總體相關(guān)文檔的比重,K表示一次檢索中得到的文檔數(shù)目。
可以看到,精確度和召回率指標(biāo)能夠衡量前K個(gè)檢索結(jié)果中相關(guān)文檔比率的情況。
平均倒數(shù)排名(mean reciprocal rank,MRR)引入相關(guān)文檔在結(jié)果中順序進(jìn)行結(jié)果評(píng)價(jià)。如公式(7)所示Ranki表示相關(guān)文檔在檢索結(jié)果中的次序。
如公式(8)所示,平均精確度(average precision)將精確度和文檔次序相結(jié)合。其中m表示當(dāng)前檢索結(jié)果中相關(guān)文檔總數(shù),N表示檢索結(jié)果總數(shù),P(k)對(duì)應(yīng)為本次檢索結(jié)果中前k個(gè)結(jié)果的精確度(即P@K),rel(k)為一個(gè)指示函數(shù),當(dāng)?shù)趉個(gè)文檔相關(guān)時(shí)為1否則為0。
MAP指標(biāo)則將API在所有查詢Q上計(jì)算了平均。
折扣累積增益(DCG)則將相關(guān)性等級(jí)引入評(píng)價(jià)。如公式(9)所示。rel(k)衡量第k個(gè)文檔的相似性分?jǐn)?shù),如1~4整數(shù)階段式分?jǐn)?shù),分母處取當(dāng)前次序相關(guān)的對(duì)數(shù)作為折扣因子。
而歸一化折扣累計(jì)增益NDCG指標(biāo)則使用最優(yōu)排列結(jié)果下的DCG分?jǐn)?shù)對(duì)其歸一化。除以上指標(biāo)外,還有Frank評(píng)價(jià)描述在檢索列表中首個(gè)相關(guān)結(jié)果在列表中次序。
本文針對(duì)2016年至今的代碼搜索研究工作進(jìn)行梳理,對(duì)其中用于評(píng)估模型效果的數(shù)據(jù)集進(jìn)行了總結(jié)。選擇標(biāo)準(zhǔn)方面,數(shù)據(jù)集必須公開(kāi)可用,同時(shí)至少有兩篇以上工作都使用該數(shù)據(jù)集對(duì)模型進(jìn)行評(píng)價(jià)。
代碼搜索常用評(píng)估數(shù)據(jù)集,如表4所示。其中共涉及七篇工作。數(shù)據(jù)集構(gòu)造方面,目前工作主要通過(guò)自動(dòng)化抽取方式構(gòu)建大規(guī)模代碼片段——自然語(yǔ)言文本組合作為訓(xùn)練數(shù)據(jù)。在自動(dòng)標(biāo)注基礎(chǔ)上結(jié)合負(fù)采樣方法構(gòu)建驗(yàn)證數(shù)據(jù)。模型評(píng)估使用常見(jiàn)代碼搜索問(wèn)題作為查詢,在構(gòu)建的代碼庫(kù)上進(jìn)行精細(xì)標(biāo)注。
表4 代碼搜索任務(wù)評(píng)估數(shù)據(jù)集Table 4 Evaluation datasets for code search task
按照數(shù)據(jù)標(biāo)注劃分,其中CSN和ROSF數(shù)據(jù)嚴(yán)格進(jìn)行了相關(guān)性等級(jí)標(biāo)注;DCS、NCS和CosBench首先篩選了自然語(yǔ)言查詢,之后在代碼庫(kù)上標(biāo)注了相關(guān)代碼片段。
按照評(píng)價(jià)指標(biāo)劃分,CNS和ROSF可以使用NDCG進(jìn)行評(píng)價(jià);StaQC主要結(jié)合文本分類指標(biāo)進(jìn)行評(píng)價(jià);其余數(shù)據(jù)集大多采用MRR、P@K以及Frank指標(biāo)進(jìn)行評(píng)估。
按照編程語(yǔ)言劃分,DCS、NCS、ROSF、CosBench數(shù)據(jù)集主要包含Java編程語(yǔ)言代碼數(shù)據(jù)(涵蓋安卓)。CoNaLa數(shù)據(jù)則結(jié)合Stackoverflow社區(qū)數(shù)據(jù)挖掘以及人工標(biāo)注,構(gòu)建了含有Java和Python編程語(yǔ)言的數(shù)據(jù)。StaQC數(shù)據(jù)集主要包含Python和SQL兩種標(biāo)注結(jié)果。CodeSearchNet數(shù)據(jù)集則包含Java、Python、Php、Ruby、Go、Javascript六種編程語(yǔ)言,覆蓋編程語(yǔ)言范圍最廣。
按照任務(wù)劃分,StaQC將代碼搜索任務(wù)轉(zhuǎn)換為相關(guān)文檔分類問(wèn)題,因此可結(jié)合文本分類方法進(jìn)行研究;CSN和ROSF數(shù)據(jù)標(biāo)注等級(jí)信息充分,可結(jié)合排序?qū)W習(xí)方法進(jìn)行研究;其余數(shù)據(jù)集中包含的代碼片段——自然語(yǔ)言組合可被用于代碼摘要任務(wù)以及基于摘要技術(shù)的代碼搜索研究。
本節(jié)在數(shù)據(jù)集和評(píng)價(jià)指標(biāo)介紹基礎(chǔ)上,從模型效果角度對(duì)近期代碼搜索實(shí)驗(yàn)工作進(jìn)行梳理,重點(diǎn)側(cè)重基于深度模型的代碼搜索方法。評(píng)價(jià)指標(biāo)則涵蓋Recall、Precision、MRR、MAP、NDCG。統(tǒng)計(jì)時(shí),提出數(shù)據(jù)集的相關(guān)文獻(xiàn)Baseline相應(yīng)在文獻(xiàn)一欄中加粗注明。部分?jǐn)?shù)據(jù)集如StaQC數(shù)據(jù)集提出時(shí)使用分類指標(biāo)作Baseline,因此此處未注明。
具體結(jié)果如表5所示,本文按照數(shù)據(jù)集、相關(guān)文獻(xiàn)以及評(píng)價(jià)指標(biāo)對(duì)結(jié)果進(jìn)行了組織。從數(shù)據(jù)集角度來(lái)看,StaQC數(shù)據(jù)集應(yīng)用最為廣泛,相對(duì)影響力較大。DCS數(shù)據(jù)集上的實(shí)驗(yàn)相對(duì)更為充分,不同文獻(xiàn)基本覆蓋了所有的評(píng)價(jià)指標(biāo)。從評(píng)價(jià)指標(biāo)角度看,MRR指標(biāo)是目前代碼搜索模型驗(yàn)證時(shí)的常用指標(biāo)。而從編程語(yǔ)言角度來(lái)看,目前研究較多的編程語(yǔ)言為Java。
表5 代碼搜索模型結(jié)果對(duì)比Table 5 Comparison of code search model results
代碼搜索研究正逐漸受到學(xué)界重視,本文從深度程序理解視角出發(fā)對(duì)代碼搜索近期進(jìn)展進(jìn)行了梳理,而未來(lái)還可以從以下方面對(duì)該問(wèn)題進(jìn)行研究:
(1)穩(wěn)定可復(fù)現(xiàn)的評(píng)價(jià)方法。當(dāng)前多數(shù)研究中未開(kāi)放評(píng)估數(shù)據(jù)集,而開(kāi)放的數(shù)據(jù)集中存在著標(biāo)注不一致等問(wèn)題。Liu等人[73]研究表明數(shù)據(jù)集和開(kāi)源代碼問(wèn)題使得深度模型的結(jié)果可復(fù)現(xiàn)性存在諸多問(wèn)題。未來(lái)研究中應(yīng)嘗試構(gòu)建一致明確的數(shù)據(jù)集和評(píng)價(jià)方法以及平臺(tái),以促進(jìn)代碼搜索研究。
(2)深入研究程序表示技術(shù)。源代碼的理解和建模是代碼搜索任務(wù)的關(guān)鍵。大多數(shù)模型采用序列建模方式對(duì)源代碼進(jìn)行特征抽取表示,少數(shù)工作將樹(shù)、圖結(jié)構(gòu)數(shù)據(jù)簡(jiǎn)單進(jìn)行了拼接融合以引入代碼結(jié)構(gòu)信息。在未來(lái)研究中可以嘗試結(jié)合圖神經(jīng)網(wǎng)絡(luò)對(duì)代碼進(jìn)行更加深入的結(jié)構(gòu)建模。
(3)多模態(tài)源代碼建模方法。源代碼由標(biāo)識(shí)符和編程語(yǔ)言特定的關(guān)鍵字組成。其中編程語(yǔ)言特定的關(guān)鍵字提供了代碼的結(jié)構(gòu)信息,而代碼標(biāo)識(shí)符則提供了更為充分的自然語(yǔ)言信息。未來(lái)研究中可以將兩種模態(tài)數(shù)據(jù)相結(jié)合,對(duì)代碼的結(jié)構(gòu)語(yǔ)義以及自然語(yǔ)義進(jìn)行統(tǒng)一建模,進(jìn)而用于代碼搜索任務(wù)。
(4)代碼搜索研究應(yīng)用問(wèn)題。當(dāng)前代碼搜索研究重點(diǎn)關(guān)注基于深度代碼建模方法的重排序問(wèn)題。而代碼搜索工具研究則更加關(guān)注代碼數(shù)據(jù)的采集、清洗和管理。代碼搜索研究中一些數(shù)據(jù)處理方法和效果優(yōu)化方法與實(shí)際應(yīng)用系統(tǒng)之間并不適用。未來(lái)研究中可以從實(shí)際應(yīng)用目的出發(fā)設(shè)計(jì)搜索模型。
本文首先以深度程序理解視角切入對(duì)代碼搜索任務(wù)進(jìn)行了定義。其次,以此為基礎(chǔ)總結(jié)得出深度代碼搜索兩種研究范式,并進(jìn)行梳理相關(guān)研究成果。同時(shí),本文總結(jié)整理了代碼搜索任務(wù)常見(jiàn)的評(píng)估方法。最后結(jié)合本文研究結(jié)果,對(duì)未來(lái)研究進(jìn)行了展望。