python构建矩阵 x y_生成Python函数一半没问题,当前最正统的代码生成是什么样的?...
生活随笔
收集整理的這篇文章主要介紹了
python构建矩阵 x y_生成Python函数一半没问题,当前最正统的代码生成是什么样的?...
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
機(jī)器之心原創(chuàng)
參與:思源
大家都說深度神經(jīng)網(wǎng)絡(luò)能力很強(qiáng),那么從函數(shù)注釋生成函數(shù)代碼,以及從函數(shù)代碼總結(jié)函數(shù)注釋這種最基礎(chǔ)的代碼任務(wù)到底能不能行?像 Python、Java 這樣的通用高級語言,到底在代碼生成上能達(dá)到什么水平?本文介紹的就是這樣一篇北大前沿研究。
開發(fā)者寫代碼,和數(shù)學(xué)家寫公式一樣是非常自然的一件事。開發(fā)者將完成某個任務(wù)的步驟和邏輯,一行行寫成代碼,并期待達(dá)到預(yù)定的效果。數(shù)學(xué)家從某個事實(shí)出發(fā),將思考過程一行行寫成表達(dá)式,并期待找到復(fù)雜邏輯背后的簡單關(guān)系。這兩者經(jīng)常會有交叉,也會有融合。數(shù)學(xué)推導(dǎo)結(jié)果可以大量簡化代碼,并提供新的解決路徑;而代碼可以快速驗(yàn)證推導(dǎo)過程,并用于實(shí)際的生活中。代碼和表達(dá)式都是一種形式化語言,而另一種必不可少的是用來描述它的自然語言,也就是注釋或文檔。通過注釋,我們能知道這段代碼干了什么,甚至很自然地想到「如果是我,這段代碼該怎么寫」。通過閱讀代碼,我們能沿著開發(fā)者的思路走一遍,總結(jié)出它到底干了什么。這兩者似乎是一種對偶關(guān)系,從代碼到注釋、從注釋到代碼,這就是代碼生成與代碼總結(jié)兩大任務(wù)。在這篇文章中,我們將介紹代碼生成與總結(jié)的最新進(jìn)展,北大 Bolin Wei、李戈等研究者提出的對偶學(xué)習(xí)在 Python 和 Java 代碼生成上獲得了新的 SOTA,并且被接收為 NeurIPS 2019 論文。如下是北大新研究根據(jù)注釋生成的兩段代碼,其中 dcsp 表示 tab 鍵、dcnl 表示換行符,它們控制 Python 代碼的縮進(jìn)結(jié)構(gòu)。值得注意的是,在 Python 語言上,根據(jù)注釋這種自然語言,生成有效的代碼已經(jīng)達(dá)到了 51.9% 的準(zhǔn)確率。也就是說,生成的一半代碼能通過詞法分析、語法分析,并生成正確的抽象語法樹。代碼生成與總結(jié),是一對兄弟之前這兩項(xiàng)研究大多都是獨(dú)立的,代碼總結(jié)會利用 Encoder-Decoder、抽象語法樹和 Tree RNN 等技術(shù)生成意圖,代碼生成會利用 Seq2Seq、語法規(guī)則和基于語法的結(jié)構(gòu)化 CNN 來生成代碼,這些研究并沒有深入挖掘它們之間的關(guān)系。而北大的這一項(xiàng)研究從對偶學(xué)習(xí)出發(fā),探索如何利用它們之間的關(guān)系促進(jìn)提升學(xué)習(xí)效果。具體而言,研究者考慮了概率與注意力權(quán)重中的對偶性,從而設(shè)計(jì)了一種正則項(xiàng)來約束對偶性。更直觀而言,這種「對偶性」表示代碼生成任務(wù)的輸入"意圖"同樣是代碼總結(jié)的輸出,反之亦然。其中意圖指開發(fā)者寫這一段代碼的目的,一般而言會通過注釋的方式用自然語言表達(dá)。利用對偶學(xué)習(xí),研究者獲得了當(dāng)前最優(yōu)的效果。其實(shí)這種提升也非常合理,例如當(dāng)前效果最好的神經(jīng)機(jī)器翻譯模型 Transformer Big + BT,它就大量采用回譯機(jī)制,希望根據(jù)原語與目標(biāo)語之間的相互翻譯,從而得到更好的最終模型。統(tǒng)一的聯(lián)合訓(xùn)練框架如下所示為代碼生成、總結(jié)的對偶學(xué)習(xí)框架,總體上生成與總結(jié)兩條路徑都非常容易理解,它們都采用了常規(guī)基于注意力機(jī)制的 Seq2Seq 模型。現(xiàn)在重要的是理解中間的對偶約束,該約束用于給損失函數(shù)加正則項(xiàng),從而令它們之間相互促進(jìn)。對偶訓(xùn)練的整體過程,代碼生成模塊與總結(jié)模塊會聯(lián)合訓(xùn)練。上面 Seq2Seq 的過程就不再贅述了,它們采用的損失函數(shù)也是常規(guī)將所有時間步上的損失相加。不過需要注意的是,源代碼的詞匯量要比注釋更大一些,因此代碼生成模塊輸出層的參數(shù)量要大于代碼總結(jié)的輸出層參數(shù)量。聯(lián)合概率來約束如前所述,對偶訓(xùn)練框架包含了非常重要的對偶約束,它由兩個對偶正則項(xiàng)組成,分別用于約束兩個模型的對偶性。這兩種正則項(xiàng)受到了注意力權(quán)重具有對稱性的啟發(fā),也受到了兩種模型之間概率相關(guān)性的啟發(fā)。若現(xiàn)在給定輸入樣本,其中假設(shè) x 為代碼,y 為對應(yīng)的代碼注釋。那么代碼生成可以描述為 p(x|y)、代碼總結(jié)可以描述為 p(y|x)。現(xiàn)在如果要找到它們之間的概率相關(guān)性,那么根據(jù)聯(lián)合概率與條件概率之間的關(guān)系式就可以快速得出:也就是說,logP(x) + logP(y|x) 需要等于 logP(y) + logP(x|y),這是代碼生成與總結(jié)的內(nèi)在聯(lián)系。如果兩項(xiàng)差別很大,那么至少可以判定代碼生成與總結(jié)都沒有達(dá)到最優(yōu)。所以,常規(guī)的做法就是把這個約束構(gòu)建為損失函數(shù):其中 P(x) 和 P(y) 分別是針對代碼和注釋的語言模型,它們都是邊緣分布。這個損失有點(diǎn)類似于回歸模型常用的均方誤差,如上所示,只要兩個子模型不滿足理論上的概率條件,那么肯定會產(chǎn)生損失,在訓(xùn)練中就會建立起代碼生成與總結(jié)的關(guān)系。注意力權(quán)重也來約束上面是其中一個正則項(xiàng),另一個正則項(xiàng)主要是考慮兩個子模型之間的對稱性。在北大的這一項(xiàng)研究中,他們考慮了注意力權(quán)重的對稱性。研究者表明,因?yàn)樽⒁饬?quán)重能度量源代碼 Token 與注釋 Token 之間的匹配關(guān)系,而這種匹配關(guān)系又是對稱的,所以注意力權(quán)重也需要是對稱的。研究者舉了一個例子,例如代碼注釋為「find the position of a character inside a string」,那么對應(yīng)源代碼可能為「string . find ( character )」。現(xiàn)在,不論是從代碼到注釋還是從注釋到代碼,源代碼中的「find」一定需要匹配到注釋中的「find」,它們之間的關(guān)系是不變的。所以,現(xiàn)在最直觀的思想是,我們希望兩個注意力權(quán)重矩陣 A_xy 和 A_yx,它們之間對應(yīng)的元素盡可能相等。因?yàn)?A_xy 表示代碼部分注意到注釋部分的程度,所以,A_xy 矩陣的每一行表示代碼的某個 Token,與注釋的所有 Tokens 之間的關(guān)系。同理 A_yx 表示注釋部分注意到代碼部分的程度,A_yx 的每一列表示代碼的某個 Token,和注釋的所有 Tokens 之間的關(guān)系。具體而言,如果?,其中 i 表示 A_xy 的第 i 行;,其中 i 表示 A_yx 的第 i 列。那么很明顯,我們需要令 b_i 盡可能等于 b_i'。如果它們非常相近,那么可以表明注意力權(quán)重矩陣是對稱的,源代碼和代碼注釋之間的匹配是成功的。因?yàn)榻?jīng)過 softmax 的 b_i 和 b_i'都是一種概率分布,所以北大研究者通過 JS 散度度量這兩類分布之間的距離。最常見的 KL 散度是不對稱的,也就是說 KL(b_i || b_i') 不等于 KL(b_i' || b_i),而 JS 散度是 KL 散度的「對稱版」,所以采用 JS 散度非常合理。此外,因?yàn)?JS 散度是對稱的,所以代碼生成模型與代碼總結(jié)模型都能采用這樣的距離度量作為約束條件。最后,以注意力權(quán)重的對稱性作為正則項(xiàng),JS 散度可以表述為:偽代碼帶你走近聯(lián)合訓(xùn)練現(xiàn)在兩種正則項(xiàng)都已經(jīng)完成了,只需要聯(lián)合訓(xùn)練兩個子模型就行了。如下算法 1 所示,輸入兩種數(shù)據(jù)源的語言模型預(yù)計(jì)對應(yīng)的數(shù)據(jù),模型就能開始學(xué)。如上所示,對于每一個批量數(shù)據(jù),模型會計(jì)算兩個子模型各自的預(yù)測損失,并同時計(jì)算兩個公共的對偶正則項(xiàng)。這樣的損失能算出對應(yīng)的梯度,并分別更新兩個子模塊的權(quán)重。目前該研究的開源實(shí)現(xiàn)已經(jīng)放到了 GitHub,研究者使用 PyTorch 實(shí)現(xiàn)了整個模型的訓(xùn)練過程。如上偽代碼所示,模型架構(gòu)方面,Seq2Seq 大家已經(jīng)比較熟了,我們需要重點(diǎn)理解的是目標(biāo)函數(shù)。如上代碼片段所示,損失函數(shù)主要由三部分組成:即常規(guī)的交叉熵?fù)p失函數(shù),它度量生成序列與標(biāo)注序列間的距離;對偶損失函數(shù),它度量的是代碼與注釋的概率相關(guān)性;最后是注意力損失,它度量的是兩組注意力權(quán)重之間的分布距離。通過這些訓(xùn)練目標(biāo)的約束,代碼生成與總結(jié)才會真正地相輔相成。真實(shí)的 GitHub 代碼生成這種最正統(tǒng)的代碼生成與總結(jié)無疑是非常困難的,它遠(yuǎn)遠(yuǎn)不能像 UI 界面那樣生成簡易的代碼。也許借助卷積神經(jīng)網(wǎng)絡(luò),UI 界面的代碼生成已經(jīng)能用于實(shí)際的界面設(shè)計(jì),但是對于「更正統(tǒng)」的純代碼生成,目前的準(zhǔn)確度還遠(yuǎn)遠(yuǎn)不能滿足我們的要求。在這篇論文中,北大研究者在 Java 與 Python 兩個數(shù)據(jù)集,測試了代碼生成與總結(jié)的效果。其中 Java 數(shù)據(jù)集是從 GitHub Java 項(xiàng)目中抽取的 Java 方法,以及對應(yīng)的自然語言注釋,該自然語言了這個方法的用途。與 Java 類似,Python 數(shù)據(jù)集也是從 GitHub 中抽取的。兩種數(shù)據(jù)集的統(tǒng)計(jì)信息如下所示:論文表 1,我們可以看到,訓(xùn)練集有 5 萬到 7 萬段代碼,且確實(shí)一段 Python 代碼平均長度要遠(yuǎn)遠(yuǎn)少于 Java 代碼。最后,我們可以看看北大研究者得出的最終效果。他們主要通過 BLEU 值、METEOR 和 ROUGE-L 三種度量方法評估模型生成的代碼注釋,這對于自然語言生成來說是比較常規(guī)的度量標(biāo)準(zhǔn);此外,研究者通過 BLEU 值與有效代碼率(PoV)來評估代碼生成的效果,其中 PoV 指生成代碼能解析為抽象語法樹的比例。如上所示為代碼生成與總結(jié)的總體效果,我們可以發(fā)現(xiàn)對偶訓(xùn)練效果要超過其它方法,且相比獨(dú)立訓(xùn)練的 Basic Model,效果也要更好一些。
值得注意的是,在代碼生成中,Java 和 Python 的 PoV 分別只有 27.4 與 51.9%。也就是說,生成的代碼首先不管是不是完成了自然語言描述的功能,它能通過詞法分析、語法分析,最終成功地構(gòu)建成抽象語法樹,占比并不高。這樣的效果,也許代表著正統(tǒng)代碼生成,最前沿的水平。它離生成合理的代碼,輔助開發(fā)者完成實(shí)戰(zhàn)開發(fā)還太遠(yuǎn)了。正如該論文作者李戈教授所說,程序的數(shù)據(jù)空間非常稀疏,而自然語言數(shù)據(jù)空間也比較稀疏,這兩個稀疏空間的變換肯定會比較困難。它并不能像圖像生成這種連續(xù)空間的變換,程序的生成還有很長的路要走。本文為機(jī)器之心原創(chuàng),轉(zhuǎn)載請聯(lián)系本公眾號獲得授權(quán)。?------------------------------------------------加入機(jī)器之心(全職記者 / 實(shí)習(xí)生):hr@jiqizhixin.com投稿或?qū)で髨?bào)道:content@jiqizhixin.com廣告 & 商務(wù)合作:bd@jiqizhixin.com總結(jié)
以上是生活随笔為你收集整理的python构建矩阵 x y_生成Python函数一半没问题,当前最正统的代码生成是什么样的?...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 心脏手术多少钱啊?
- 下一篇: python高阶函数介绍_python高