除了檢查語法,用上深度學習的編輯器也能自動優化程式碼

機器之心發表於2019-05-06

「將類似 i = i + 1 的語句替換為 i++」,「好的,已替換~」

IDE 除了檢查語法錯誤或拼寫錯誤,能不能更高階一點?藉助深度學習,程式碼編輯能更智慧,編輯器也能理解一些高階語義。在這篇文章中,CMU 和微軟的研究者介紹了一篇 ICLR 2019 的新研究,它只需要輸入一些高階語義,編輯器就能自動改改程式碼。

「這是我的頂會論文—你覺得如何?」經過數小時麻煩的文字輸入和圖片插入後,分享初稿的時刻你感到非常自豪。但沒過多久,你可能就會有打臉的感覺,你的同事給你反饋時進行了大量的編輯。

這些編輯很多隻是簡單的語法、風格修正或新增引用,這些反饋的小建議並不如論文實質內容那樣令人高興或有價值。例如指出單詞拼寫錯誤等操作,最基礎的反饋形式已經實現了自動化。但是,那些更復雜的編輯任務能否也實現自動化呢?

特別適合探究該問題的一個領域是原始碼編輯(source code editing)。利用先進的控制工具和重構工具,原始碼倉庫為訓練和測試深度學習模型提供大量資料,以研究如何表徵、發現和應用編輯。在 ICLR 2019 大會論文《Learning to Represent Edits》中,微軟利用這些資源建立無監督深度學習模型,該模型在程式碼和自然語言領域生成合理編輯過程顯示出了良好的前景。

論文:LEARNING TO REPRESENT EDITS

論文連結:https://openreview.net/pdf?id=BJl6AjC5F7

學習編輯表徵

深度學習在生成和理解自然語言、原始碼等方面已經取得了很多成果,它們在很多方面都達到了當前最優效能。而在微軟的這項研究工作中,主要挑戰在於設計一種專門編碼「編輯(edits)」的方法,以使編輯過程能通過深度學習技術自動處理。

為了理解研究者提出來的方法,我們可以思考下面的類比:

若一臺影印機有大量設定,例如黑白或彩印的選擇、放大或縮小文字等等。我們可以將這些設定的組合表示為一個向量,這裡為簡單起見可以表示為Δ,它描述了影印機各種按鈕與開關。在配置Δ下複製原文件 x-可以得到新文件 x+,在這過程中會發生很多編輯過程,例如將彩色轉換為黑白。編輯本身會應用到影印機上,而Δ只是這些編輯的高階表示。也就是說,Δ編碼「輸出一份黑白影印」的語義資訊,影印機再解碼這些編碼,並生成底層指令來調整內部引擎。

若將前面的概念轉換到原始碼或自然語言編輯後,影印機就類比於神經網路,編輯表徵Δ就表示提供給神經網路的低維向量。我們可以限制該向量的表示能力,從而鼓勵系統學習編碼「編輯」的高階語義資訊。例如,學習「將輸出轉化為黑白影印」,而不是學習低維語義資訊:「令畫素 (0, 0) 為白色、畫素 (0, 1) 為黑色...」。

這意味著,給定兩個不同的輸入文件 x- 和 x-',如下原始碼所示,Δ 應該執行相似的編輯:

除了檢查語法,用上深度學習的編輯器也能自動優化程式碼

低維向量Δ的表示能力會受到限制,從而鼓勵編輯器或神經網路學習編碼「編輯」的高階語義資訊。

在這個案例中,Δ表示了語義編輯:「將 v0.projectIds 計數為零的斷言(assertion)替換為斷言 v0.projectIds 為空(emptiness)」。

到目前為止,我們已經描述了一個編輯器網路,它可以在給定表徵向量Δ的情況下完成編輯。但是我們又該如何學會將觀察到的編輯轉化為高階表徵Δ呢?

這類似於學習影印機上的各種按鈕與開關,而且還不需要任何開關的標註。為了完成這些過程,研究者收集了一個包含編輯過程的資料集,即原來的 x-與編輯後的 x+。對於原始碼編輯,研究者根據 GitHub 上的開原始碼 commit 記錄,建立了一個新的資料集。對於自然語言編輯,研究者使用的是已存的 Wikipedia edits。

收集這些資料集後,研究者就可以使用第二個神經網路計算編輯表徵Δ,它的輸入和標註分別是 x-和 x+,這個神經網路被稱為編輯編碼器。

編輯器和編輯編碼器可以聯合訓練。研究者要求整個系統來計算編輯表徵Δ,所以編輯器能使用Δ和 x-重建 tilde x+,重建出來的程式碼需要基本等同於原始 x+。因此,編輯編碼器和編輯器能相互適應,從而通過Δ傳遞有意義的編輯資訊。

除了檢查語法,用上深度學習的編輯器也能自動優化程式碼

為了將觀察到的編輯轉化為高階表徵Δ,研究者需要聯合訓練兩個神經網路,即編輯器網路和編輯編碼網路。

探索學習到的表徵

既然我們能夠在低緯向量空間中表徵編輯,則可以開始解決最初的問題了:哪些更復雜的編輯任務可以實現自動化?

回答該問題的第一步是探究我們的系統是否可以學會區分不同種類的編輯。為此,微軟的研究者在 90,000 條 C# 程式碼編輯中訓練該系統,之後使用訓練的編輯編碼器(edit encoder)對 3,000 個特殊標記的編輯進行編碼。在標籤集中,每個編輯都是從 16 條手寫的程式碼重構規則(被稱為 Roslyn fixer)中生成的。

例如,其中模板之一是 RCS1089,其描述為「使用++/– 運算元替代運算語句」。當應用時,該 fixer 以「x++」替代「x = x + 1」等語句。我們為每個標記編輯收集編輯編碼器生成的編輯表徵Δ,並且使用 t-SNE 投影在 2D 中視覺化這些向量;在下圖中,每個點的顏色表示該點是由哪個 fixer 生成的。

微軟觀察到,大多數編輯根據應用的程式碼重構規則正確地聚集在一起,表明該編輯編碼器在分配類似表徵Δ給類似語義編輯以及區分不同種類的編輯方面表現良好。

除了檢查語法,用上深度學習的編輯器也能自動優化程式碼

編輯編碼器利用 16 個手動程式碼重構規則生成編輯的 tSNE 視覺化結果,該編碼器能夠將類似表徵分配給類似語義編輯。每個點的顏色表示該點是由哪個 fixer 生成的。

研究者在自然語言的編輯中也觀察到了類似結果。微軟的系統將語義上有意義的編輯聚集在一起。例如,當系統在 Wikipedia edits 中進行訓練時,其中一個編輯叢集表示在句子中新增「on the moon」和「in the market」等介詞短語,另一個表示在人名中新增中間名。

應用學習到的編輯

微軟認為,當分析了大量的編輯語料庫並確定了編輯叢集之後,就可以從叢集形心中提取出規範的編輯向量,並將其應用到新文件中,從而生成能將編輯過程自動化的建議。為了檢驗這種想法是否可行,微軟再次轉向由 Roslyn fixer 生成的編輯資料庫

為了評估將編輯表徵遷移到新語境中的效果,研究者考慮了兩對編輯:x-和 x+以及 y-和 y+。他們從第一對編輯中計算出一個編輯表徵 Δ,然後讓編輯器將其應用到 y-中。例如,考慮將「x=x+1」替換為「x++」的編輯,然後嘗試將得到的編輯表徵應用到「foo=foo+1」。他們在實驗中發現,50% 的樣本中的編輯結果可以與預期編輯結果相匹配。然而,由於編輯的複雜程度有所差別,匹配的準確率也有很大差異。例如,在 RCS1089 fixer 生成的樣本中,匹配準確率是 96%,但在 RCS1197 生成的樣本中,準確率只有 5%。

儘管微軟的 ICLR 論文已經探索了文字和程式碼中的編輯表徵問題,但他們展示出的方法還只是一個開始。該方法的應用潛力令人振奮:從數萬名專業編輯、軟體工程師和設計師的作品中學到的文字、程式碼或影像的自動改進。也許,當你下次再把自己的論文拿給同事編輯的時候,你會感覺非常自豪。

原文連結:https://www.microsoft.com/en-us/research/blog/beyond-spell-checkers-enhancing-the-editing-process-with-deep-learning/

相關文章