LeCun 說的可微分編程是什麼?


Differentiable Programming Differentiable Programming Languages,不是什麼新鮮名詞,其實搞Deep Learning和Programming Language的人近幾年來一直在探索。

一個比較通俗的解釋是:

  • 傳統的編程方法:程序員人工寫出每一行代碼,機器按照給定的代碼運行程序,根據輸入數據X得到運算結果Y。
  • Differentiable Programming:程序員不寫代碼,或者僅寫出少量high-level的代碼,但是提供大量輸入數據X與對應運算結果Y的例子。神經網路根據提供的數據集,自動學出從輸入數據X到最終運算結果Y的映射(既整個程序);或者結合程序員提供的high-level的代碼,用神經網路作為中間函數,補全得到整個程序。Differentiable Programming有點像用Deep Learning來實現Programming by example

個人感覺近期比較有代表性的paper有:

  • 完全不寫代碼:
    • Neural Turing Machines
    • Neural Symbolic Machines/Neural Programmer
    • DeepCoder: Learning to Write Programs
  • 程序員給出少量代碼,用神經網路擬合得到中間缺失的函數:
    • Programming with a Differentiable Forth Interpreter
    • Differentiable Programs with Neural Libraries
  • 相關工作--如何利用人工寫的程序來提高神經網路『寫代碼』的能力:
    • Coupling Distributed and Symbolic Execution for Natural Language Queries

個人感覺最有意思的研究方向是第二條,既怎麼能讓程序員給出一個程序大概的框架,然後利用訓練神經網路來補全中間缺失的函數。但需要指出的是,Differentiable Programming相關的研究仍然處於比較初步的階段,主要的難點有:(1)很多任務很難提供大量的輸入數據X到運算結果Y的數據集,這樣訓練X-&>Y的神經網路就比較困難。(2)把一個programming language變成全可微後,每一步運算(每一行code)都是所有可能運算加權綜合後的結果,這會帶來很大的運行開銷。導致最近Programming Language界不太看好這條路。。。總之,個人認為Differentiable Programming Differentiable Programming Language是非常有趣的研究方向,但前路漫漫~


========= 更新 =========

不好意思之前沒表達清楚意思,可能造成了一些困惑,所以更新一下~

為了理解可微分編程,首先讓我們看看近幾年都發生了些什麼:

(1)在深度神經網路剛剛提出的時候,網路是很整齊的,有輸入層,隱含層,輸出層,層層疊加。因為有很多層,所以它被稱為「深度」神經網路,也是深度學習這個詞的由來。

(2)而最近,有一些研究者轉向了「不整齊」的神經網路。這些神經網路並沒有分出明顯的層次,反而是,神經節點之間可以跨層次連接,不同的神經網路之間也可以相互連接,它們之間的連接也可以是各種函數。Hinton的Capsule網路,也類似於這個思想。還有一個課題叫AutoML,研究如何自動生成神經網路的結構。但是不論網路結構怎麼改變,有效的訓練方法還是那幾種,例如BP演算法和遺傳演算法。其中最常用的BP演算法,就是以求「微分」為基礎的。只要一個函數可以求微分,那就可以用BP演算法去訓練(訓練能否成功是另一回事)。

(3)LeCun的原文中提到,現在越來越多的人用「過程式」的方法定義神經網路,就像是定義以往的程序一樣。這句話的意思是,人們開始「設計」神經網路的結構,就像是我們以往的程序設計一樣。舉個例子,以往我們編程,要對一串數字進行排序,我們一般會寫一個sort函數,然後我們就可以多次調用這個sort函數。神經網路也是一樣,比方說我們有個神經網路,它可以對一串數字進行排序,那麼我們也可以多次調用它(題外話:在Neural Turing Machines這篇論文中,就訓練了可以對數字進行排序的神經網路)。這樣的神經網路,就像是我們傳統編程概念中的函數一樣,可以被重複調用。唯一的不同點是,以往的程序是固定的;而神經網路是動態的,是可以被訓練的。

所以LeCun提到的可微分編程,他很有可能是想表達這個意思:「深度學習」這個詞太狹隘了,人們聽到這個詞,想到的就是「有很多隱含層的神經網路」。而實際上,神經網路的結構可以有各種變化,沒必要按照深度進行分層。而且,深度學習的原理不僅僅可以用在神經網路上啊,它還可以跟我們已有的編程思想結合起來,形成一種新的程序設計方法。在幾年前,我們把「神經網路」這個領域改名為「深度學習」,而現在為了讓這個領域更進一步發展,應該把「深度學習」改名為「可微分編程」。

======== 下面是原答案 ========

剛好是我的研究課題。

首先,請看看之前我在這個問題下面的回答:

為什麼深度神經網路要使用權值來連接神經元?

這個問題跟可微分編程(Differentiable Programming)很有關。至於為什麼,我會在下文說明。

Differentiable Programming的大致思想是說:在我們以往的編程中,程序的參數都是固定的。而這些參數都是程序員事先設定好的。舉個簡單的例子,比如你編寫了一個函數,假設是f(t) = 3 * sin (2 * t + 1)。這個函數是你用來表示你的心情f跟時間t的關係。這個函數的參數是3、2、1,它們是固定的,是由你(也就是寫代碼的人)指定的。這樣問題就來了,我們知道f(t) = a * sin(b * t + c)還可以用來表示其它的很多東西,包括電磁波、聲波、交流電等等。但是每次你都要重新確定參數a、b、c的值。這樣就花費了你大量的時間,而做的是重複的工作。這種情況在我們平時編寫軟體的時候其實很常見,(所以你就知道為什麼程序員累死而不償命)。

那麼我們能不能避免這些重複性的工作呢?根據Differentiable Programming的思想,是可以避免的。我們可以讓這些確定參數的工作交給機器去做,讓機器自動幫我們確定這些參數。我們都知道反向傳播演算法(back-propagation,BP)是深度學習的基礎,而在使用BP演算法的時候,要計算神經網路中每個函數的微分(所以說是可「微分」編程)。在BP演算法中,我們需要的是神經元(Neuron)、偏置(Bias)和權值(Weight)的微分。有了這些微分,再加上一些訓練數據,我們就可以對神經網路進行訓練。那麼,我們可以把BP演算法從神經網路延伸到其它的函數。比如說剛剛提到的f(t) = a * sin(b * t + c),我們可以用BP演算法去訓練a、b、c三個參數:我們只要有幾組輸入(input)和目標(target)的數據(t是輸入,f(t)是目標),就可以讓機器自動訓練出a、b、c這三個參數的值。這樣就為程序員節省了大量時間。

在本文一開始我提到 為什麼深度神經網路要使用權值來連接神經元 這個問題。在這個問題的回答中,我引用了最近的一篇論文 Trainable back-propagated functional transfer matrices 。這篇論文主要是說,神經元節點之間的連接,並不必須是權值,還可以是各種千奇百怪的函數,而BP演算法可以訓練這些千奇百怪的函數。下面是我之前的回答:

神經節點之間並不一定非得使用權值連接。從某種意義上來說,使用權值是一種極度省麻煩的方法。實際上有各種其它的函數可以使用。題主可以看2017年10月發出的這篇論文:

Trainable back-propagated functional transfer matrices

地址是:

https://arxiv.org/abs/1710.10403

這篇論文是說,在BP演算法的框架下,節點之間的連接可以是各種複雜的函數。這些函數其實可以替代權值,而這些函數(文中舉例了20種函數)的參數也可以是可以通過BP演算法去訓練的,也可以堆疊在一起形成多隱含層的結構。在MNIST上,這些函數是可以收斂的。甚至於,它們還可以是帶有記憶的函數,用來做序列建模(原理類似於RNN,但是上一個時刻的信息不是儲存在節點中,而是儲存在節點之間的連接中)。在有先驗知識的情況下(比如說我們知道哪種函數特別適合於圖像識別,哪種可以用來抗噪等等),我們就可以根據場景和需求去設計不同的函數(這可能也是未來的一個潛在的研究方向)。

此外,從嚴格意義上來說,在卷積神經網路中常用的Max Pooling層,也不是用線性的權值去連接節點。它用的是一個Pooling函數,用於在幾個輸入中取最大值。

所以說,神經節點之間並不一定非得使用權值連接。人們使用權值只是因為它最容易實現,也最容易從數學上分析。

【參考文獻】

[1]. C.-H. Cai, Y. Xu, D. Ke, K. Su, J. Sun.

Trainable back-propagated functional transfer matrices. CoRR abs/1710.10403

(2017)

[2]. I. Goodfellow, Y. Bengio, A. Courville.

Deep learning. MIT press, 2016.

也就是說,在Differentiable Programming中,我們依據的也是這個原理。但是實際上或許並沒有這麼容易。因為訓練這些函數比訓練權值難,函數的堆疊關係多了以後更是難上加難。而在Differentiable Programming中,不僅僅要處理函數的堆疊關係,還要處理各種數據結構、循環、遞歸調用等等。所以Differentiable Programming能走多遠,我們還不知道。

【參考文獻】

因為牆的存在,貼地址大家也看不到,所以我直接截圖貼過來了:


追根溯源,簡單介紹我所知道的可微分編程(或可導編程)的歷史,及其與機器學習的關係。

「自動編程」時代

上世紀四五十年代,一個熱門的課題叫「自動編程(automatic programming)」。從這個課題中衍生出了後來的編譯器。但「編譯器」這個詞要到六十年代才盛行開來。

因為導數在科學工程問題中十分常見,子課題「自動微分」應運而生。例如1953年 MIT 的一篇碩士論文 [1]。論文中通過鏈式法則,為源代碼靜態生成導數計算。

科學計算中的可微分編程

隨著計算機語言與編譯器日漸成熟,自動微分被廣泛應用,並在兩種語義上得到了實現:符號計算,數值計算。

在符號計算中,鏈式法則用來推導代數語義(algebraic semantics)上等價的導數表達式(代數表達式)。

在數值計算中,鏈式法則用來推導操作語義(operational semantics)上等價的導數表達式(代碼)。

代數語義上的等價意味著兩種表達式都指向同一個對象。操作語義上的等價意味著兩種表達式都是通過同樣的操作步驟,來構建同一個對象。例如矩陣乘法 (A*B)*C 在操作語義上不等於 A*(B*C),因為計算順序直接影響計算複雜度。因此,雖然符號計算和數值計算中的自動微分都採用鏈式法則,在數值計算會區分鏈式法則的計算順序:正序,逆序。對於不同的導數,正序或逆序計算的複雜度可能相差 N 倍。

在符號計算的編程語言中,如 Maple, Mathematica, MuPAD,自動求導通常是標配。

在數值計算,尤其在求解優化問題的應用中,自動微分通常也是標配。幾乎所有的常用語言都有或強或弱的自動微分編譯器/解釋器:Community Portal for Automatic Differentiation。

這些自動微分軟體被用來解決各類連續優化問題

(1) argmin_{x}fleft(x
ight)

機器學習與神經網路的爆發,領域專用語言(DSL)的可微分編程

神經網路作為大腦科學的概念,很早就已出現。但神經網路作為計算模型的興起,大致是從 1974年 backpropagation 的普及開始的。BP 演算法等價於上文中說到的逆序自動微分。BP 演算法的提出者 Werbos 後來也發文追溯 Backpropagation 與逆序自動微分的關係。畢竟,神經網路的訓練也具有 (1) 的形式。

但 BP 作為機器學習領域的專門演算法,與通用的自動微分最大的區別在於,自動微分面向的是通用的,基於文本的編程語言如 C++/Python,而 BP 面向的是機器學習/神經網路領域的專門語言。這些專門語言通常是基於圖的編程語言(如 TensorFlow),所以 BP 通常不需要語法分析/類型推論,而自動微分需要。

深度學習以後的可微分編程

@林宇航 的回答附的截圖裡 Lecun 提到,隨著新模型的結構越來越不規整,也許 BP 演算法不再能勝任微分計算。開發一門可微分的通用語言也許勢在必行。但那些 BP 所未觸及,但自動微分不得不面對的問題也就來了。例如

  • 在通用編程語言可以寫出的程序中,只有很小一部分是可導的。數學上常見的可導的定義採用的是極限的概念,但極限在操作語義下是無意義的(計算機無法表達無限小或實數)。如何驗證程序的可導性?靜態分析?動態分析?
  • 神經網路的分層結構為並行計算提供能天然的條件。但在更通用的基於文本的編程語言中,這種分層結構(可並行的計算)並不總是存在。如何從文本(源代碼)中靜態分析可並行的部分,或在運行時發現可並行性?好消息是,函數及其導數在計算上是同構的,發現了一個的可並行性,就能用同樣的方式並行另一個。
  • 可微分語言的類型系統如何定義?合格的類型系統應當解決上面第一個問題。優秀的類型系統還應該解決第二個問題。

[1] Nolan, J. F. (1953). Analytical differentiation on a digital computer.

[2] Werbos, P. (2006). Backwards differentiation in AD and neural nets: Past links and new opportunities. Automatic differentiation: Applications, theory, and implementations, 15-34.


明明都是我先的,怎麼會變成這樣。

我在2016年就說了,下一代深度學習框架,必須得自動求導。沒想到他們直接改名了。

所以我建議他學習一下J語言,因為下一代可微分編程不是過程式的。


以前我們編程的時候,需要在一個函數里定義變數a,b,c,d,然後基於if else while寫邏輯,然後給出返回。

未來,我們在一個函數里定義一組張量 A,B,C,D,然後給出一組矩陣運算公式然後返回新的張量。

這樣一個函數就是一個可微的NN模塊。而一個複雜的程序由大量的基本NN模塊組合而成。

傳統的函數寫出來就能直接運行,基於NN的函數都需要訓練來得到參數。但是前者永遠只能處理確定性數據計算,後者可以復現我們的大腦。


就是在微分的基礎上添加更多的「編程」的元素。用於控制網路的前饋過程、反饋過程,控制數據的餵給過程,控制多個網路之間的協調過程。

簡而言之,是將大型項目的中高層次由人類構建,中低層次由網路從數據中學習。將學習好的神經網路直接作為函數調用。

pytorch只是一個自動求導的工具,動態圖計算框架。沒有它不過就是麻煩了點。


深度學習領域最知名的學者之一Yann LeCun今日在自己facebook上發表的一篇短文,瞬間引爆了國內人工智慧關注者們的朋友圈。這條動態講的是什麼呢?為何會引起如此軒然大波?

我們常常提到的深度學習是全部深度學習演算法的總稱,卷積神經網路是深度學習演算法在圖像處理領域的一個應用。而Yann LeCun就是卷積神經網路的發明者,也被稱之為「卷積神經網路之父」。卷積神經網路的出現對人工智慧發展的重要性不必多說。而這次Yann LeCun的推文傳播如此之快,是不是有比「卷積神經網路」更重大的學術成果出來了?

首先開頭是一句極具有標題黨風格的英法混合語:

Deep Learning est mort. Vive Differentiable Programming!

翻譯成中文就是:深度學習已死,可微分編程萬歲!

為何突出此言?深度學習演算法是人工智慧多個領域的底層框架,怎麼就死了呢?接著往下看發現LeCun說的是「深度學習」這個詞已死,該有新的名詞來替代它了。

LeCun提到的新詞是可微分編程。

他在推文中解釋道「可微分編程」不過是把現代深度學習技術重新換了個叫法,這就跟當年神經網路還只有兩個以上隱藏層時就被稱之為「深度學習」差不多。對於現代深度學習技術,「深度學習」這個詞已經不夠用了。

他又寫道:

但重點的是,人們現在正通過組裝參數化功能模塊網路,構建一種新軟體,並用某種基於梯度優化的方法來訓練它們。

越來越多的人正在以一種依賴於數據的方式(循環和條件)來程序化定義網路,讓它們隨著輸入數據的動態變化而變化。這與普通的程序非常類似,除了前者是參數化的、可以自動可微分,並且可訓練和優化。動態網路變得越來越流行(尤其是對於NLP),這要歸功於PyTorch和Chainer等深度學習框架(注意:早在1994年,之前的深度學習框架Lush,就能處理一種稱為Graph Transformer Networks的特殊動態網路,用於文本識別)。

現在人們正在積極研究開發命令式可微分編程語言編譯器,這對開發基於學習的AI(learning-based AI)來說是一條非常令人興奮的途徑。

最後,LeCun還特彆強調將「深度學習」改名為」可微分編程」還不夠,其他的一些概念也需要改,比如「預測性學習」應該改為 「Imputative Learning」。他說稍後會談更多......

Yann LeCun爆驚人言論:深度學習已死?


早上看到了新聞,匆匆看了一眼了,我對他的觀點深以為然。這裡解釋一下, 權當拋磚引玉。

  1. 簡單的神經網路,一層加一層,每一層有N個節點,forward過程做加權,backward過程,因為每個節點都是可以微分的,做反向傳播(BP)。
  2. CNN,每一層改為一個3維或者4維的層級,每一塊掃描,每一塊可微分。forward加權,因為每個節點可微分,做BP。
  3. RNN,每個層可以向自己做微分。
  4. GAN,兩個網路,每層都可以微分,特殊的loss函數。

那我們可以看出來,其實任何神經網路都可以像搭積木一樣拼出來,這個積木只需要一個條件,就是可以微分,這種可微分是做BP的必要條件, 而且可微分有一個很好的特點,就是鏈式法則,這樣決定了所有的微分可以組合起來。除了這個之外,和普通編程沒有什麼區別。我想這就是可微分編程的來歷。

想一想,這對以後的編程有什麼影響,以後寫神經網路。直接提供給你幾個可以微分的模塊(就像Drag and Drop UI 裡面的這種模塊), 你簡單的組合起來, 加上loss function, 就可以形成你的神經網路了。

我覺得有點像Keras現在做的,但是現在Keras只提供了有限的Cell。以後的模塊應該只要滿足模塊可微分就可以了,這個比現在的Keras Cell 要多的多得多。


感覺就是給PyTorch打了個廣告


反向傳播時要求導,貌似沒什麼好問的。


推薦閱讀:

深度學習cnn中,怎麼理解圖像進行池化(pooling)後的平移不變性?
學習聖經Deeplearning需要掌握哪些數學基礎?
神經網路的損失函數為什麼是非凸的?
如何評價邢波(Eric Xing)老師實驗室開發的深度學習平台 Poseidon?
wasserstein 距離的問題?

TAG:軟體 | 數學 | 機器學習 | 深度學習DeepLearning | 自動微分 |