DeepLearning經常使用庫簡要介紹與對比

網上近日流傳一張DL相關庫在Github上的受關注度對比(數據應該是2016/03/15左右統計的):
html

其中tensorflow,caffe,keras和Theano排名比較靠前。python

今日組會報告上tj師弟從我的使用經驗上作了簡單介紹與對比,分享給你們。c++

===================華麗的分隔線====================git

師弟的原文出處:http://tianjun.me/essays/102/github

本文將從deep learning 相關工具庫的使用者角度來介紹下github上stars數排在前面的幾個庫(tensorflow, keras, torch, theano, skflow, lasagne, blocks)。因爲個人主要研究內容爲文本相關的工做,因此各個庫的分析帶有必定主觀因素,以RNN模型爲主,CNN相關的內容瞭解得不是特別深刻(本 文沒有比較caffe和mxnet,其實主要緣由仍是本身C++過久沒用了……)。算法

閱讀本文你會了解:
1. 各個庫是如何對神經網絡中的結構和計算單元進行抽象的;
2. 如何用每一個庫跑RNN相關的模型;
3. 各個庫學習和使用的難以程度對比;
4. 在各個庫基礎之上進一步改進和開發的難易程度.編程

本文不會涉及:
1. 各個庫運行時間效率的對比(我沒有本身作過相關的對比實驗,可是網上有不少數據能夠查);
2. CNN相關模型的構建(前面提到了本身最近對這塊瞭解得很少);
3. RNN相關模型的原理和解釋(網上不少資料,能夠先學習後再進一步閱讀).網絡

先說說這幾個庫之間的大體關係dom

對於一個優秀的深度學習系統,或者更廣來講優秀的科學計算系統,最重要的是編程接口的設計。他們都採用將一個領域特定語言 (domain specific language)嵌入到一個主語言中。例如numpy將矩陣運算嵌入到python中。這類嵌入通常分爲兩種,其中一種嵌入的較淺,其中每一個語句都按原 來的意思執行,且一般採用命令式編程(imperative programming),其中numpy和Torch就是屬於這種。而另外一種則用一種深的嵌入方式,提供一整套針對具體應用的迷你語言。這一種一般使用 聲明式語言(declarative programing),既用戶只須要聲明要作什麼,而具體執行則由系統完成。這類系統包括Caffe,theano和剛公佈的TensorFlow。機器學習

以上是摘自MXNet設計和實現中 的一段話。理解了這段話後,對後面各個庫的進一步理解頗有幫助。MXNet的設計者表示融合了這兩種編程模式,咱們先拋開mxnet,如上所述torch 是採用命令式編程,而後theano和tensorflow是採用聲明式編程,skflow對經常使用的tensorflow的封裝,lasagne是對 theano的封裝,blocks除了對theano進行封裝以外還提供了額外的處理機制,keras則是用一套接口同時封裝了theano和 tensorflow,以下圖所示。

從theano提及

前面說theano是聲明式語言,其基本過程能夠描述爲如下幾步:

1. 定義輸入變量(x,y),輸出變量(z);
2. 描述變量之間的計算關係(z = x + y);
3. 編譯(f = theano.function([x, y], z);
4. 求值(f(1,2)).
那麼,若是我想用theano寫一個lstm呢?(具體參見這裏)

1. 準備輸入變量x及x_mask(維度爲 batch_size * sentence_length * vector_size),目標變量target(維度爲batch_size);
2. 定義初始化lstm結構單元中的參數(i, f, o, c);
3. 定義好一個scan函數,在scan函數中完成每一個結構單元的計算,根據lstm網絡的性質,將結構單元的輸出導入到下一步的輸入。在這裏,theano中的scan就是一個增強版的for循環;
4. 計算loss,採用某種算法更新參數;
5. 編譯,f = theano.function([x, x_mask, target], loss);
6. 對每一個batch求值.
注意前面加黑的幾個關鍵詞,在後咱們將反覆看到每一個庫的設計者對這幾個概念的不一樣理解。

接着說tensorflow

tensorflow的設計思想和theano很接近。可是我感受,tensorflow彷佛更強調總體性和結構型。兩者的明顯區別在於:

1. tensorflow默認有一個Graph的結構,全部添加的結點都是在這個圖結構上,可是theano中並無這個概念。個人理解是這個Graph結構對於變量的管理會方便點;
2. tensorflow目前可以在單機上多卡並行處理,其機制是經過指定gpu來分配計算過程的。所以,能夠說其並行機制是數據層面的。而theano須要在載入包以前就指定gpu.
其他的不少地方都是類似的,只是換了名字而已,好比: tensorflow中的variable對應theano下的共享變量shared variables, tensorflow中的placeholder對應theano中的tensor變量, 另外tensorflow中爲了不變量的來回複製,其所用的tensor的概念和theano中不太同樣

而後來看看tensorflow是怎麼實現一個LSTM網絡的,與theano不一樣,tensorflow已經對rnn_cell和lstm_cell作了封裝,所以寫起來容易了不少。

1. 定義好輸入及中間變量;
2. 採用for循環將每一個lstm_cell的輸入輸出組裝起來;
3. 剩下的也就沒有新意了,計算loss,更新state.
咱們後面再討論這種封裝方式與其餘庫的對比。

再說torch

torch的代碼寫起來有點像寫matlab,自己torch是一個科學計算的大集合(我感受只是借了lua這個語言一個外殼,方便和c及c++交互罷了,從這個角度來看,我以爲julia這門語言彷佛大有潛力),這裏咱們主要是討論其中的nn和rnn模塊。
我本身對lua及torch都不是很熟,可是好在語法不復雜,基本都能看懂,建議你們也能花點時間學習下,這樣下次看到哪篇paper裏實驗部分用 torch寫的時候,不至於徹底看不懂。儘管我對torch的瞭解不深,可是不得不說torch對剩下其它幾個庫的設計影響很是大!

在torch的nn模塊裏,首先對整個網絡結構作了分類抽象。首先是最頂層的抽象Model,這個裏面最基礎的就是output和 grad_output,記憶中和caffe的抽象是相似的,將計算結果和偏導結果用一個抽象類來表示了。而後是Sequential, Parallel 及 Concat這三個容器。Sequential用於描述網絡中一層層的序列關係,典型的就是MLP,Parallel能夠用於分別處理輸入的不一樣維度,而 Concat則能夠用於合併操做。通常來講,咱們如今的網絡結構均可以經過這三種結構拼接獲得。

而後再看看torch的rnn模塊中如何構建lstm網絡的:

和tensorflow同樣,首先是繼承自AbstractRecurrent的一個抽象,而後是參數配置和初始化,不一樣之處在於,其對LSTM中的門結構也作了進一步抽象,最後,用Sequence代替了for循環的功能,從而提供一個完整的網絡結構。

小結

經過上面的簡單描述,咱們對這三個基本庫有了些大體的印象。

1. torch是最龐大的庫,若是一開始就選擇這個庫做爲工具的話,還算說得過去,不然學習的代價有點大,由於日常作實驗涉及的每每不僅是跑跑模型這麼簡單,還涉及到數據的預處理與分析,相關圖表的繪製,對比實驗等等。這樣一來要學習的東西就比較多了;
2. theano因爲借用了numpy,scipy等python下科學計算的庫,相對torch來講要輕鬆一些。不過,theano自己並無像其它兩個庫同樣提供cnn,rnn等模型的抽象類,所以每每不會直接使用theano去寫模型;
3. tensorflow則更像是爲神經網絡相關模型而定製的。從頂層設計上就以graph爲依託,經過不一樣的Session來控制計算流.

從庫的使用者角度來講,tensorflow和torch都還不錯。可是,若是涉及網絡結構(這裏特指RNN相關的網絡)修改,那麼torch要相 對容易一些,主要是多了一個Gate的抽象,中間參數的處理上不須要太操心,而tensorflow中LSTM和RNN抽象類的耦合比較緊,若是涉及內部 結構的修改會稍稍麻煩點,須要重寫的方法比較多。

tensorflow開源時間不久,先拋開不計。因爲theano缺乏對神經網絡結構的抽象,而torch中nn模塊又設計得很合理,因而後面涌現的基於theano的庫多多少少都有所參照。

Keras

keras設計的level有點高,其設想的就是底層的計算模塊是可拔插的。這個功能固然看起來很炫酷,我想用tensorflow就用 tensorflow,想用theano就用theano做爲計算內核,然而代價也是有的,若是你想改其中的結構,複雜程度立立刻去了。我以爲這個庫的目 標用戶僅限於使用現有神經網絡單元結構的人。若是你發現某個結構keras裏沒有?沒事,這個項目開發者衆多,發起個issue,立刻就有人填坑(好比 highway network, 我在其它幾個庫裏還沒發現,這裏竟然就有了,雖然並不複雜)。若是你想構造個本身的結構單元?那得了,您仍是看看後面幾個庫吧。

綜上所述,keras最大的亮點就是,簡潔而全面。正所謂人多力量大嘛! 因爲其底層處於兼容性作了一套本身的封裝,想改的話稍顯麻煩。

若是你以爲看完keras還不知道怎麼用?想來點更簡單的?有!sklearn用過把,fit, predict兩步便可,傻瓜式操做,人人都是機器學習大神。skflow就是相似的,看名字就知道了。不過是基於tensorflow開發的。我反正是沒用過這個庫……

Lasagne

lasagne對網絡結構的抽象和上面的幾個庫有很大的不一樣,在lasagne中基本抽象單元是Layer,對應到整個神經網絡中的一層結構。這個 layer能夠是cnn也能夠是rnn結構,除此以外還有一個MergeLayer,就是多輸入多輸出的結構。和torch同樣,也對Gate門結構作了 抽象。

這樣設計有好處也有麻煩的地方:

1. 好處是,寫出來的網絡結構很簡潔,網絡結構的初始化和配置都包含在layer初始化參數裏;
2. 不方便的地方是,只引入了layer結構抽象層,是在是有些單一,若是能再加一個相似torch中的Sequential結構就perfect了,由於一 旦涉及到循環,就不得不回頭去使用theano中的scan函數,說實話,scan函數設計得太複雜了點。(固然,做者是不這麼認爲的,設計者認爲 lasagne並非要將theano徹底隔離開,相反,lasagne中的全部變量都應該相對theano是透明的Transparency)。

此外,lasagne中LSTM網絡的實現與前面的大體相同,實現細節上,lasagne中的lstm類直接繼承自MergeLayer,而後內部 採用scan函數實現,像其它庫因爲有循環結構的抽象實現,所以每一個lstm_cell類只須要完成單個結點內部的運算(也即只實現scan函數中的 _step輔助函數)

總的感受就是,lasagne在類的抽象上並無過分設計,整個網絡中的參數採用自頂向下的寬度優先算法獲取,所以,只要你願意,你能夠任意在這個網絡上「鑿」個洞,獲得該局部網絡的關係。有必定的擴展性優點。

Blocks

這個庫是我最看好的一個庫,做者應該從torch中借鑑了不少思想。

在這個庫中,每個運算都看作是一塊磚,這塊磚涉及配置、分配、應用和初始化這四步。更重要的一點是,brick與brick之間能夠嵌套,從而獲得更抽象的brick。這下子解決了咱們前面一直碰到的一個問題:抽象層次的把握!前面大多都是根據抽象層次的不一樣設計各自的類,而blocks經過嵌套將類統一塊兒來,這樣咱們在設計本身的模塊時,能夠很方便地選取合適尺寸的brick。

相比lasagne中直接根據layer.get_output來獲取參數,blocks採用了ComputationGraph來管理整個網絡結 構,個人理解是,lasagne的那種方式仍是有點野蠻……採用ComputationGraph以後,能夠同時制定輸入和輸出對象,這樣即便網絡結構變 得更復雜了,咱們也能夠爲所欲爲指定其中某個部分來更新。

下面用blocks文檔中關於rnn的一個模型來講明blocks在個性化定製方面是多麼優雅。先看圖:

若是要設計這樣一個stack的模型,就須要make your hands dirty 了。在lasagne中,這個總體會被看作一個layer,因此須要本身重寫一個layer,那跟直接用theano寫無異了……keras中也沒有提供 現有的模型,因此……對於tensorflow和torch來講,須要重寫AbstractRecurrent類,從而可讓其接受兩個輸入。

相比之下Keras提供的解決方案就比較優雅,經過iterate將simplerecurrent在time_step維度上縮短到了1步,而後再將整個鏈接結構封裝起來。(也許其它幾個庫也有相似的控制,暫時沒發現)

固然,除了上面這些抽象層面的易用性,blocks還提供了豐富的可視化調試和控制接口,以及數據預處理的fuel模塊。這些功能在整個工程變得愈來愈臃腫的時候仍是很實用的。

總結

Torch的學習成本比較低,建議稍微花點時間學習,這樣之後碰到相關代碼不至於看不懂;

在瞭解theano的基礎上,若是隻是想跑一下現有的模型不關注底層的實現,快速驗證能夠直接用Keras,上手快,模塊清晰。若是打算持續投入, 涉及大量網絡結構改進,須要深度定製的網絡,推薦使用blocks,其對訓練過程的控制有着獨特的優點。對於一個相對複雜的實驗,建議用blocks,主 要是預處理數據管理方便,圖表信息很全。由於越到後面,這塊話的時間甚至遇上建模的時間了.

另外,這裏沒有涉及Caffe和MxNet,Caffe聽說圖像處理中用的比較多,雖然最近也支持RNN相關模型了,但彷佛你們並不捧場。
MxNet支持多機多卡並行,這點就決定了其在工程項目中的應用。底層用c++寫的,也提供了python接口,一樣也是以CNN相關模型爲主,網上評價其對RNN相關模型支持很好,沒親自試過。

另外須要注意的一點是,一樣的數據,用不一樣庫的同一個算法時,結果極可能會出現幾個點的差別,這每每是不一樣庫中對默認參數的初始化方式不一樣引發的,須要仔細檢查下。

 

from: http://jacoxu.com/?p=1836

相關文章
相關標籤/搜索