李睿 趙逢禹 劉亞



關鍵詞:代碼注釋;類注釋模板;類原型;雙編碼器;深度學習
中圖分類號:TP311 文獻標志碼:A
0 引言(Introduction)
在許多軟件系統中,代碼源文件的注釋經常出現不完整、過時甚至缺失等情況,對這些系統代碼進行維護與完善時,開發人員需要花費大量時間理解代碼[1]。當代碼內部有較準確的注釋文本時,開發人員可以通過瀏覽注釋文本快速理解相關代碼片段的含義,從而節省維護時間,提高維護質量。
自動代碼注釋生成技術是用于提高代碼可讀性和可維護性的有效方法,目前針對代碼注釋自動生成的研究大致分為以下兩類:基于模板的注釋自動生成和基于深度學習的注釋自動生成。基于模板自動生成的代碼注釋可讀性較高,但缺乏對具體代碼結構信息的獲取能力,而基于深度學習的代碼注釋生成研究大多應用于方法粒度,對于復雜的類結構的注釋生成比較困難。
針對上述兩類自動代碼注釋生成技術存在的問題,本文結合模板與深度學習技術,提出一種為類自動生成注釋的方法,首先確定當前類所屬的類原型,并選擇對應類注釋模板,提取類中的信息填充到模板中,其次針對類中方法的注釋生成問題,提出構建一種基于注意力機制的雙編碼器模型,實現代碼到注釋的映射,最后通過實驗驗證了本方法的可行性與實際應用效果。
1 相關研究(Related research)
基于模板的注釋生成方法,首先需要預定義一組啟發式規則,其次提取代碼的關鍵信息并通過啟發式規則生成自然語言描述。HILL等[2]提出一種基于軟件單詞使用模型(SoftwareWord Usage Model,SWUM)分析Java方法簽名的方法,為Java方法生成自然語言注釋。SRIDHARA等[3]在HILL等研究的基礎上進一步考慮了方法體內含有的代碼,提出一種基于啟發式規則的方法為方法代碼生成注釋,該方法主要分為內容選擇和注釋生成兩個階段。MORENO等[4]將關注的代碼粒度從方法級別提升到類級別,首先確定類和方法的原型,其次通過結合原型信息與預先定義的基于方法和數據成員訪問級別的啟發式規則,并通過現有的文本生成工具對Java類生成描述性摘要。基于規則模板生成的代碼注釋容易理解,但受限于模板只能為特定的代碼結構生成注釋,對于模板之外的代碼無法靈活地生成有效的代碼注釋。
基于深度學習的注釋生成方法通過神經網絡對代碼中包含的信息進行挖掘,得到其特征向量表示,并通過模型進行訓練,最終得到自然語言描述。目前,大量的研究主要采用神經機器翻譯(Neural Machine Translation,NMT)模型,通過提取不同的代碼特征信息,使用不同的神經網絡結構進行訓練得到代碼注釋。IYER等[5]率先將深度神經網絡引入自動代碼摘要研究,提出代碼-描述嵌入神經網絡(Code-DescriptionEmbedding Neural Network,CODENN)方法,在長短期記憶網絡(Long-Short Term Memory,LSTM)的基礎上通過引入注意力機制構建一個端到端的學習網絡,從而自動生成代碼摘要。HUANG等[6]采用門控循環單元(Gated Recurrent Units,GRU)作為編碼器和解碼器,并為代碼塊生成注釋,GRU是對LSTM網絡的一種改進,能夠保留較長的上下文信息[7]。CAI等[8]提出使用樹形長短期記憶網絡(Tree-LSTM),通過引入語法類型信息對程序代碼進行結構化編碼,并在解碼時采用多種策略對抽象語法樹的節點進行篩選,最終生成代碼注釋。基于深度學習的自動代碼注釋方法可以較靈活地為代碼片段生成注釋,在面對復雜程序代碼時,仍然具有良好的結構學習能力,但目前大多只應用于方法粒度,針對類粒度的代碼片段無法生成較為全面的注釋。
2 類注釋生成方法(Class annotation generationmethod)
本文提出的基于類原型與深度學習為類生成注釋的方法活動圖如圖1所示,主要包括以下幾步:第一步,提取類中方法,確定類中方法原型,并通過類中方法原型的分布確定類原型;第二步,為不同的類原型選擇不同的類注釋模板;第三步,針對類注釋模板中各部分的信息設計相應的提取規則,并將提取到的信息填充到類注釋模板中;第四步,對于類中的主要方法通過深度學習模型得到方法注釋,將方法代碼注釋填充到類注釋模板中,得到完整類注釋。
2.1 類原型分類
類原型是項目設計中類的角色和責任的簡單抽象,開發人員可以通過類原型較快地了解類在系統中的一般職責。在軟件的維護和發展過程中,對類原型的準確描述是必要的,STARON等[9]驗證了類原型信息在程序理解任務中的有效性。本文首先對類的原型進行識別,確定類的職責,其次為不同的類原型選擇不同的類注釋模板。
目前,在類與方法的原型識別領域已有大量研究,文獻[10]首先提出了一種方法原型的自動識別技術,并給出了方法原型的分類法;文獻[11]在此基礎上提出一種根據方法原型分布確定類原型的方法,并給出了類原型的分類法。為了構建符合類職責的注釋模板,本文參照文獻[11]對方法原型和類原型的分類方法進行重新定義,將方法原型分類為5類,類原型分類為4類,其中方法原型分布是類原型分類的重要特征。表1給出了本文定義的方法原型分類及原型描述,表2中給出了本文定義的類原型分類、原型描述及分類規則。
在表2的類原型分類規則中,acc 表示類中訪問器類型方法的數量,mut表示類中變換器類型方法的數量,con 表示類中構造方法的數量,col 代表類中協作方法的數量,cont 表示類中控制器類型方法的數量,mtd 表示類中方法的總數。
2.2 類注釋模板
不同類原型代表不同的職責,代碼注釋主要關注的信息也不同,例如Entity類型代表實體類,重點關注繼承關系、類中屬性以及類在項目中的使用情況,由于Entity類中方法大多數為訪問器、變換器及創建方法,因此不需要對類中方法進行注釋;Boundary類型代表邊界類,多用于與其他類進行通信,因此重點關注類在項目中的使用情況和類中方法的功能;Controller類型代表控制類,主要負責處理外部對象數據,重點關注繼承關系、實現關系、類在項目中的使用情況和類中方法的功能。受篇幅限制,本文以Controller類原型為例,展示其注釋模板(如表3所示)。
2.3 類中信息提取規則
表4給出了類注釋模板中各部分注釋內容的提取規則。首先,通過代碼抽象語法樹(Abstract Syntax Tree,AST)結構提取父類、接口的實現類和類中屬性;其次,在項目中進行代碼搜索提取其子類及該類在其他類中的使用情況,將上述信息填充到預定義的類注釋模板中。類中方法是類功能的具體實現,類中方法的注釋生成是類注釋的難點。針對這一問題,本文首先識別類中的主要方法,對主要方法使用深度學習的技術建立方法代碼到代碼注釋的映射模型,通過該模型獲得方法代碼的注釋并填充到類注釋模板中,最終獲得完整的類注釋。
3 基于注意力機制的雙編碼器方法代碼注釋生成模型(A model for code annotation generation inbi-encoder method based on attention mechanism)
由于方法代碼結構復雜,包含較多的序列信息和結構信息,因此僅使用預定義規則提取,無法為方法代碼生成較為準確的注釋,而深度學習可以捕捉代碼的結構信息,并可以通過大量訓練得到從代碼到注釋的映射,本文使用深度學習技術為方法代碼生成代碼注釋。本文在經典編碼器-解碼器模型的基礎上,提出了一種雙編碼器-解碼器的方法代碼注釋生成模型,其中雙編碼器包括一個序列編碼器和一個樹結構編碼器,圖2展示了該模型網絡結構。該模型首先對數據進行預處理,在源碼文件中提取以方法為粒度的代碼,構建算法提取代碼序列和代碼抽象語法樹結構信息;其次分別將代碼序列和抽象語法樹序列的向量表示輸入各自對應的編碼器中進行訓練;最后經過注意力機制關注解碼重點,將序列向量和抽象語法樹向量進行拼接后,由解碼器解碼得到方法代碼注釋序列。
3.1 序列編碼器
在經典編碼器-解碼器模型中,編碼器通常使用循環神經網絡(RNN)按照時序提取代碼序列特征,據目前已有的研究可知,當序列較長時,基于遞歸機制的RNN可能存在梯度消失或者梯度爆炸問題。GERS等[12]提出了一種長短期記憶網絡(LSTM),相對于RNN而言,LSTM在處理長序列數據時表現更為出色。因此,本文選擇LSTM 作為雙編碼器中的序列編碼器處理代碼序列信息。
為了構造序列編碼器中的輸入方法代碼序列,首先利用Antlr4語法分析器生成工具將方法代碼轉化為抽象語法樹(AST),其次對方法AST進行前序遍歷,組成代碼序列。算法1給出了提取方法代碼序列的算法。
通過自底向上的遍歷,最終獲取根節點的輸出作為樹編碼器的輸出,在圖2中通過結構向量ht 表示該向量。
3.3 解碼器
本文采用融合注意力機制的LSTM 作為解碼器,首先將序列編碼器輸出的序列表示向量hs 和樹編碼器輸出的結構表示向量ht 分別通過注意力機制進行加權求和重新計算權重。其次將注意力機制篩選后的向量進行拼接,得到綜合編碼向量作為解碼器的輸入向量。至此,解碼器就同時融合了代碼的序列信息和結構信息。
4 實驗結果與分析(Experimental results andanalysis)
為了全面評估本文提出的基于類原型與深度學習為類自動生成注釋的方法,將從以下兩個方面進行實驗驗證:一是評估本文提出的基于注意力機制的雙編碼器方法代碼注釋生成模型的性能;二是評估本文提出的結合類原型與深度學習的類粒度注釋生成的準確性。
4.1 數據集
本文采用文獻[14]提供的Java-med數據集進行實驗,該數據集收集于軟件項目托管平臺GitHub,包括1 000個Java頂級項目。該數據集包含約400萬個方法,涵蓋模型需要的源代碼信息和注釋信息。本文將數據集按照8∶2的比例劃分訓練集和測試集,其中訓練集用于訓練雙編碼器-解碼器模型,測試集用于評估雙編碼器-解碼器模型性能及Java類注釋生成效果。
4.2 評估指標
本文從兩個方面評估本文提出方法的應用效果。對于方法代碼注釋自動生成的雙編碼器-解碼器模型的評估問題,采用BLEU[15]、ROUGE[16]和METEOR[17]評估生成方法代碼注釋的質量,這些指標廣泛應用于機器翻譯領域。其中,BLEU表示生成句子和真實句子的相似程度,更側重于準確率,本文選擇其中的BLEU-4作為評估指標;ROUGE與BLEU類似,但更加關注召回率,ROUGE-L基于生成句子和真實句子的最長公共子序列共現統計召回率和準確率;METEOR引入了同義詞匹配,在計算得分時考慮了詞性變換和同義詞的情況。三種機器翻譯性能評估指標與生成的自然語言注釋質量呈正相關。
針對類粒度注釋的準確性與完整性評估問題,由于類粒度注釋生成的相關研究與通用數據集較少,因此本實驗采用具有Java軟件領域開發經驗的工程師對類注釋進行人工方式的準確性評估。
4.3 實驗結果分析
4.3.1 方法粒度的注釋生成模型性能對比
本文提出的雙編碼器-解碼器模型基于Python編程語言和PyTorch深度學習框架實現,在訓練過程中,使用Adam作為優化器,初始學習率設置為0.001。其中,雙編碼器和解碼器均具有兩個隱藏層,隱藏狀態設為256維,嵌入單詞的維度也設為256維。
為了評估本文在方法粒度的注釋自動生成中提出的雙編碼器-解碼器模型的有效性,選用方法注釋生成領域中常見的注釋生成模型進行實驗對比。
(1)Seq2Seq模型+注意力機制[5]。Seq2Seq模型將源代碼序列信息輸入LSTM中進行編碼,引入注意力機制,最終由解碼器進行解碼獲得注釋。
(2)Code2Seq模型+注意力機制[14]。Code2Seq模型通過使用抽象語法樹中組合路徑的集合表示代碼片段,使用BiLSTM作為編碼器,并在解碼時使用注意力機制選擇相關的路徑最終解碼獲得注釋序列。
(3)Tree2Seq模型+注意力機制[18]。Tree2Seq模型使用Tree-LSTM作為編碼器,將源代碼轉化為抽象語法樹結構,使用編碼器自下而上遞歸對AST節點進行編碼,然后由基于注意力機制的解碼器進行解碼。
表5展示了4種模型在選定的Java數據集上的實驗評估結果對比。從表5中可以看到,本文提出的雙編碼器-解碼器模型的BLEU-4分數達到35.2,并且在各項指標上均優于其他三種對照方法。相對于其他三種模型,本文模型既融合了代碼的序列信息,又融合了代碼的結構信息,同時引入了注意力機制(Attn),能充分地獲取代碼信息,進而提升了注釋生成效果。
4.3.2 類粒度的注釋生成性能評估
為了評估本文結合類原型與深度學習生成類注釋的性能,從類原型識別的準確性及類注釋的準確性兩個方面進行評估。首先在測試數據集中選擇部分類,通過人工識別方式進行類原型分類;其次使用本文提出的類原型識別方法對這些類進行原型識別。從表6可以看出,本文提出的類原型識別規則能較準確地識別類的原型。
為了評估生成類注釋的準確性,評估者閱讀選定類的主要功能和結構并給出對相應類的注釋描述,然后與本文生成的類注釋進行對比。表6展示了對不同類原型的類注釋準確性的評估,評估者認定當類原型為實體類和邊界類時,本文方法能較準確地生成符合該類職責的注釋,對于類中方法數量較少的控制類能夠較為準確地描述類的使用情況,但對于類的功能描述信息較少,對于大類(Large class)能較為準確地描述類中具體方法的功能,從而反映類的功能。
4.4 示例展示
本文首先通過確定類的原型選擇類注釋模板,其次提取類中信息填充到模板中,最終生成完整的類注釋,表7展示了實驗中類原型為Controller類最終生成的類注釋結果。
5 結論(Conclusion)
本文通過結合類原型與深度學習技術,提出一種為類生成注釋的方法,首先通過確定類原型選擇類注釋模板,其次提取類中的信息填充模板,對于類中的方法使用帶有注意力機制的雙編碼器模型訓練后得到方法注釋,最終得到完整的類代碼注釋。實驗表明,本文在方法粒度中提出的雙編碼器模型在性能和效果上優于對比模型,完整的類粒度的注釋經人工評估后確定具有較高的準確性。未來,可以結合信息搜索以及其他深度學習方法,融合更多的代碼信息與注釋文本,進一步提高自動生成類注釋的質量。
作者簡介:
李 睿(1999-),女,碩士生。研究領域:自然語言處理,深度學習。
趙逢禹(1963-),男,博士,教授。研究領域:計算機軟件與軟件系統安全,軟件工程與軟件質量控制,軟件可靠性。
劉 亞(1983-),女,博士,副教授。研究領域:信息安全,密碼學。