使用從細粒度更改中進行統計學習的 API 代碼推薦

使用從細粒度更改中進行統計學習的 API 代碼推薦

引用

Anh Nguyen and Michael Hilton and Mihai Codoban and Hoan Nguyen and Lily Mast and Eli Rademacher and Tien Nguyen and Danny Dig. API Code Recommendation using Statistical Learning from Fine-Grained Changes. In Proceedings of the 24th International Symposium on Foundations of Software Engineering, 2016, 511-522.

摘要

學習和記憶如何使用 API 是一件困難的事情。儘管代碼補全工具能夠推薦 API 方法,但是瀏覽冗長的 API 方法名列表及文獻是一件苦悶的工作,並且用戶經常對數量過多的信息望而卻步。

我們提出了一種新的 API 推薦方法,它利用重複代碼更改的預測能力為開發人員提供相關 API 的推薦。我們使用的方法及工具 APIREC 是通過對細粒度代碼更改及這些更改所在的上下文進行統計學習從而實現的。我們的評估結果顯示,在 59%的情況下,APIERC 能夠將正確的推薦 API 置於首位,在 77%的情況下,能將其置於前 5 位。這相對於之前最先進的方法有著極大的改善:其在首位的準確度上有 30-160% 的提升,在前 5 位上有 10-30% 的提升。我們的結果還顯示,即使只用從 50 個開源項目獲得的一次性、最小訓練數據集,APIERC 也能展現出色的性能。

定義

使用從細粒度更改中進行統計學習的 API 代碼推薦

使用從細粒度更改中進行統計學習的 API 代碼推薦

1. 原子更改:一個(細粒度)的原子更改可以表示為(,,)。實驗中用 AST 表示源代碼,以防止格式更改對推薦結果的影響。對於更改的文件,通過比對更改前後的 AST 獲取細粒度更改。主要採用的工具是 GumTree。 操作類型可歸納為:change、add、delete 和 move。AST 節點類型表示 Java 抽象語法樹的節點,而標籤表示 AST 節點所含的文本信息。圖 1 顯示了一次代碼更改,而表 1 是對其 AST 中原子更改的歸納。

2. 交易:在一次提交中,更改文件中的所有原子更改被收集在交易中。這些更改是以袋而不是列表的方式存儲,因為同一更改模式下,不同的編程者所寫的原子更改也是不一樣的,如果建立嚴格的順序,將會難以統計學習用於推薦的模式。此外,由於這些代碼更改都是從代碼倉庫中已提交的更改中收集的,所以無法得知它們編輯的順序。

3. 更改上下文:它表示在同一編輯會話中,發生在當前更改請求之前的細粒度更改組成的更改袋。它們對於當前方法的推薦十分有用,除此之外,實驗中還按這些更改對編程元素的影響賦予它們權值,其與當前代碼元素的數據依賴性越高,權值也就越大,目前只涉及變量的定義和使用,以及相同變量的不同方法調用間的依賴。

4. 代碼上下文:它表示代碼記號的集合,這些代碼記號處於當前編輯處之前的一段距離內,該距離長短取決於代碼記號自身。實驗中代碼記號從 AST 上獲取。其原理在於:推薦請求點周圍的一些代碼即使不發生更改,也經常與期望的 API 調用同時出現,因而這些代碼上下文對推薦正確的 API 有益。實驗中忽略分隔符與標點符號。

實驗中對於更改上下文和代碼上下文都要考慮到它們的距離和範圍,對於更加接近推薦請求點的上下文,會賦予其更高的權重。實驗中距離以記號數為單位進行測量;而對於範圍,實驗中賦予方法作用域內的上下文更高的權重。

模型介紹

該模型的目的在於:由先於當前更改 c 的更改上下文 C 中給定的代碼更改,以及 API 請求處周圍的代碼上下文 T 中給定的代碼記號,能夠推斷出一個更改 c 出現在請求處的可能性分數。其中 c 的形式為,而 APIREC 的任務是預測 methodName。

一個更改 c 的出現可能性分數 Score(c, (C, T))是關於 c、C 和 T 的函數。為了進行計算,作者假設更改上下文與代碼上下文對於下一記號出現的影響是相互獨立的,分別記為 Score(c, C)和 Score(c, T)。Score(c, (C, T))是 Score(c, C)與 Score(c, T)的賦權線性組合:

使用從細粒度更改中進行統計學習的 API 代碼推薦

使用從細粒度更改中進行統計學習的 API 代碼推薦

訓練和推薦

訓練:

公式(3)和(4)APPREC 需要學習三種參數:

使用從細粒度更改中進行統計學習的 API 代碼推薦

推薦:

當上述所有的參數都訓練好了,便可以使用公式(3)與(4)以及訓練過程中獲得的代碼及更改出現數量來估算更改 c 發生的可能性。實驗中計算了所有在詞彙表中並滿足以下條件的候選更改的可能性:1、該更改是對方法調用的增添;2、它至少在出現在一個交易中的車 c1,c2,c3,c4....cn 現在一個交易中的的 t1,t2,t3,t4.....,tn 至少一個記號中。最終將候選項按分數排序。表 2 顯示的是圖 1 所示代碼更改中記號 result 後的代碼補全實驗結果:

使用從細粒度更改中進行統計學習的 API 代碼推薦

其中 c1,c2,c3....,c13 表示更改上下文,t1,t2,....,t6 表示代碼上下文。所有滿足條件 1 和 2 的候選方法調用 c 被列在右列,包括:add、remove、contains、addAll 和 clear。表 2 中的分數表示可能性分數 Score(c, C)(表示 ci 出現在更改上下文時更改 c 出現的可能性)與 Score(c, T)(表示記號 ti 出現在代碼上下文時 c 出現的可能性),它們分別通過公式(3)和(4)計算得出。考慮到所有因素如距離、範圍以及數據依賴性,在所有候選項的聯合得分中,add 得到了最高分並且獲得了最高排名。從結果看來也是有理可循的,因為編程者經常在循環中使用 add 將元素加入容器中。

語料庫介紹:

大語料庫:使用 50 個從 Github 隨機選取的具有很長開發歷史的 Java 項目構成,將其所有提交中的原子更改使用 GumTree 提取了出來

社區語料庫:較小的語料庫,僅包含 8 個 Github 上的項目,處理方式與大語料庫相同。

實證評估:

1、準確性:

社區版:在這項實驗中,APIREC 使用大語料庫進行訓練,並在社區語料庫上進行測試。實驗中作者復現了 n-gram API 、Bruch、GraLan 等模型並使用相同的語料庫進行訓練和測試,並通過兩種不同的設置進行比較:

1)、在語料庫的所有庫中的 API 上進行比較:

考慮到 APIREC 無法推薦訓練集上未出現過的 API 調用 ,而這些 API 可能會在測試集上出現,為了公平比較,實驗中測量的是詞彙表內的準確率。如圖 3 ,實驗

使用從細粒度更改中進行統計學習的 API 代碼推薦

結果表明 APIREC 的首位準確率達到了 44.2-59.5%,相較於其他工具有 30-160%的提高,在前五位的準確率達到了 83.6%,相較於其他工具有 20-30%的提高。

2)、在 JDK 庫中的所有 API 上進行比較:

在這一環節中,只針對 JDK 中的 API 庫進行推薦準確率評估。實驗結果表明 APRREC 在 JDK 中 API 的推薦準確率十分高,其首位準確率達到了 56.4-74.3%,在前五位的準確率達到了 76.1-89.8%,並且在任何項目上都遠遠高於其他工具(其首位準確率比 n-gram 高 200%,比 Bruch 高 170%,比 GraLan 高 120%)。

項目版:這項實驗的目的在於評估企業文化對 APIREC 準確率的影響。為了便於比較,實驗中選取了企業版中的測試項目,並在相同的項目上進行訓練和測試。對於每一個項目,將其所有的提交按時間排序,並將最近的 10%的提交用於推薦,其餘的用於訓練。實驗結果表明,雖然 APIREC 的表現仍然好於其他工具,但是不管是在通用 API 還是特定(JDK)API 上, 它的準確率都明顯低於社區版。

用戶版:在這項實驗中,我們評估了僅在一個用戶的所有提交上訓練 APIREC 時的準確率。實驗中選取了一位提交數最多的用戶,其提交在各項目中佔比 10-28%,為便於比較,實驗項目的選用與數據集的劃分都與項目版相同。實驗結果表明,雖然其準確率仍低於社區版(可能是訓練數據較少),但是有趣的是,用戶版的準確率總體上高於項目版。這提醒我們:相比與將整個項目作為訓練集,如果將代碼作者納入考慮,可能會通過更少的訓練數據獲得更精確的結果。

2.靈敏度分析:

更改上下文與代碼上下文:實驗測量了預測點前的更改的數量以及代碼記號的數量對推薦結果的影響。實驗中隨機選取了社區語料庫中的 antlr 項目,並改變其上下文的規模並測量了詞彙表內準確性。結果表明:增加更多的更改上下文可以與更改的高層意圖建立關聯,從而帶來更高的準確性,而代碼上下文的增加對結果增幅較小。而當增加數量超過 15 時,準確率的提高就變得十分微小了。

預測點:由於 APIREC 的推薦結果是基於預測點前的代碼及更改數的,因此從交易的 n 個更改中選擇不同的預測點將會對結果造成影響。模型在大語料庫上進行訓練,並隨機選取了社區語料庫中的 JGit 項目進行測試。實驗選取了三個不同的預測點,其結果表明預測點的後移將略微增加推薦的準確率,因為後移使得更改上下文擁有了更多的前置更改。

訓練數據的規模:實驗中選取了 6 組不同的數據集,並分別增加了 50-300 個項目。結果顯示當項目數增加時,準確率只從 57.3%提高到 58.6%。可見更大的訓練數據集確實能帶來更好的性能,但是提升非常小。這也表示 APIREC 只需要使用來自 50 個項目的最小訓練集就能獲得很好的結果。

3、運行時:

所有實驗都是使用一臺配置為 Xeon E5-2620 2.1GHz(1 線程和 32GB RAM)的計算機運行的。推薦響應時間為每次推薦小於 1 秒,因此 APIREC 十分適合在 IDE 中交互式使用。

本文貢獻

1. 方法:本文提出了一種全新的方法:通過對周圍代碼上下文的細粒度變化進行統計學習來實現代碼推薦。我們還提供了新的方向,即結合利用源代碼和細粒度變化的重複性。

2. 實現:我們通過工具 APIREC 實現了提出的方法,它能夠計算出在代碼請求處最可能被插入的 API 方法調用。

3. 實證評估:我們通過實證評估表明:APIREC 在 API 代碼補全上有著很高的準確性(59%的首位準確率,這相比於之前最先進的方法都有著 30-160%的提升)。我們的評估還表明:只用從 50 個開源項目獲得的最小訓練數據集,APIERC 就能展現出色的性能。有趣地是,我們發現比起使用一整個項目進行訓練,如果考慮到代碼的作者,甚至可以用更少的訓練數據得到更高的準確率。使用社區語料庫訓練模型比使用來自項目或單個開發人員的訓練結果更加準確。

致謝

感謝國家重點研發計劃課題:基於協同編程現場的智能實時質量提升方法與技術(2018YFB1003901)和國家自然科學基金項目:基於可理解信息融合的人機協同移動應用測試研究(61802171)支持!

本文由南京大學軟件學院 2020 級碩士生孫昱翻譯轉述。


分享到:


相關文章: