微軟提出程序圖方法:從源代碼中學習,揪出惱人的Bug

做者|微軟
編譯|Debra
編輯 | Emily
AI 前線導讀在過去五年中,基於深度學習的方法已經完全改變了不少應用,例如能夠理解圖片、語音和天然語言的應用。對於計算機科學家來講,他們天然而然會提出一個疑問:計算機是否學會了理解源代碼?乍一看,這彷佛是一個微不足道的問題,由於編程語言的確被設計爲能夠被計算機所理解。可是,許多軟件 bug 的出現,實際上反映了開發者的真實心理:他們但願代碼按他們想要的方式去執行,而不是按他們寫的去執行。換句話說,小的錯別字會帶來很嚴重的後果。

更多幹貨內容請關注微信公衆號「AI 前線」,(ID:ai-front)

如下是一個簡單的例子:git

float getHeight {return this.width; }。程序員

在這個例子中存在的問題對於人類,或一個能夠理解術語「高度」和「寬度」含義的系統是顯而易見的。它的關鍵洞見是源代碼提供兩種功能。首先,它向計算機傳達應該準確執行哪些硬件指令。其次,它向其餘程序員(或六週後向做者本身)傳達程序如何工做的信息。後者是經過選擇名稱、代碼佈局和代碼註釋來實現的。經過識別兩個通訊渠道出現分歧的狀況,自動系統會指出可能存在的軟件缺陷。github

過去的程序分析主要集中在正式的、機器可解釋語義的程序上,或者它把程序視爲天然語言的一個(有點奇怪的)例子。前者這個方法來源於數學邏輯(https://www.microsoft.com/en-us/research/research-area/programming-languages-software-engineering/),須要針對每一個須要處理的新案例進行大量的工程設計工做。另外一方面,天然語言方法則涉及天然語言處理工具(https://www.microsoft.com/en-us/research/research-area/human-language-technologies/)的應用,這些工具在純粹的句法任務上運做良好,但迄今還不能學習程序的語義。編程

在 ICLR 2018 年發表的一篇新論文中,來自微軟研究院和溫哥華西蒙弗雷澤大學的研究人員提出了一種將這二者結合起來的新方法,並展現瞭如何用這種方法找出已發佈軟件中的錯誤。微信

程序圖

爲了可以從豐富的源代碼結構中學習,首先須要將它轉化爲程序圖。圖的節點包括程序的標記(即變量、運算符、方法名稱等)及其抽象語法樹的結點(定義語言語法的元素,如條件語句)。程序圖包含兩種不一樣類型的邊緣:句法邊緣只表示應該如何解析代碼,好比 while 循環和 if 塊;以及做爲簡單程序分析結果的語義邊緣。網絡


句法邊緣包括簡單的「NextToken」邊,用於表示抽象語法樹的「Child」邊,和用於將源代碼與源代碼文本中最後一次發生鏈接的「LastLexicalUse」邊。圖 1 以語句 Assert.NotNull(clazz)爲例展現了這種邊,其中與 token 對應的節點是灰色框,與程序語法的非終端對應的節點是藍色橢圓。子邊緣顯示爲藍色實心邊緣,而 NextToken 邊緣爲黑色雙邊緣。機器學習

語義邊緣包括將變量鏈接到上一次可能在程序執行中使用過的「LastUse」邊緣,「LastWrite」邊緣則鏈接到上一次寫入的變量,「ComputedFrom」邊將變量鏈接到計算值。利用程序分析工具箱中的其餘工具(例如別名和點對點分析)以及路徑條件,能夠得到更多的語義邊緣。圖 2 展現了一小段代碼中的一些語義邊緣(黑色)。編程語言


LastUse 關係以綠色邊緣顯示。所以,例如,y 與循環以前的 y 的最後一次使用以及自身相關聯。一樣,LastWrite 關係顯示爲紅色邊,所以在 while 條件中使用 x 與循環前的 x 賦值,以及循環內 x 的賦值相關聯。最後,ComputedFrom 關係由藍色邊緣表示,將變量鏈接到從中計算出來的變量。ide

句法邊緣大體對應程序員在閱讀源代碼時看到的內容。另外一方面,語義邊緣則與程序如何執行相對應。經過將這些概念結合在一張圖中,系統能夠同時從更多的信息源中學習。工具

從圖形中學習

最近,從圖形結構數據中學習引發了一些關注,由於圖形是表示數據及其關係的標準方式,例如咱們能夠用一張圖包含一個組織或藥物成分的信息。近期圖形深度學習比較成功的兩種方法有圖形卷積網絡(graph convolutional networks,卷積網絡的擴展,是圖像理解的關鍵)和門控圖形神經網絡(gated graph neural networks ,普遍用於天然語言處理的遞歸神經網絡的擴展)。

這兩種方法首先均對每一個節點進行獨立處理,以得到節點自己的內部表示(即低維空間中的向量)。隨後,重複地將每一個節點的表示與它所鏈接的節點的表示相結合(兩種方法的組合方式有所不一樣)。所以,在第一個步驟以後,每一個節點都包含其自身及其直接鄰居的信息;在第二步以後,它得到兩步以外的節點的信息,以此類推。因爲該方法的全部步驟都在(小)神經網絡上進行,所以能夠訓練它們從數據中提取與總體任務相關的信息。

尋找錯誤

學習程序圖可用於查找錯誤,例如本文開頭的示例中所示的錯誤。爲了這個目的,該模型被賦予一個程序,該程序中的一個位置以及能夠在該位置使用的變量列表,以後要求模型預測應該使用哪一個變量。爲了處理這個任務,程序被轉換成一個圖形,其中一個特殊節點對應要選擇的位置。經過權衡該特殊節點的計算表示以及與可用變量相對應的節點表示,網絡能夠計算每一個變量可能性的大小。爲這樣的模型提供數百萬行現有的代碼,以及不須要特別註釋的數據集,就能夠輕鬆進行訓練。

當在新代碼上運行這個模型,並以很高的機率預測 var1,但程序員選擇了 var2 時,這可能表示這是一個錯誤。經過標記這些問題讓人類專家審查,咱們就能夠發現實際的錯誤。以 Microsoft C#編譯器 Roslyn 獲取的代碼爲例:


請注意突出顯示的參數文件路徑和字段 _filePath 的用法,它們很容易被混淆。_filePath 是一個錯字,開發人員在研究人員報告了這個問題和相似問題後將之修復。在其餘一些 C#項目中也發現了相似的 bug,被報告以後獲得修復。

在量更大的定量評估中,這種新方法比傳統的機器學習技術要好得多。做爲基準測試方法,它考慮到了直接在源代碼上工做的雙向遞歸神經網絡(BiRNN)以及訪問數據流信息的 BiRNN 的簡單擴展。爲了評估不一樣的模型,他們分析了總共包含 290 萬行源代碼的開源 C#項目。在不一樣的機器學習模型中使用其中單個變量被刪除並被要求預測最初使用的變量(假設代碼通過充分測試且老是正確的)的源代碼進行測試。在第一個實驗中,他們用已保存的文件對這些模型進行訓練。在第二個實驗中,使用全新項目的數據測試這些模型。結果以下表所示,使用新的程序圖測試結果更好。image

將來的應用

程序圖是一種將深度學習方法應用於程序的多功能工具。微軟將在明年的 AI Residency Program(https://www.microsoft.com/en-us/research/academic-program/microsoft-ai-residency-program/)中繼續研究其將來的應用。


相關連接


  • 開源代碼實現:https://github.com/Microsoft/gated-graph-neural-network-samples

  • Deep Program Understanding projecthttps://www.microsoft.com/en-us/research/project/program/

  • 門控圖神經網絡論文https://arxiv.org/abs/1511.05493

  • 門控圖神經網絡代碼庫https://github.com/Microsoft/gated-graph-neural-network-samples

  • 學習用圖表來表示程序 - ICLR'18 論文https://arxiv.org/abs/1711.00740

原文連接:

https://www.microsoft.com/en-us/research/blog/learning-source-code/

相關文章
相關標籤/搜索