• 
    

    
    

      99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看

      ?

      基于深度學習的程序理解研究進展

      2019-08-01 03:23:10
      計算機研究與發(fā)展 2019年8期
      關鍵詞:代碼向量程序

      劉 芳 李 戈 胡 星 金 芝

      (北京大學信息科學技術學院 北京 100871) (高可信軟件技術教育部重點實驗室(北京大學) 北京 100871)

      程序理解(又叫軟件理解)是通過對程序進行分析、抽象、推理從而獲取程序中相關信息的過程,自1968年軟件工程誕生起,程序理解就開始受到關注.程序理解是軟件復用、維護、遷移、逆向工程等任務中的首要活動[1],其目的是通過對程序進行多方面、多層次、多角度地分析來提取程序中的相關信息.程序理解是軟件工程中的一個重要部分,在整個軟件維護與開發(fā)過程中起著舉足輕重的作用.

      早期的程序理解大多基于人為制定的啟發(fā)式規(guī)則確定程序的特征,然后根據(jù)所確定的特征從程序中提取出的相關信息并進行分析,分析結果完全依賴于開發(fā)人員具備的先驗知識.主要方法包括程序靜態(tài)分析、動態(tài)分析等,其中,靜態(tài)分析直接分析程序源代碼,分析過程不需要執(zhí)行程序[2];動態(tài)分析用于理解程序運行時的性質,在程序執(zhí)行過程中獲取其輸入輸出關系等[3].這些方法主要局限有3個方面:

      1) 完全依賴開發(fā)人員具備的先驗知識來確定需要從程序中提取什么特征;

      2) 一旦軟件系統(tǒng)過于復雜規(guī)模過大,則程序性質分析不能有效地進行,不具備可擴展性;

      3) 針對不同程序分析需求,需制定特定規(guī)則進行分析,通用性較差.

      深度學習是一種數(shù)據(jù)驅動的端到端的方法,它根據(jù)已有數(shù)據(jù)構建深度神經(jīng)網(wǎng)絡來挖掘數(shù)據(jù)中隱含的特征.近年來,深度學習已經(jīng)在語音識別、圖像處理、自然語言處理等眾多領域中受到廣泛關注.程序理解需要從程序中提取出與程序理解任務相關的特征信息,若能運用深度學習技術根據(jù)程序理解任務以及已有數(shù)據(jù)自動地學習程序數(shù)據(jù)中蘊含的特征,將會極大地提高程序理解的效率.開源社區(qū)(例如GitHub[注]https://github.com/)和編程問答網(wǎng)站(StackOverflow[注]https://stackoverflow.com/)等平臺上存在大量高質量的開源代碼和文檔,這些數(shù)據(jù)中蘊含著許多知識,為研究者們提供了利用深度學習技術挖掘代碼和文檔數(shù)據(jù)等中包含的知識來解決程序理解相關問題的新途徑.因此,人們開始嘗試如何將深度學習技術應用于程序理解任務,利用深度神經(jīng)網(wǎng)絡表征程序中包含的信息,獲得程序的特征向量表示,從而替代傳統(tǒng)方法中的人工特征提取.

      程序理解中常用的深度學習技術包括循環(huán)神經(jīng)網(wǎng)絡(recurrent neural network, RNN)、卷積神經(jīng)網(wǎng)絡(convolution neural network, CNN)、序列到序列(seq2seq)模型以及注意力(attention)機制等,它們可以用于不同的程序理解應用場景:

      1) RNN通過增加神經(jīng)網(wǎng)絡中隱藏層節(jié)點之間的連接引入循環(huán)機制來處理序列中前后關聯(lián)問題,適合對較長的序列進行建模.基于RNN及其變體LSTM[4]和GRU[5]的模型可用于對程序語言的建模,獲得程序序列的特征向量表示,因此RNN在代碼補全、代碼檢索、代碼克隆檢測等任務中被廣泛使用.

      2) CNN利用卷積核對輸入數(shù)據(jù)進行卷積運算提取數(shù)據(jù)中的局部特征,擅長于處理具有局部性的數(shù)據(jù).在程序理解任務中,CNN可用于提取程序中的局部特征,可被應用于程序分類、程序方法名預測等任務中.

      3) 序列到序列(seq2seq)模型則用于從輸入序列到輸出序列映射的任務中,它包含編碼器(encoder)和解碼器(decoder)兩部分,其中編碼器用于將輸入序列表示為特征向量,解碼器則根據(jù)該向量生成輸出序列.可用于程序生成、程序注釋生成等任務中.

      4) 注意力(attention)機制[6]最早在seq2seq模型中被使用,通過引入該機制,神經(jīng)網(wǎng)絡在生成每一個輸出時動態(tài)地關注輸入中與當前輸出更相關的內(nèi)容,在輸入較長的情境下也能減輕網(wǎng)絡對長序列的記憶負擔,能有效提升模型性能.注意力機制在程序生成、程序注釋生成等任務中被廣泛使用.此外,它還可用于基于RNN的語言模型,在預測下一個元素時可以重點關注上文中更相關的部分.因此,注意力機制也可用于代碼補全任務.

      5) 指針網(wǎng)絡(pointer networks)[7]是利用注意力機制設計的一種神經(jīng)網(wǎng)絡結構.它直接利用注意力機制計算得到的權重作為指針,利用該指針從輸入文本中選擇最相關的元素作為解碼器的輸出.See等人[8]利用指針網(wǎng)絡生成文本摘要,以解決摘要生成中包含詞表之外的詞(out of vocabulary, OoV)的問題.受此啟發(fā),近年研究者開始將指針網(wǎng)絡應用于代碼補全任務中.

      上述方法最早被應用于自然語言處理任務中,由于程序語言和自然語言在一定程度上的相似性,這些技術被遷移到了程序理解的相關任務中.但程序語言具有其自身獨特的性質,例如更強的結構性、可執(zhí)行性等,因此設計程序理解模型時需要考慮程序中包含的這些性質.同時,程序理解的不同任務需求對模型的設計也有相應的要求,例如在程序變量命名任務中(代碼風格修正),需要考慮程序代碼中的數(shù)據(jù)流和控制流信息,所以一般構建基于圖的神經(jīng)網(wǎng)絡進行建模;在程序自動生成任務中,生成的程序需要嚴格符合語法規(guī)則,需要對程序的抽象語法樹進行建模.總之,設計程序理解模型,需要重點考慮程序自身的特性以及具體的理解任務需求.

      1 程序性質及程序理解框架

      1.1 程序性質

      程序語言與自然語言有許多相似之處,例如它們都由詞素(token)組成,都可以解析為語法樹的形式,并且都具有較高的自然性(重復性)[9]等.因此,一些適合于自然語言處理任務的模型可以被遷移到程序理解任務中.例如近幾年很多基于統(tǒng)計的語言模型被用于程序語言處理中[9-14],其中包括基于深度學習的統(tǒng)計語言模型.但是,程序語言與自然語言之間仍然有較大的差別,程序語言具有其自身獨特的性質,主要包括強結構性、自定義標識符、長依賴和可執(zhí)行性,這些性質是構建程序理解模型不可忽視的.

      1.1.1 強結構性

      程序具有更強的結構性,程序中存在著大量的嵌套結構.例如圖1是Python語言實現(xiàn)的冒泡排序的算法[注]此處不特指Python語言, 其他語言的實現(xiàn)與之類似,其中2個for循環(huán)相互嵌套,在內(nèi)部的for循環(huán)中包含一個if語句,這樣相互嵌套語句中蘊含著程序的邏輯結構,這些結構對于程序語義的理解十分關鍵.在程序語言中,這樣的結構無處不在.在一些較長的程序中,嵌套層次往往會非常深.當把程序解析為語法樹之后,語法樹往往非常大.程序的結構對于整個程序的理解至關重要,也是程序理解中面臨的難點之一.

      Fig. 1 Bubble sort algorithm of Python code
      圖1 Python語言實現(xiàn)的冒泡排序算法

      1.1.2 自定義標識符

      與自然語言不同,程序中包含著大量用戶自定義的標識符,例如函數(shù)名、變量名、類名等.在對自然語言建模時,通常需要預先構建一個能夠覆蓋數(shù)據(jù)集中絕大多數(shù)詞語的詞匯表.在自然語言相關的任務中,很少會出現(xiàn)創(chuàng)造新詞的情況.而程序中卻存在著大量用戶自己定義的標識符,并且不同用戶的命名習慣又不盡相同.因此在對程序代碼的token建模時,預先構建好的詞匯表往往不能滿足建模的需求.無論定義多大的詞表,總會有許多出現(xiàn)在詞表之外(OoV)的新詞,這對于程序的理解造成了較大的干擾.

      1.1.3 長依賴

      在程序語言中,上下文之間依賴間隔可能會很長.例如在程序開始時定義的變量可能會在程序的末尾用到.并且由于程序中存在著作用域,一些局部變量或者方法只會在其各自的作用域中用到,而不會在其他地方用到,而這些局部變量或方法的存在會增加上下文直接的依賴間隔.在程序中,大部分前文信息很可能與當前的token是無關的.

      1.1.4 可執(zhí)行性

      程序必須是可以執(zhí)行的,這就要求程序代碼必須嚴格符合語法規(guī)則,這也是程序語言與自然語言的一個很大的不同之處.在自然語言中,即使語句中存在一些語法錯誤,其表達的含義仍然是可以理解的,而程序語言中只要包含一個語法錯誤,便會導致其無法運行.因此,在程序理解中程序的語法至關重要.

      1.2 基于深度學習的程序理解框架

      在構建程序理解模型時,程序特性以及具體的任務需求不容忽視.針對不同程序理解任務需求,程序可以被表示為多種形式,以便于對程序中包含的不同特性進行建模.目前主要有3種表示形式:

      1) 序列.基于序列的表示方法將程序表示為序列的形式,例如token序列、字符序列或者API序列.

      2) 結構.基于結構的表示方法考慮程序語言的結構,將程序表示為抽象語法樹(abstract syntax tree, AST)或者程序圖(graph)的形式.

      3) 執(zhí)行過程.基于執(zhí)行過程的表示方法重點關注程序的動態(tài)執(zhí)行過程,將程序運行過程中產(chǎn)生的中間結果作為程序的表示,例如在執(zhí)行過程中調(diào)用的子程序及其參數(shù),或者在執(zhí)行過程中程序中各個變量值的變化情況.

      基于深度學習的程序理解框架可以用圖2來展示.程序中包含不同性質,不同程序理解任務需求對程序性質的側重點不同,因此在人們在完成程序理解任務時會選擇合適的形式(序列、結構或執(zhí)行過程)來表示程序,然后構建相對應的程序理解模型對不同形式的程序進行建模.表1列出了程序理解中主要任務、任務重點關注的性質以及完成該任務主要采用的程序表示形式.

      2 程序理解的深度學習模型

      不同程序理解任務根據(jù)其需求采用不同的程序表示方式,然后構建相應模型完成具體任務.基于此,本文將基于深度學習的程序理解模型分為3類:基于序列的程序理解模型、基于結構的程序理解模型和基于執(zhí)行過程的程序理解模型,本節(jié)結合這些模型的應用場景對這3種模型進行詳細介紹.

      2.1 基于序列的程序理解模型

      程序是由符號序列構成的,因此我們可將程序代碼形式化地表示為字符(character)或詞素(token)序列.除此之外,程序中的應用程序接口(application programming interface, API)序列中蘊含著程序的功能信息,因此API序列也成為了許多研究工作的研究對象.目前已有的基于序列的程序理解研究工作主要基于構建統(tǒng)計語言模型來學習程序的序列化表示.對于程序序列S=t1,t2,…,tn來說,該序列出現(xiàn)的概率為:

      P(S)=P(t1,t2,…,tn)=P(t1)×P(t2|t1)×
      P(t3|t1,t2)×…×P(tn|t1,t2,…,tn-1),

      (1)

      其中,P(t1)表示第1個詞是t1的概率,P(tn|t1,t2,…,tn-1)表示給定前n-1個詞的情況下,第n個詞出現(xiàn)的概率.早期的研究工作大多基于N-gram語言模型對程序序列進行建模[9,15].隨著深度學習的發(fā)展,近年來,基于深度循環(huán)神經(jīng)網(wǎng)絡的統(tǒng)計語言模型開始被應用于程序序列建模中.表2列出了基于序列的程序理解相關研究工作.

      Table 2 Research on Sequence-Based Program Comprehension表2 基于序列的程序理解相關研究工作

      2.1.1 基于字符序列的程序理解模型

      基于字符序列的程序理解模型將程序表示為字符序列,利用深度神經(jīng)網(wǎng)絡對其進行建模,學習代碼字符序列中包含的信息.由于程序中包含的字符數(shù)目是確定的,因此將程序表示為字符序列在構建詞匯表時不會出現(xiàn)OoV的問題,這也是采用字符序列表示程序的主要原因.Cummins等人[12]構建了字符級別的LSTM語言模型學習程序,該方法將程序代碼視為字符構成的序列.他們基于該模型構建了程序生成的工具CLgen,利用該工具生成了大量程序作為基準數(shù)據(jù)(benchmark data),為其他程序理解相關研究提供了測評數(shù)據(jù).盡管基于字符序列的程序理解模型不會出現(xiàn)OoV問題,但極大地增加了程序序列長度,使得模型很難學習到整段代碼的語義.不僅如此,用字符序列表示程序無法捕捉程序中的token,API等中包含的信息,這些信息對于程序語義的理解十分重要.

      2.1.2 基于詞素(token)序列的程序理解模型

      由于字符的表達能力較弱,許多程序理解模型將程序詞素(token)序列作為研究對象.基于token序列的程序理解模型將程序表示為token序列,利用深度神經(jīng)網(wǎng)絡對token序列進行建模,學習序列中包含的信息.給定部分程序序列,模型可以預測之后最可能出現(xiàn)的token.因此,該模型可被應用于代碼補全任務.除此之外,該模型也可以得到整個程序序列的特征向量表示,基于該向量人們可以完成程序注釋生成、代碼檢索等任務.

      在代碼補全任務中,一些工作直接構建基于RNN的語言模型對token序列建模,根據(jù)已有token序列預測下一個token.例如White等人[13]設計了一個RNN語言模型對程序代碼的token序列建模,為了驗證該模型的有效性,他們將其應用于Java語言的代碼補全任務中并取得了72.2%的準確率.Bhoopchand等人[14]則提出了基于指針網(wǎng)絡的程序語言模型,該工作旨在解決程序代碼中自定義標識符之間的長依賴問題.該方法在構建LSTM語言模型的過程中,依次記錄程序代碼中出現(xiàn)過的自定義標識符,通過指針網(wǎng)絡選擇標識符作為輸出的備選項,最后結合語言模型和指針網(wǎng)絡的結果,共同預測輸出詞語的概率分布.在Python語言的代碼補全任務的實驗結果表明:該模型相較于N-gram模型和普通的LSTM模型能夠取得更高的準確率,并且該方法能夠預測出距離當前位置較遠的上文中出現(xiàn)的自定義標識符.以上基于token序列的代碼補全模型相較于傳統(tǒng)基于統(tǒng)計和規(guī)則的方法而言能夠取得更高的準確率,且實現(xiàn)較為簡單.但這些模型也存在著一定的缺陷,例如將程序表示為token序列會丟失程序中的結構信息,導致模型不能很好地對程序的結構進行建模,從而無法為代碼補全任務提供充分的信息.

      在代碼注釋生成任務中,許多工作基于seq2seq框架構建模型完成該任務.這些工作首先將代碼表示為token序列,然后構建基于RNN或CNN的編碼器對代碼進行建模,得到其特征向量表示,最后根據(jù)該向量構建解碼器生成代碼的自然語言描述.例如,Iyer等人[17]和Hu等人[18]使用RNN作為編碼器對代碼進行編碼得到其向量表示,然后根據(jù)該向量利用解碼器生成代碼注釋,并引入了注意力機制.而Allamanis等人[16]則采用基于注意力機制CNN對程序建模,提取程序中存在的關鍵語句以及層次結構性的特征,將該模型應用于代碼注釋生成(方法名的預測)任務中.該方法將函數(shù)體表示為token序列,在序列上進行卷積操作并引入注意力機制學習序列和函數(shù)名相關的關鍵信息.同時引入了指針網(wǎng)絡來解決OoV的問題,在Java項目的方法名預測任務上達到了超過40%的F1值.相較于CNN,RNN能夠記憶更長的代碼序列信息,而CNN模型更關注于程序局部特征并且模型訓練效率較高.以上這些工作相較于傳統(tǒng)基于人工定義的規(guī)則或模板抽取代碼中對應的內(nèi)容的方法能夠生成更加豐富的注釋內(nèi)容,且不需要人為制定規(guī)則,模型的可擴展性更強.但是這些基于token序列的代碼摘要模型在對代碼進行建模時未能充分考慮程序中的結構性,且生成的摘要通常比較簡短,很難用于生成較為復雜的代碼的摘要.

      在代碼檢索任務中,目前基于token序列的模型將程序表示為token序列,然后構建RNN模型得到序列的向量表示,將該向量與其對應的自然語言查詢語句的向量映射到相近的向量空間中.在檢索時,直接根據(jù)查詢語句的向量在向量空間中搜索與其相近的代碼向量作為檢索結果.Gu等人[19]提出了基于深度學習的代碼檢索模型,使用RNN得到自然語言查詢語句與其對應的代碼的向量表示,使得這2種向量映射到相近的向量空間中.對于自然語言,該方法使用RNN以及最大池化方法進行編碼得到其向量表示;對于代碼,該方法分別對代碼中的token序列、方法名序列以及API序列進行編碼,分別采用了RNN,RNN以及MLP模型,之后進行最大池化操作,然后將這3個向量進行組合作為代碼的向量表示.

      在得到代碼和查詢語句的向量表示之后,通過余弦相似度函數(shù)來衡量這2個向量之間的相似度,將查詢語句與其對應代碼的向量作為正例,然后從代碼庫中隨機挑選一個代碼作為負例,通過最大化正例之間余弦相似度和最小化負例之間的余弦相似度來訓練模型,使得模型能夠將自然語言查詢語句與其對應的代碼的向量表示映射到相近的向量空間中.實驗結果表明,該方法在代碼檢索任務中較其他方法取得了較大的提升.傳統(tǒng)代碼搜索方法基于信息檢索中的相似度匹配方法來匹配自然語言和代碼,只能根據(jù)較低層次的特征進行搜索,例如關鍵詞匹配.而運用深度神經(jīng)網(wǎng)絡得到代碼序列和查詢語言的向量表示然后再對向量之間的空間距離進行優(yōu)化的方式能夠挖掘出更高層次的匹配特征,因此這種方法可以取得更好的效果.

      基于token序列的程序理解模型還可以應用于代碼糾錯任務中,Gupta等人[20]提出了基于強化學習的程序語言糾錯模型,該方法首先基于LSTM網(wǎng)絡對程序中的token序列進行編碼,得到每一個token的向量表示,然后基于強化學習策略實現(xiàn)程序代碼糾錯.在強化學習策略中,狀態(tài)(state)是一個程序文本和游標的二元組string,cursor,其中string表示程序文本,cursor表示游標,用于在學習過程中選擇程序中需要修改的位置.模型學習過程中,代理(agent)每一時刻根據(jù)當前狀態(tài)選擇要執(zhí)行的動作(actions),其中動作分為2類,分別為游標位置更新動作(navigation actions)和修改程序文本動作(edit actions).當代理能夠糾正全部錯誤時獎勵(reward)是最大的(maximum_reward),此外還定義了中間獎勵(intermediate_reward),作為糾正不低于一個錯誤時的獎勵.該方法在學習時采用了異步的優(yōu)勢行動者評論家算法(asynchronous advantage actor-critic, A3C)[22]算法.實驗結果表明:該方法在C語言程序糾錯中準確率較當時最好的方法[23]取得了較大的提升.但是該方法目前只能對程序中的簡單錯誤進行糾正,較為復雜的錯誤目前還沒有較好的解決方案.

      2.1.3 基于應用程序接口(API)序列程序理解模型

      基于應用程序接口(API)序列程序理解模型將程序中包含的API序列作為研究對象.由于程序所調(diào)用的API可以在一定程度上反映了程序的功能特性,因此一些研究工作對程序中包含的API序列進行建模,具體的任務包括API序列檢索、代碼檢索以及代碼注釋生成.

      在代碼檢索和API序列檢索任務中,現(xiàn)有工作都是通過對比自然語言和代碼(API序列)向量的相似度來完成.Gu等人[21]提出了基于深度學習的API檢索方法,根據(jù)自然語言查詢語句來檢索與其相匹配的API序列.該方法采用seq2seq框架構建模型,首先將自然語言編碼為一個特征向量,然后基于該向量生成API序列.在生成API序列時,該方法還考慮了API的重要性,在損失函數(shù)中增加了懲罰項,對數(shù)據(jù)集中出現(xiàn)頻率較高的API進行懲罰,避免模型頻繁地預測高頻API.該方法利用BLEU來評估生成的API序列的質量,在API序列檢索任務中,較其他方法取得了40%左右的提升.最近,Gu等人[19]又提出了基于深度學習的代碼檢索方法,如2.1.2節(jié)介紹,該方法對代碼中的token序列、方法名序列以及API序列進行編碼,將這3個向量進行組合作為代碼的表示.

      在代碼注釋生成任務中,Hu等人[18]對基于seq2seq的程序注釋模型進行了改進.在程序的表示中,除了代碼token序列之外,該文還考慮了代碼中調(diào)用的API序列中所包含的知識,將這些知識輸入到網(wǎng)絡模型中輔助生成注釋,使得生成的注釋能夠更好地描述代碼的功能.實驗結果表明:該方法的BLEU指標相比Iyer等人[17]的方法在開源Java項目的注釋生成任務上提升了近20個百分點,取得了當時最好的效果[18].

      以上工作表明了API序列在程序理解任務中的重要性,對API序列中包含的信息進行挖掘可以幫助人們更好地理解程序.基于結構的程序理解模型則考慮了程序語言的語法結構、數(shù)據(jù)流以及控制流等信息,通過將程序表示為抽象語法樹或者程序圖的形式來對程序的語法結構、數(shù)據(jù)流動和控制流等進行建模,在代碼補全、代碼注釋生成、代碼模式檢測以及程序自動生成等任務中被廣泛使用.表3是基于結構的程序理解相關研究工作.

      Table 3 Research on Structure-Based Program Comprehension表3 基于結構的程序理解相關研究工作

      2.2 基于結構的程序理解模型

      2.2.1 基于抽象語法樹的程序理解模型

      抽象語法樹(AST)是一種程序代碼的抽象表示形式,樹中的每一個節(jié)點(及其子節(jié)點)對應源代碼中的某個代碼片段.在抽象語法樹中,非終結符對應于樹的中間節(jié)點(如Assign,If,For,Expr等),與代碼片段的具體類型相對應,與程序結構緊密相關;而終結符則位于樹的葉子節(jié)點(如字符串、變量名、方法名等),與程序語義密切相關.抽象語法樹可以有效地表示程序的語法及其結構,被廣泛應用于程序理解相關任務中[24-27],如代碼補全、程序自動生成、代碼模式檢測等.

      在代碼補全任務中,基于AST的程序理解模型針對代碼的抽象語法樹進行建模.在這些工作中,程序被解析為AST,然后對AST進行遍歷得到節(jié)點序列,然后構建基于循環(huán)神經(jīng)網(wǎng)絡的語言模型對節(jié)點序列進行建模.Li等人[24]和Liu等人[25]構建基于LSTM的代碼補全模型在AST節(jié)點序列上完成代碼補全任務,根據(jù)已有AST節(jié)點來預測之后最可能出現(xiàn)的AST節(jié)點.在預測AST節(jié)點時分為2種情況,即預測節(jié)點的類型(type)和節(jié)點的取值(value).由于節(jié)點類型數(shù)目是確定的,因此在節(jié)點類型預測時不存在前文中提到的OoV的問題.而節(jié)點的值中包含了大量程序員自定義的標識符,會出現(xiàn)OoV問題,因此Li等人[24]在預測節(jié)點值時引入了指針網(wǎng)絡來緩解OoV.除此之外,該方法中還引入了注意力機制.到目前為止,該方法在基于AST的代碼補全任務上取得了當時最好的效果[24].盡管AST可以提供程序語法和結構信息,但以上這些工作都是針對AST節(jié)點序列進行建模,建模的對象仍然是序列,樹中包含的結構信息仍然會被丟失.此外,以上代碼補全研究直接對AST的節(jié)點進行預測,這與實際的代碼補全場景并不完全一致.在實際的代碼補全任務中,需要根據(jù)程序員已寫好的代碼來預測下一個token,而AST節(jié)點和程序token并非一一對應,因此,預測AST節(jié)點并非嚴格意義上的代碼補全.并且,將代碼解析成AST之后樹中節(jié)點的數(shù)目遠遠大于源代碼中token的數(shù)目.目前,對較長的節(jié)點序列建模是一件較困難的事情.因此,在代碼補全任務中如何恰當?shù)乩肁ST信息還需要進一步思考.

      在根據(jù)自然語言生成程序的任務中,AST被用于約束生成的代碼使其符合語法規(guī)則,先生成AST再將AST轉換為源碼就可以保證生成的代碼符合語法規(guī)則.Yin等人[26]等人使用seq2seq框架完成代碼生成任務,其中編碼器對自然語言進行編碼,然后通過解碼器生成程序代碼的AST,然后再將語法樹轉換為代碼.以抽象語法樹作為中間結果,一方面縮小了生成代碼token時的搜索空間,另一方面也能使生成的代碼符合程序語言的語法規(guī)則.該模型的解碼器在生成AST節(jié)點的過程中,利用編碼器得到的特征向量以及已經(jīng)生成的節(jié)點作為上文信息,同時還考慮了當前預測節(jié)點的父節(jié)點和兄弟節(jié)點,利用這些信息來增加結果的可靠性.與該工作類似,Rabinovich等人[27]同樣也基于AST完成代碼生成任務,不同的是,該方法中還使用了有監(jiān)督的注意力機制來增強結果的可靠性.以上方法面向的都是較為簡單的程序生成任務,生成的程序較短且形式較為單一.若要生成較為復雜的代碼,其對應的AST會十分龐大.目前,生成龐大的AST仍然是一個巨大的挑戰(zhàn).以上這些方法距離生成可以直接投入工業(yè)使用的代碼還很遠.

      AST也被應用于在代碼模式檢測任務中,如代碼克隆檢測、代碼分類等.利用深度神經(jīng)網(wǎng)絡對AST進行建模得到其向量表示作為代碼的特征信息,根據(jù)該信息完成代碼模式檢測任務.在克隆檢測任務中,White等人[31]提出了基于深度學習技術的代碼克隆檢測方法,該方法將程序表示為token序列和AST節(jié)點序列,利用2個不同的RNN分別對這2個序列進行建模,以學習程序中的詞法和語法特征.該文將這2個特征相結合作為整個程序的特征向量,根據(jù)該向量判斷2個程序是否屬于一個克隆對.與該工作類似,Wei等人[32]提出了基于AST的LSTM模型來學習程序中的詞法和語法結構,該工作的目的是利用神經(jīng)網(wǎng)絡模型檢測出第4種類型的克隆,即功能相似的代碼構成的克隆對.在程序分類任務中,Mou等人[33]提出了基于樹結構的卷積神經(jīng)網(wǎng)絡,通過該網(wǎng)絡對程序AST進行建模.該方法通過網(wǎng)絡中的卷積層對抽象語法樹進行卷積計算,學習程序代碼的結構信息,并通過動態(tài)池化層來處理語法樹大小不同的問題,最終到一個能夠表示程序代碼結構特征的向量表示.論文中將該向量作為提取到的程序特征應用于程序分類和代碼模式檢測2個任務中驗證其模型的有效性.實驗結果表明該模型在POJ104類程序代碼分類任務上取得了94%的準確率,在冒泡程序檢測任務中取得了89.1%的準確率.以上模型均使用AST作為代碼的表示形式,旨在對程序中的語法和結構進行建模,并取得了較好的效果,這說明程序代碼的語法和結構在代碼模式檢測任務中不容忽視.

      在代碼注釋生成任務中,程序結構也受到了關注,近年來基于AST的模型也被用于該任務中.Hu等人[28]基于AST實現(xiàn)了代碼注釋生成,為了保留代碼中的結構和語法信息,該工作將程序解析為抽象語法樹,然后提出了一種能夠保留其結構的遍歷AST的方法,將AST轉化為節(jié)點的線性序列,然后基于seq2seq框架完成注釋生成任務.相比于基于代碼token序列的注釋生成方法,該方法取得了近10個百分點的提升.Alon等人[34]利用抽象語法樹路徑(AST path)來表示程序,通過AST路徑來表示程序的結構和語法.該方法首先將程序解析為抽象語法樹,對于程序中每個元素(變量名、方法名、表達式類型),提取與其相關的路徑,然后采用條件隨機場和word2vec這2種方法獲得該變量的表示.該方法在變量名預測、方法名預測以及表達式類型預測任務中都取得了目前最好的結果,較其他方法有較大提升.最近,Alone等人[29]又對該模型進行了改進,通過雙向LSTM對AST路徑進行建模,將該模型用于代碼摘要任務中.在生成摘要時還引入了attention機制,在生成摘要中的詞語時選擇與其最相關的AST路徑.以上模型都是直接對AST節(jié)點序列或者路徑進行建模,構建線性模型對序列化的AST進行建模,Wan等人[30]則構建了Tree-LSTM模型對AST結構進行建模得到其代碼的結構化表示,除此之外該方法還采用LSTM對源代碼token序列進行建模得到代碼的序列化表示,然后利用Tree-LSTM對代碼的AST進行建模得到代碼的結構化表示,最后將二者結合起來作為代碼的最終表示,根據(jù)該表示完成代碼注釋生成任務.在生成注釋時引入了強化學習機制緩解exposure bias(即模型的解碼器部分在訓練過程中輸入的數(shù)據(jù)來自真實的樣本(groundtruth),采用最大似然估計算法來預測下一個單詞;而在測試時,每一時刻的輸入來自前一時刻的輸出.一旦前面的單詞生成錯誤,錯誤就會傳遞下去,使得生成結果越來越差)的問題,該方法在訓練過程中不再采用最大似然估計算法,而是直接根據(jù)生成結果的好壞計算獎勵值(reward),根據(jù)獎勵值來更新模型參數(shù),這樣就可以緩解exposure bias的問題,提升模型的性能.目前的代碼注釋生成研究大多是生成程序中某個方法的摘要,相對于完整的程序而言,方法的長度一般比較短,因此其AST也不會過于龐大,相較于代碼補全任務,在注釋生成任務中對AST進行建模相對容易一些.

      2.2.2 基于圖的程序理解模型

      圖的結構可以對程序中的數(shù)據(jù)流動關系進行建模,例如控制流圖以及數(shù)據(jù)依賴圖.圖中節(jié)點表示程序中的元素,例如程序中的token或變量[35-37]、程序中指針(pointer)的內(nèi)存地址[40];圖中的邊表示節(jié)點之間的依賴關系或數(shù)據(jù)流動情況.近年來許多程序分析的研究工作基于圖展開,通過將程序表示為圖的形式使得模型能夠更好地理解程序中變量之間的依賴關系以及程序語義.隨著深度學習的發(fā)展,基于深度神經(jīng)網(wǎng)絡的圖模型被用于程序理解相關任務中,包括程序代碼風格修正、代碼修復、程序注釋生成等.

      在代碼風格修正任務中,Allamanis等人[35]基于GGNN[40],提出了基于圖的程序表示方法,旨在學習程序中的數(shù)據(jù)依賴關系.該工作基于AST將程序表示為圖的形式,圖中每個節(jié)點表示程序代碼中的token,圖中的邊則包含了AST中的節(jié)點之間的關聯(lián)以及變量之間的數(shù)據(jù)依賴關聯(lián)關系.根據(jù)以上表示,該方法構建圖神經(jīng)網(wǎng)絡對表示為圖形式的代碼進行學習,得到代碼中各個token的特征向量表示.該方法在程序變量命名任務中達到45%左右的準確率,而在變量誤用錯誤檢測任務中能夠達到80%的準確率.通過圖來表示程序中變量之間的依賴關系也被應用于代碼修復任務中,Allamanis等人[36]提出了深度神經(jīng)網(wǎng)絡的模型,對代碼中的變量之間數(shù)據(jù)流進行建模,考慮了變量的上下文(context)及其用法(usage).該文提出了一個新的代碼修復的場景——智能粘貼(SmartPaste),將一段代碼插入到現(xiàn)有的一個程序中,然后修改插入代碼片段中的變量使其能夠符合它所插入的程序的語義,并在該任務中驗證了模型的有效性.該模型首先基于GRU得到程序中變量的上下文表示,然后基于變量在上下文中的使用情況來計算變量的用法(usage)表示,根據(jù)這2個表示來完成智能粘貼任務.

      最近,基于圖的程序理解模型也被用于程序生成和代碼模型檢測中.Brockschmidt等人[38]在程序AST上增加相應的邊構建程序圖,然后構建圖神經(jīng)網(wǎng)絡[40]對程序的結構和數(shù)據(jù)流進行建模完成程序生成任務.Ben-Nun等人[39]提出了一種基于圖和代碼中間表示(intermediate representation)的程序向量表示inst2vec,該表示是語言無關和平臺無關的.該文首先通過編譯器LLVM對代碼進行編譯得到代碼的中間表示(LLVM IR),在該表示中,不包含數(shù)據(jù)流和控制流信息.為了對代碼中的數(shù)據(jù)流和控制流進行建模,作者將數(shù)據(jù)流和控制流信息引入已經(jīng)得到的中間表示中,構建了上下文流圖(contextual flow graph, XFG),然后基于該圖構建循環(huán)神經(jīng)網(wǎng)絡得到向量表示.在訓練時該模型采用與skip-gram模型相同的方式來預測上下文語句,得到最終的程序向量表示.該向量在程序理解任務中取得了較好的效果,其中,在程序分類實驗中準確率超過了當時最好的模型TBCNN,達到了目前最高的準確率.

      在代碼注釋生成任務中,基于圖的程序表示方法也被采用.Fernandes等人[37]提出了將基于序列和圖的模型相結合的程序表示方法.該方法首先通過雙向LSTM對程序的token序列進行編碼,得到每個token的向量表示.然后構建圖神經(jīng)網(wǎng)絡對程序中的數(shù)據(jù)流和控制流進行建模,將雙向LSTM模型中得到的每個token的向量作為圖中節(jié)點的初始值.然后將圖神經(jīng)網(wǎng)絡得到的向量作為整個程序的表示,根據(jù)該特征向量生成代碼注釋.

      在以上模型中,圖的構建大多基于AST來完成,具體來說,他們通過在AST中增加相應的邊來表示節(jié)點之間的關聯(lián)以及變量之間的數(shù)據(jù)依賴關聯(lián)關系完成圖的構建.因此,基于圖的程序理解模型可以被理解為是基于AST的模型的擴展,由于增加了更多信息,因此基于圖的模型具有更強的建模能力.但是,基于圖的模型也存在網(wǎng)絡復雜、較難訓練的缺點,在實際應用中仍然面臨著一些挑戰(zhàn).

      2.3 基于執(zhí)行過程的程序理解模型

      程序的動態(tài)執(zhí)行過程在程序理解中也是不容忽視的一部分,在程序表示和程序生成任務中占有重要的地位.程序執(zhí)行軌跡(execution traces)是程序執(zhí)行過程中的中間結果,例如在執(zhí)行過程中調(diào)用的子程序及其參數(shù)[42],或者在執(zhí)行過程中程序中各個變量值的變化情況[43].例如Wang等人[43]對程序執(zhí)行過程中變量值的變化情況進行建模,圖3是該方法中執(zhí)行max函數(shù)過程中變量值的變化情況示意圖.圖4為Reed等人[42]的方法中生成的加法程序在執(zhí)行過程中所調(diào)用的子程序及其參數(shù).通過對程序執(zhí)行軌跡進行學習與建模,可以對程序的執(zhí)行過程有更好地理解.關于程序執(zhí)行軌跡的研究工作近年來主要集中在程序綜合任務上[42,44-46].除此之外,文獻[43]基于程序執(zhí)行軌跡構建了程序表示模型得到了程序的特征向量完成程序錯誤分類任務.表4是基于執(zhí)行過程的程序理解相關研究工作.

      Fig. 3 Variable and state traces obtained by executing function max, given arr=[1,5,3]圖3 arr=[1,5,3]時執(zhí)行max函數(shù)過程中變量值的變化情況[43]

      Fig. 4 Sub-programs and parameters invoked by addition program圖4 執(zhí)行加法程序過程中調(diào)用的子程序及其參數(shù)[42]

      在程序綜合任務中,Reed等人[42]提出了神經(jīng)程序解釋器(neural programmer-interpreters, NPI)用于表示和執(zhí)行程序.圖4所示的是該方法生成的執(zhí)行加法程序過程中調(diào)用的子程序及其參數(shù),其中,子程序包括進位(CARRY)、單位數(shù)相加(ADD1)、值的寫入(WRITE)等操作.該方法由基于循環(huán)神經(jīng)網(wǎng)絡的組合神經(jīng)網(wǎng)絡構成,包含一個任務無關的循環(huán)神經(jīng)網(wǎng)絡內(nèi)核、一個鍵值對存儲單元以及一個領域相關的編碼器.該文將程序執(zhí)行過程中的執(zhí)行軌跡作為訓練數(shù)據(jù)進行有監(jiān)督地訓練,使得模型能夠模擬程序運行過程,并利用基于棧的記憶單元對中間結果進行保存以減輕循環(huán)神經(jīng)網(wǎng)絡的記憶負擔.實驗結果表明該方法能夠生成加法、排序、3D模型旋轉等程序.Cai等人[44]對NPI模型進行了改進,提出了RNPI.該方法在NPI模型的基礎上,允許程序調(diào)用其自身,使得模型具備生成包含遞歸的程序的能力.最近,Xiao等人[45]對NPI進行了改進,提出了組合子神經(jīng)程序解釋器(combinatory neural programmer-interpreter, CNPI)來增強NPI的泛化性(universality)和易學性(learnability).該工作提出了4種組合子(combinators)來表示程序中最常見的4種模式——順序、條件、線性遞歸以及樹遞歸.其中,每一個組合子是一個“程序模板”,可以作為子程序被調(diào)用.該方法中程序子的提出減少了網(wǎng)絡運行過程中需要調(diào)用的子程序數(shù)目和復雜度,因此減輕了整個網(wǎng)絡的負擔.以上程序綜合相關研究大多只能生成簡單的程序,例如簡單運算、排序、字符串操作等,Chen等人[46]針對該問題,提出了能夠生成復雜程序的程序綜合方法,該方法能夠生成將程序解析成語法樹的解析器,即輸入程序和其對應的語法樹,該方法能夠生成一個解析器程序,生成的程序能夠將輸入的程序解析為其對應的語法樹形式,該方法基于LL(1)文法設計了一個LL機(LL機包含的指令即為程序執(zhí)行軌跡),然后利用神經(jīng)網(wǎng)絡生成執(zhí)行LL機的指令,將這些指令(執(zhí)行軌跡)作為訓練集.該模型的網(wǎng)絡結構為GRU,并且在模型中引入了強化學習策略,應用于執(zhí)行軌跡缺乏的場景中.在解析器程序生成上,該方法在其測試集上達到了100%的準確率.

      Table 4 Research Onexecution Process-BasedprogramComprehension表4 基于執(zhí)行過程的程序理解相關研究工作

      除了程序綜合任務,基于執(zhí)行過程的程序理解模型也被用于程序錯誤分類任務中.Wang等人[43]認為程序執(zhí)行軌跡能夠更準確地表達程序的語義,因此設計了基于程序執(zhí)行軌跡的程序表示方法.該方法將程序執(zhí)行過程中各個變量的取值變化情況作為程序執(zhí)行軌跡.如圖3所示,圖3(b)列出的即為圖3(a)程序執(zhí)行過程中變量max_val值的變化情況.然后,該文構建了基于GRU的模型對程序執(zhí)行軌跡序列進行建模,得到程序的特征向量表示.在程序錯誤分類任務上,該方法相較于基于token和AST的模型取得了巨大的提升.

      盡管程序的執(zhí)行軌跡可以更好地表達程序的動態(tài)執(zhí)行過程及其語義,但程序的執(zhí)行軌跡數(shù)目往往十分巨大,尤其在一些較為復雜的程序中.目前的工作所使用的程序數(shù)據(jù)都較為簡單,若要對復雜程序的執(zhí)行軌跡進行建模,則是一件十分困難的事情,這也是該方法的局限性.

      2.4 模型對比分析

      本節(jié)對3種不同程序理解模型進行對比分析.表5列出了不同模型的主要應用、技術及其面臨的挑戰(zhàn).如表5所示,基于序列的程序理解模型針對序列化的程序進行建模,主要被應用于代碼補全、程序注釋生成以及代碼檢索等任務中,采用的技術主要為基于序列的深度學習模型,包括LSTM,GRU,CNN等.將程序表示為線性序列導致程序中的結構信息未被充分利用.此外,在序列較長時,模型無法對較長的序列信息進行充分建模.基于結構的模型主要對程序語法樹或者程序數(shù)據(jù)流圖、控制流圖等進行建模,主要應用于程序生成、代碼模式檢測、注釋生成等任務中,主要采用GNN,GRU,LSTM等網(wǎng)絡構建模型.與基于序列的模型類似,在對AST進行建模時,同樣面臨著長依賴的問題.而在對圖進行建模時存在著網(wǎng)絡復雜、較難訓練的缺點.基于執(zhí)行過程的程序理解模型對程序的執(zhí)行軌跡進行建模,主要被應用于程序綜合中,采用LSTM,GRU等網(wǎng)絡來構建模型.目前該模型處理的都是較為簡單的程序,例如四則運算、排序、字符串操作等.生成可以直接投入工業(yè)界使用的程序仍是目前研究的一大難點.此外,程序軌跡的數(shù)目往往十分龐大,尤其是在一些較為復雜的程序中,直接對其進行建模也是目前面臨的難點之一.

      Table 5 Comparison of Different Program Comprehension Models表5 不同程序理解模型對比

      3 相關應用

      在程序分析中,程序理解起著至關重要的作用.在本節(jié),將介紹基于深度學習的程序理解在軟件工程和程序分析中的相關應用.

      3.1 代碼補全

      代碼補全是IDE(例如Eclipse,IntelliJ,Visual Studio等)中使用頻率最高的功能[47],它有效地幫助程序員預測代碼的類名、方法名、關鍵字等,提高了程序開發(fā)的效率并減少了編碼過程中的拼寫錯誤.在該任務中,代碼的理解與表示至關重要.傳統(tǒng)代碼補全方法利用靜態(tài)類型信息結合各種啟發(fā)式規(guī)則來決定要預測的Token,例如方法名、參數(shù)等.目前基于深度學習技術的代碼補全相關研究大多通過構建語言模型對已有部分代碼(context)進行建模,根據(jù)其特征向量來預測接下來最可能出現(xiàn)的token.學術界針對如何表示已有的部分代碼提出了各種各樣的模型,其中RNN,CNN等被廣泛應用于代碼補全任務中[13-14,24-25],包括了基于token級別和基于AST級別的模型.

      相較于傳統(tǒng)基于統(tǒng)計和規(guī)則的方法,基于深度學習的代碼補全模型通過深度神經(jīng)網(wǎng)絡對代碼token序列或者AST進行建模,能夠充分挖掘代碼中蘊含的特征信息.因此,在代碼補全任務中基于深度學習的模型能夠取得更高的準確率,且模型的實現(xiàn)較為簡單.

      3.2 代碼注釋生成

      在軟件工程中,軟件維護占據(jù)了90%的軟件開發(fā)資源.研究表明:給軟件代碼添加注釋可以幫助開發(fā)人員更有效地理解相關代碼背后的語義,有利于提升代碼的可讀性和軟件的可維護性[48-50].早期關于代碼注釋生成的研究大多基于人工定義的規(guī)則或模板,這類方法根據(jù)規(guī)則抽取代碼中對應的內(nèi)容,并填入定義好的模板中,獲得代碼對應的摘要[51-52].基于模板的方法,通常需要對不同類型的代碼進行模板定制,需要消耗大量的人力;此外,當代碼中的方法名、變量名等命名不規(guī)范時,抽取式的方法很難得到有效的注釋內(nèi)容.近幾年來隨著深度學習的發(fā)展,基于seq2seq框架的模型被用于代碼注釋生成[17-18,29].這些模型首先將代碼token序列或者AST編碼為特征向量,然后根據(jù)該向量逐個生成注釋中的詞語.在生成注釋時還利用了注意力機制選擇代碼中與當前生成的詞語最相關的內(nèi)容.

      基于深度學習的程序注釋生成方法運用深度神經(jīng)網(wǎng)絡對代碼中包含的知識進行挖掘,得到其特征向量表示.相較于基于模板的注釋生成方法,基于深度學習的方法能夠生成更加豐富的注釋內(nèi)容,且不需要人為地針對不同類型代碼制定規(guī)則,模型具有更強的可擴展性,也極大地節(jié)省了人力資源.

      3.3 代碼風格修正

      除了程序語言自身的語法約束之外,代碼風格也是約束程序的方式之一,例如代碼格式、命名風格等.風格規(guī)范的代碼有利于代碼的理解、查詢與調(diào)試[53].傳統(tǒng)方法基于規(guī)則通過對代碼進行語法分析來進行代碼風格檢查,例如Checkstyle[注]http://checkstyle.sourceforge.net/工具.近年來隨著深度學習技術的發(fā)展,利用自動化方法來修正代碼風格開始被研究人員關注.目前基于深度學習的代碼風格的研究主要包括變量名、函數(shù)名和類名的預測(重命名)、代碼格式修正等.這些工作利用CNN,GGNN等網(wǎng)絡得到待修正代碼的特征向量表示[16,35],根據(jù)這些向量表示進行風格修正.

      在大量數(shù)據(jù)的支持下,利用深度學習技術構建神經(jīng)網(wǎng)絡對待修正代碼進行建??梢宰詣踊剡M行代碼風格修正,省去了傳統(tǒng)方法中人為制定語法檢查規(guī)則的繁瑣步驟,簡單且有效.

      3.4 代碼搜索

      代碼搜索是軟件開發(fā)過程中必不可少的一項操作,基于自然語言查詢語句生成符合其描述的代碼片段近幾年來受到了學術界的關注.與程序生成任務類似,代碼搜索任務同樣需要同時具備自然語言和程序的理解能力.早期的代碼搜索相關研究基于信息檢索(information retrieval, IR)技術[54-55],通過相似度匹配等算法來進行代碼搜索.隨著深度學習技術的廣泛應用,近幾年來基于深度學習技術被應用于代碼搜索的研究中[19,21].他們利用深度神經(jīng)網(wǎng)絡分別對自然語言和代碼進行建模得到其向量表示,在模型訓練過程中將自然語言查詢語句與其對應的代碼的向量表示映射到相近的向量空間中.在測試時,根據(jù)自然語言查詢語句,在向量空間中搜索與其最相近的代碼向量,得到對應的代碼.

      傳統(tǒng)代碼搜索方法基于信息檢索中的相似度匹配方法來匹配自然語言和代碼,只能根據(jù)關鍵詞匹配等對較低層次的特征進行搜索.而運用深度神經(jīng)網(wǎng)絡得到代碼和查詢語言的向量表示然后對向量之間的空間距離進行優(yōu)化能夠挖掘更高層次的特征,模型可以搜索出更加多樣化的結果.

      3.5 程序自動生成

      根據(jù)需求(輸入輸出樣例或者自然語言描述)自動生成程序近幾年來引起學術界廣泛關注.其中,基于輸入輸出樣例生成程序的任務又被稱為程序綜合.在程序自動生成任務中,需要同時具備對需求和對程序的理解能力,因此程序自動生成也是程序理解的一個重要應用場景.傳統(tǒng)方法基于語法規(guī)則匹配等方式完成該任務[56-57].近年來,許多研究者利用深度學習方法對程序自動生成進行了探索.

      在根據(jù)自然語言描述生成對應代碼的任務中,現(xiàn)有方法主要可分為2類:基于抽象語法樹以及基于程序圖的程序生成方法.其中,基于抽象語法樹的程序生成方法[26-27]利用AST約束生成的代碼符合語法規(guī)則;基于圖的程序生成模型[38]則是在程序AST上增加相應的邊構建程序圖,然后構建圖神經(jīng)網(wǎng)絡對程序的結構和數(shù)據(jù)流進行建模.此外,Murali等人[58]提出了基于代碼骨架(sketch)的程序生成方法,可根據(jù)API生成代碼.該方法根據(jù)Java語言的語法定義了程序骨架,在代碼生成任務中先生成代碼骨架,然后將骨架轉換為代碼.

      在程序綜合中,Reed等人[42]提出了基于深度學習的程序綜合方法,構建了神經(jīng)程序解釋器(NPI)來表示和執(zhí)行程序.此后,許多研究工作基于NPI展開,對其進行了改進[44-45].此外,Balog等人[59]提出了基于深度神經(jīng)網(wǎng)絡的程序綜合方法,該方法可生成簡單的程序,這些程序是由大小為34的領域特定語言(domain specific language, DSL)語句集合中的元素組合而成.給定輸入輸出樣例,該方法通過將深度學習與傳統(tǒng)的基于搜索的程序綜合方法相結合,該方法能夠生成由DSL語句組合而成的程序.較傳統(tǒng)方法,該方法實現(xiàn)效率更高.

      目前程序生成研究主要面向生成簡單的程序,例如四則運算、排序、字符串操作等,目前已取得較高的準確率.相較于傳統(tǒng)的程序生成方法,基于深度學習的方法基于已有數(shù)據(jù)樣例構建神經(jīng)網(wǎng)絡來挖掘輸入數(shù)據(jù)和生成的代碼中隱含的對應關系,極大地減少了對人的依賴,在簡單程序的生成任務中能夠取得較高的準確率.但是,在復雜程序的生成方面目前相關研究較少,是一個重要的未來研究方向.

      4 問題與挑戰(zhàn)

      近幾年來,深度學習逐漸被應用于包括程序理解在內(nèi)的各個領域,并且取得了一定的成就.由于程序自身復雜的特性以及程序理解任務的復雜性,基于深度學習的程序理解研究中仍然面臨著以下問題與挑戰(zhàn).

      4.1 數(shù)據(jù)集的獲取

      數(shù)據(jù)集是利用深度學習完成程序理解任務的關鍵,規(guī)范、高質量的數(shù)據(jù)集更有利于深度神經(jīng)網(wǎng)絡的學習.在圖像識別和自然語言處理中,有許多公開的數(shù)據(jù)集供研究者展開研究.然而,在程序分析領域,公開的高質量數(shù)據(jù)集十分稀缺,許多研究者需要自己構造數(shù)據(jù)集來完成相應的程序理解任務,這導致了訓練語料的質量參差不齊,給模型的訓練與優(yōu)化帶來了額外的噪聲.此外,相同的任務中,也存在各種各樣的數(shù)據(jù)集,這對于不同方法之間的對比和評估帶來很大的不便.因此,如何獲取統(tǒng)一規(guī)范的高質量程序語料庫是基于深度學習的程序理解中的一項挑戰(zhàn).

      4.2 程序的表示

      目前的程序理解研究中,程序的表示大多都只采用某一種表示方式,例如程序token序列級別的表示[13,16]、AST節(jié)點序列表示[24-25]、程序中的數(shù)據(jù)流[35-36]、程序執(zhí)行軌跡[42-43,46]等.這些信息分別表示了程序的不同特性,例如程序的統(tǒng)計特性、結構性、語義等,人們根據(jù)任務需求選用一種表示方式對程序的某種特性進行建模.然而,這些不同的表示之間的差距較大.因此,現(xiàn)有的程序表示方法的泛化性較差,適用的任務范圍較小,很難遷移到其他任務中.若能設計更加泛化的程序表示方式,就可以構建更加通用的程序理解模型,這也是程序理解面臨的一項挑戰(zhàn).

      4.3 自定義標識符的處理

      由于程序中存在著大量用戶自定義標識符,因此在基于深度學習的程序模型中,構建的詞表往往非常大.即使如此,還是無法覆蓋程序中全部的token,仍有許多詞表之外的詞(OoV)出現(xiàn).這給程序的理解帶來了很大的影響.為了解決該問題,Cummins等人[12]構建了基于字符級別的語言模型對程序進行建模,但直接對字符序列進行建模會丟失程序的token以及API所表達的語義;Bhoopchand等人[14]和Li等人[24]構建了基于指針網(wǎng)絡的模型以一定概率選擇上文中的token來表示后文可能出現(xiàn)的OoV詞語.但是該方法并不能處理未出現(xiàn)過的OoV詞.以上方法并沒有從本質上解決自定義標識符的問題.因此,如何解決基于深度學習的程序建模中OoV的問題也是未來的一個研究重點.

      4.4 模型的有效性分析

      目前的程序理解任務在數(shù)據(jù)來源、實驗方式以及評價方法等方面存在很大的差異,難以對不同方法的有效性進行比較.一方面,缺乏通用的測試基準(Benchmark),無法對各種程序理解模型進行直接對比;另一方面,當前的評估指標大多參照自然語言處理任務中使用的評價指標(例如BLEU),而這些評價指標是否能直接用于評價程序理解模型還有待于進一步驗證.因此,如何針對程序理解建立具有普適性的測試基準和評價度量體系也是程序理解研究中面臨的一項挑戰(zhàn).

      5 總 結

      程序理解是軟件開發(fā)與維護中的重要活動,在軟件工程中占據(jù)著重要的地位.近幾年來,深度學習技術的發(fā)展和互聯(lián)網(wǎng)中大量高質量代碼的涌現(xiàn)為研究者們提供了利用大規(guī)模代碼中包含的知識來解決程序理解相關問題的新途徑.本文對近年來基于深度學習的程序理解研究工作進行了綜述,對這些工作的原理和技術進行梳理與總結,最后對目前程序理解研究中存在的問題與挑戰(zhàn)進行討論.基于深度學習的程序理解是一個新興的研究方向,具有重要的研究意義和廣闊的發(fā)展前景.

      猜你喜歡
      代碼向量程序
      向量的分解
      聚焦“向量與三角”創(chuàng)新題
      試論我國未決羈押程序的立法完善
      人大建設(2019年12期)2019-05-21 02:55:44
      創(chuàng)世代碼
      動漫星空(2018年11期)2018-10-26 02:24:02
      創(chuàng)世代碼
      動漫星空(2018年2期)2018-10-26 02:11:00
      創(chuàng)世代碼
      動漫星空(2018年9期)2018-10-26 01:16:48
      創(chuàng)世代碼
      動漫星空(2018年5期)2018-10-26 01:15:02
      “程序猿”的生活什么樣
      英國與歐盟正式啟動“離婚”程序程序
      向量垂直在解析幾何中的應用
      东港市| 郴州市| 营口市| 峡江县| 镇坪县| 沙坪坝区| 龙海市| 师宗县| 莎车县| 新干县| 梁河县| 永定县| 涿鹿县| 崇明县| 彭州市| 汤阴县| 项城市| 女性| 道孚县| 晋江市| 博湖县| 株洲县| 大兴区| 海丰县| 两当县| 盱眙县| 武平县| 五家渠市| 东山县| 丁青县| 秀山| 巴马| 禹城市| 双峰县| 克拉玛依市| 武夷山市| 通渭县| 屏南县| 蒙城县| 响水县| 西和县|