寫程式碼是軟體工程師們每天的工作,但當你辛辛苦苦寫了一大堆程式碼,卻發現無法運行的時候,內心一定是崩潰的。
找 bug 不僅費時費力,最關鍵的是還經常找不著,並且有時候改了一個 bug 又會引入更多 bug,子子孫孫無窮盡也。
簡直就是找 bug 找到吐血。
隨著 AI 技術的發展,各大公司開發的程式碼助手如 GitHub Copilot 等也能幫你少寫一些有 bug 的程式碼。
但這還遠遠不夠!
深度學習要是能幫我把程式碼裡的 bug 也給修了,我上班豈不是輕鬆多了!
微軟在 NeurIPS 2021上還真發了一篇這樣的論文,其中提出了一個新的深度學習模型 bug Lab,並透過自監督的學習方法,可以在不借助任何標注數據的情況下檢測和修復程式碼中的 bug,堪稱程式員的救世主!
修bug難在哪?
所謂的 bug,就是程式碼的實際運行和自己的預期不符。
該執行的沒執行,該輸出a,結果卻輸出個b,這種程式碼故意找碴的行為都屬於 bug。
所以想要找到並修復程式碼中的 bug,不僅需要對程式碼的結構進行推理,還需要理解軟體開發者在程式碼注釋、變量名稱等方面留下的模糊的自然語言提示。
例如一段程式的意圖是,如果名字的長度超過了22個字元,那就只截取前22個。但原始程式碼中錯誤地把大於號寫成了小於號,導致條件判斷錯誤,程式運行結果和預期不符。
這種小錯誤在寫程式碼的過程也是太常見了,稍不注意就會把條件弄反。
還有一種 bug 就是使用了錯誤的變量,例如下面的例子里面 write 和 read 弄錯了,就會導致條件判斷失敗,這種 bug 的修復只有在理解了變量名的意義後才能修復,傳統的修復手段對此是無能為力。
這種錯誤看起來很簡單,但往往盯著看程式碼的時候卻很難發現,屬於一改改一天的那種。
並且每個程式員有自己的程式風格,比如不同的命名、縮進、判斷以及重構的方式,想讓程式碼來給自己找 bug,一個字,難!
對於微軟來說,好在有 GitHub 程式碼庫可以用來訓練模型。但問題來了,GitHub上帶 bug 的程式碼有那麼多嗎?有 bug 誰還 commit 啊?就算能找到程式碼,也沒人來標注數據啊!
微軟提出的 bug Lab 使用了兩個相互競爭的模型,透過玩躲貓貓(hide and seek)游戲來學習,主要的靈感來源就是生成對抗網路(GAN)。
由於有大量的程式碼實際上都是沒有 bug 的,所以需要設計一個 bug selector 來決定是否修改正確的程式碼來引入一個 bug,以及以何種方式引入 bug (例如把減號改為加號等)。當選擇器確定了 bug 的類別後,就透過編輯源程式碼的方式引入 bug。
另一個用來對抗的是 bug detector,用來判斷一段程式碼是否存在 bug,如果存在的話,它需要定位並修復這個 bug。
選擇器和檢測器都能夠在沒有標記數據的情況下共同訓練,也就是說整個訓練過程都是以自監督的方式進行,並成功在數百萬個程式碼片段上訓練。
selector 負責寫 bug,並把它藏(hide)起來,而 detector 負責找 bug,並修復,整個過程就像躲貓貓一樣。
隨著訓練的進行,selector 寫 bug 越來越熟練,而 detector 也能夠應對更復雜的 bug。
整個過程與GAN的訓練大體相似,但目的卻大不相同。GAN 的目的是獲得一個更好的生成器來修改圖片,但 bug Lab 的目的是找到一個更好的檢測器(GAN中的判別器)。
並且整個訓練也可以看作是一個 teacher-student 模型,選擇器教會檢測器如何定位並修復 bug。
為開源社群修bug!
雖然從理論上來說,使用這種 hide and seek 的方式可以訓練更復雜的 selector 來生成更多樣的 bug,進而 detector 的修 bug 能力也會更強。
但以目前的 AI 發展水平來說,還無法教會 selector 寫更難的 bug。
所以研究人員表示,我們需要集中精力關注那些更經常犯的錯誤,包括不正確的比較符,或者不正確的布爾運算符,錯誤的變量名引用等等其他一些簡單的 bug。並且為了簡單起見,實驗中只針對 python 程式碼進行研究訓練。
雖然這些解釋聽起來都像是藉口。
為了衡量模型的性能,研究人員從Python包索引中手動注釋了一個小型 bug 數據集,和其他替代方案(例如隨機插入 bug 的 selector )相比,使用 hide and seek 方法訓練的模型性能最多可以提高30%
並且實驗表明大約26%的 bug 都可以被發現並自動修復。在檢測器發現的 bug 中,有19個在現實生活中的開源 GitHub 程式碼中都屬於是未知的 bug。
但模型也會對正確的程式碼報告存在 bug,所以這個模型在離實際部署上線還有一段距離。
如果更深入地研究 selector 和 detector 模型的話,就會引出那個老生常談的問題:深度學習模型到底有沒有,又怎麼樣去「理解」一段程式碼的作用?
過去的研究表明,將程式碼表示為一個 token 序列就能夠產生次優的(suboptimal)效果。
但如果想要利用程式碼中的結構,例如語法、數據、控制流等等,就需要將程式碼中的語法節點、表達式、標識符、符號等等都表示為一個圖上的節點,並用邊來表示節點間的關係。
有了圖以後就可以使用神經網路來訓練 detector 和 selector 了。研究人員使用圖神經網路(GNN)和 relational transformer 都進行了實驗,結果發現 GNN 總體上優於 relational transformer。
如何讓AI幫助人類來寫程式碼和改 bug 一直都是人工智慧研究中的一項基礎任務,任務過程中AI模型需要理解人類對程式程式碼、變量名稱和注釋提供的上下文線索來理解程式碼的意圖。
雖然 bug Lab 離真正解放程式員改 bug 還很遙遠,但距離我們消滅 bug 總算又向前走了一步!
參考資料:
https://www.microsoft.com/en-us/research/blog/finding-and-fixing- bug s-with-deep-learning/
- 本文授權轉載自:36kr(36氪)
請注意!留言要自負法律責任,相關案例層出不窮,請慎重發文!