程式翻譯是將一種語言的遺留程式碼遷移到用另一種語言構建的生態系統的重要工具。本文作者首次使用深度神經網路來解決程式翻譯問題。他們觀察到程式翻譯是一個模組化的過程並據此設計了一個樹到樹的神經網路,將源樹轉換為目標樹。與其他神經翻譯模型相比,該方法始終比對比基線好 15 個百分點以上。此外,該方法的效能在實際專案的翻譯上比目前最先進的程式翻譯方法高 20 個百分點。
程式是構建計算機應用、IT 產業和數碼世界的主要工具。為了方便程式設計師為不同的應用開發程式,人們發明了各種程式語言。與此同時,當程式設計師想要將用不同語言編寫的程式組合在一起時,這些程式語言的差異就為這項工作帶來了困難。因此,實現不同程式語言之間的程式翻譯是十分必要的。
如今,為了在不同的程式語言之間翻譯程式,程式設計師通常會自己親自研究兩種語言語法之間的對應關係,然後開發一個基於規則的翻譯器。然而,這個過程可能效率低下,而且十分容易出錯。在本文的工作中,我們首次嘗試檢驗是否可以利用深度神經網路來自動構建一個程式翻譯器。
憑直覺看,程式翻譯問題在其形式上類似於自然語言翻譯問題。先前的一些工作提出將基於短語的統計機器翻譯(SMT)用於程式碼遷移 [26,20,27]。最近,基於序列到序列(Seq2Seq)的模型等神經網路方法在機器翻譯方面取得了當前最佳效能 [5,10,14,15,36]。在本文中,作者研究了使用神經機器翻譯方法來處理程式翻譯問題。然而,使基於序列到序列的模型失效的一個巨大挑戰是:與自然語言不同,程式語言有嚴格的語法,它不能容忍拼寫錯誤和語法錯誤。已經證明,當程式語言序列變得太長時 [21],基於 RNN 的序列生成器很難生成句法正確的程式。
在本文的工作中,我們注意到,RNN 很難生成句法正確程式的主要原因是它將兩個子任務——學習語法及對齊序列與語法——糾纏在了一起。當這兩個任務可以被分別處理時,模型的效能通常會提高。例如,Dong 等人使用了一個基於樹的解碼器來分離兩個任務 [12]。特別是 [12] 中的解碼器利用樹結構資訊:(1)使用 LSTM 解碼器在解析樹的相同深度生成節點;(2)展開一個非葉子節點並在解析樹中生成它的子元素。這種方法已被證明可以在一些語義解析任務上取得目前最好的結果。
受到這個觀測結果的啟發,我們假設可以利用源解析樹和目標解析樹的結構資訊來實現這種分離。受這種直覺的啟發,我們提出樹到樹的神經網路,將樹編碼器和樹解碼器結合在一起。特別地,我們注意到在程式翻譯問題中,源程式和目標程式都有各自的解析樹。此外,跨語言的編譯器通常遵循一個模組化過程,將源樹中的各個子元件轉換為相應的目標元件,然後使用它們組合成最終的目標樹。因此,我們設計了一種樹到樹神經網路的工作流程來配合這個過程:當解碼器展開一個非葉子節點時,它會使用注意力機制在源樹中定位對應的子樹,並利用子樹的資訊來引導非葉子節點展開。特別需要注意的是,樹編碼器在這種情況下有很大的作用,因為它可以將子樹的所有資訊聚合到它的根的嵌入中,這樣嵌入就可以用來指導目標樹的非葉子節點擴充套件。
我們根據上述直覺來設計樹到樹的轉換模型。一些現有的工作 [34,22] 提出了基於樹的自動編碼器體系架構。但是,在這些模型中,解碼器只能訪問表示源樹的單個隱藏向量,因此它們在翻譯任務中不夠高效。在我們對模型的評價過程中,我們證明了在沒有注意力機制的情況下,翻譯效能在大多數情況下為 0%,而使用注意機制可以將效能提升到 90% 以上。論文「Towards neural machine translation with latent tree attention」提出了一種用於自然語言翻譯的基於樹的注意力編碼器-譯碼器架構,但其模型的效能甚至比注意力序列到序列的對比基線模型更差。一個主要原因是,它們的注意力機制獨立地計算每個節點的注意力權值,這並不能很好地捕獲解析樹的層次結構。在本文的工作中,作者設計了一個父親節點注意力反饋機制,該機制建立了不同節點之間的注意力對映依賴關係,作者證明了這種注意力機制進一步提高了樹到樹模型的效能,特別是當解析樹變大時(即獲得了 20%−30% 的效能提升)。據我們所知,這是目前針對翻譯任務提出的樹到樹神經網路架構的首次成功展示。
為了檢驗我們的假設,我們開發了兩個新的程式翻譯任務,並使用現有的 Java 到 c# 的程式翻譯工作 [26,27] 進行對比基準測試。首先,我們在提出的兩個任務上,對我們的方法和一些神經網路方法進行了對比。實驗結果表明,我們的樹到樹模型在程式翻譯任務上優於其他最先進的神經網路,在單詞翻譯的準確率上提升了 5%,在程式翻譯的準確率上提升了 15%。此外,我們將我們的方法與以前在 Java 到 c# 對比基準上的程式翻譯方法進行了比較,結果顯示,我們的樹到樹模型在程式翻譯的準確率上比以前的技術領先 20%。這些結果表明,我們的樹到樹模型在解決程式翻譯問題上是很有發展前景的。同時,我們認為我們提出的樹到樹神經網路也可以適用於其他樹到樹的任務,這將是我們未來的工作。
論文:Tree-to-tree Neural Networks for Program Translation
論文連結:https://arxiv.org/pdf/1802.03691.pdf
摘要:程式翻譯是將一種語言的遺留程式碼遷移到用另一種語言構建的生態系統的重要工具。在本文的工作中,我們首次使用深度神經網路來解決程式翻譯問題。我們觀察到程式翻譯是一個模組化的過程,在這個過程中,源樹的子樹在每一步都被轉換成相應的目標子樹。為了利用這種直覺,我們設計了一個樹到樹的神經網路,將源樹轉換為目標樹。同時,我們為樹到樹模型開發了一種注意力機制,當解碼器在目標樹中展開一個非葉子節點時,注意力機制會在源樹中定位相應的子樹來引導解碼器展開。我們將樹到樹模型的程式翻譯能力和一些目前最先進的方法進行比較,從而對其進行評價。與其他神經翻譯模型相比,我們的方法始終比對比基線好 15 個百分點以上。此外,我們方法的效能在實際專案的翻譯上比以前最先進的程式翻譯方法提高了 20 個百分點。
2 程式翻譯問題的形式化定義
定義 1(程式翻譯)
給定兩種程式語言 L_s 和 L_t,每種程式語言都有一組例項(p_k,T_k),其中 T_k 是這種語言對應的解析樹。我們假設存在標準的翻譯結果 π,它能將 L_s 中的例項完美地對映到 L_t 的例項上。給定一個例項對(i_s,i_t)的資料集,我們有 i_s ∈ L_s, i_t ∈ L_t 且 π(i_s) = i_t,本文研究的問題就是如何學習到一個函式 F 能夠將每個 i_s ∈ L_s 對映到 i_t = π(i_s) 上。
3 樹到樹的神經網路
3.1 將程式翻譯看做一個樹到樹的翻譯問題
圖 1:將一個 CoffeeScript 程式翻譯成一個 JavaScript 程式。CoffeeScript 程式的子元件及其在 JavaScript 中相對應的翻譯結果被高亮顯示了出來。
圖 1 展示了一個從 CoffeeScript 到 JavaScript 的翻譯示例。我們注意到程式翻譯問題的一個有趣特性是,翻譯過程可以是模組化的。圖中高亮顯示了源樹中對應於 x=1 的子元件及其在目標樹中對應於 x=1 的翻譯結果;這種對應關係獨立於程式的其他部分。當程式變得更長,這樣的情況可能重複發生多次時,序列到序列模型可能很難僅基於沒有結構資訊的 token 序列來捕獲對應關係。因此,當將目標樹中的非葉子節點擴充套件為子樹時,這樣的對應關係使得在源樹中定位引用的子樹成為一種自然的解決方案。
3.2 樹到樹的神經網路
在上述動機的啟發下,我們設計了樹到樹的神經網路,它遵循了一個編碼器-解碼器框架,將源樹編碼為嵌入,並將嵌入解碼為目標樹。為了利用模組化翻譯過程的直覺,解碼器在展開非葉子節點時採用了注意力機制來定位相應的源子樹。我們在圖 2 中展示了樹到樹模型的工作流。
圖 2:樹到樹模型的工作流:箭頭表示計算流。藍色實箭頭表示指向左子節點/從左子節點流入的流,橙色虛線箭頭表示右子節點的流。從源樹根到目標樹根的黑色點箭頭代表 LSTM 狀態被複制。綠色框表示擴充套件節點,灰色框表示佇列中待擴充套件的節點。與擴充套件節點對應的源樹的子樹用黃色高亮顯示。右下角列出了預測擴充套件節點值的公式。
4 模型評價
在本章中,作者在程式翻譯任務上評價了本文提出的樹到到樹神經網路和其它一些對比基準方法。
表 1:在 CoffeeScript 和 JavaScript 之間進行翻譯的程式準確率。token 準確率見附錄 C。
表 2:在 Java 到 C# 的翻譯中的程式準確率。在括號中,我們給出了可以透過增加訓練集來達到的程式準確率。