亚洲免费av电影一区二区三区,日韩爱爱视频,51精品视频一区二区三区,91视频爱爱,日韩欧美在线播放视频,中文字幕少妇AV,亚洲电影中文字幕,久久久久亚洲av成人网址,久久综合视频网站,国产在线不卡免费播放

        ?

        基于深度學(xué)習(xí)的程序理解研究進(jìn)展

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

        劉 芳 李 戈 胡 星 金 芝

        (北京大學(xué)信息科學(xué)技術(shù)學(xué)院 北京 100871) (高可信軟件技術(shù)教育部重點(diǎn)實(shí)驗(yàn)室(北京大學(xué)) 北京 100871)

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

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

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

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

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

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

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

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

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

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

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

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

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

        1 程序性質(zhì)及程序理解框架

        1.1 程序性質(zhì)

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

        1.1.1 強(qiáng)結(jié)構(gòu)性

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

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

        1.1.2 自定義標(biāo)識符

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

        1.1.3 長依賴

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

        1.1.4 可執(zhí)行性

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

        1.2 基于深度學(xué)習(xí)的程序理解框架

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

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

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

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

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

        2 程序理解的深度學(xué)習(xí)模型

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

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

        程序是由符號序列構(gòu)成的,因此我們可將程序代碼形式化地表示為字符(character)或詞素(token)序列.除此之外,程序中的應(yīng)用程序接口(application programming interface, API)序列中蘊(yùn)含著程序的功能信息,因此API序列也成為了許多研究工作的研究對象.目前已有的基于序列的程序理解研究工作主要基于構(gòu)建統(tǒng)計語言模型來學(xué)習(xí)程序的序列化表示.對于程序序列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語言模型對程序序列進(jìn)行建模[9,15].隨著深度學(xué)習(xí)的發(fā)展,近年來,基于深度循環(huán)神經(jīng)網(wǎng)絡(luò)的統(tǒng)計語言模型開始被應(yīng)用于程序序列建模中.表2列出了基于序列的程序理解相關(guān)研究工作.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        Table 3 Research on Structure-Based Program Comprehension表3 基于結(jié)構(gòu)的程序理解相關(guān)研究工作

        2.2 基于結(jié)構(gòu)的程序理解模型

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

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

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

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

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

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

        2.2.2 基于圖的程序理解模型

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

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

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

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

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

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

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

        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]

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

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

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

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

        2.4 模型對比分析

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

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

        3 相關(guān)應(yīng)用

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

        3.1 代碼補(bǔ)全

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

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

        3.2 代碼注釋生成

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

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

        3.3 代碼風(fēng)格修正

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

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

        3.4 代碼搜索

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

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

        3.5 程序自動生成

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

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

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

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

        4 問題與挑戰(zhàn)

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

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

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

        4.2 程序的表示

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

        4.3 自定義標(biāo)識符的處理

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

        4.4 模型的有效性分析

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

        5 總 結(jié)

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

        猜你喜歡
        代碼向量程序
        向量的分解
        聚焦“向量與三角”創(chuàng)新題
        試論我國未決羈押程序的立法完善
        創(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
        “程序猿”的生活什么樣
        英國與歐盟正式啟動“離婚”程序程序
        向量垂直在解析幾何中的應(yīng)用
        少妇又色又爽又高潮在线看| 亚洲国产精品久久久久秋霞影院| 97人伦影院a级毛片| 亚洲人成77777在线播放网站| 欧美大黑帍在线播放| 国产成人av在线影院无毒| 亚洲精品精品日本日本| 区一区二区三区四视频在线观看| 97久久婷婷五月综合色d啪蜜芽 | www国产亚洲精品| 国产精品99久久久久久猫咪 | 久久人妻AV无码一区二区| 日本人妻少妇精品视频专区| 午夜桃色视频在线观看| 天堂资源中文网| 99在线精品免费视频九九视| 中文字幕国产91| 国产目拍亚洲精品区一区| 精品私密av一区二区三区| 伊人久久大香线蕉av色婷婷色| 欧美怡红院免费全部视频| 久久国产欧美日韩高清专区| 久久亚洲av午夜福利精品西区| av日韩高清一区二区| 丁香美女社区| 亚洲av区无码字幕中文色| 国产小车还是日产的好| 久久精品亚洲精品国产区| 国产欧美精品一区二区三区四区| 亚洲男同志网站| 精品国产午夜久久久久九九 | 日韩精品视频免费在线观看网站| 又粗又黑又大的吊av| 无码人妻丰满熟妇片毛片| 国产自精品在线| 青青久久精品一本一区人人| 中文字幕人妻丝袜成熟乱| 午夜精品久久久久久| 久久婷婷国产精品香蕉| 久久av一区二区三区黑人| 亚洲国产精品成人久久|