雷鋒網按:本文作者黃文堅,PPmoney 大數據算法總監,《 TensorFlow 實戰》作者。本文節選自《 TensorFlow 實戰》第二章。
在下周二(2月28日)雷鋒網硬創公開課欄目將會推出黃文堅老師的公開課《深度學習之經典卷積神經網絡的技術淺析》(點擊了解詳情),歡迎大家報名!
Google 近日發布了 TensorFlow 1.0 候選版,這第一個穩定版將是深度學習框架發展中的裡程碑的一步。自 TensorFlow 於 2015 年底正式開源,距今已有一年多,這期間 TensorFlow 不斷給人以驚喜。在這一年多時間,TensorFlow 已從初入深度學習框架大戰的新星,成為了幾近壟斷的行業事實標準。
主流深度學習框架對比
深度學習研究的熱潮持續高漲,各種開源深度學習框架也層出不窮,其中包括 TensorFlow、Caffe、Keras、CNTK、Torch7、MXNet、Leaf、Theano、DeepLearning4、Lasagne、Neon 等等。然而 TensorFlow 卻殺出重圍,在關注度和用戶數上都佔據絕對優勢,大有一統江湖之勢。表 2-1 所示為各個開源框架在GitHub上的數據統計(數據統計於 2017 年 1 月 3 日),可以看到 TensorFlow 在 star 數量、fork 數量、contributor 數量這三個數據上都完勝其他對手。
究其原因,主要是 Google 在業界的號召力確實強大,之前也有許多成功的開源項目,以及 Google 強大的人工智慧研發水平,都讓大家對 Google 的深度學習框架充滿信心,以至於 TensorFlow 在 2015 年 11 月剛開源的第一個月就積累了 10000+ 的 star 。其次,TensorFlow 確實在很多方面擁有優異的表現,比如設計神經網絡結構的代碼的簡潔度,分布式深度學習算法的執行效率,還有部署的便利性,都是其得以勝出的亮點。如果一直關注著 TensorFlow 的開發進度,就會發現基本上每星期 TensorFlow 都會有1萬行以上的代碼更新,多則數萬行。產品本身優異的質量、快速的迭代更新、活躍的社區和積極的反饋,形成了良性循環,可以想見 TensorFlow 未來將繼續在各種深度學習框架中獨佔鰲頭。
表2-1 各個開源框架在 GitHub 上的數據統計
觀察表2-1還可以發現,Google、Microsoft、Facebook 等巨頭都參與了這場深度學習框架大戰,此外,還有畢業於伯克利大學的賈揚清主導開發的 Caffe,蒙特婁大學 Lisa Lab 團隊開發的 Theano,以及其他個人或商業組織貢獻的框架。另外,可以看到各大主流框架基本都支持 Python,目前 Python 在科學計算和數據挖掘領域可以說是獨領風騷。雖然有來自 R、Julia 等語言的競爭壓力,但是 Python 的各種庫實在是太完善了,Web 開發、數據可視化、數據預處理、資料庫連接、爬蟲等無所不能,有一個完美的生態環境。僅在數據挖據工具鏈上,Python 就有 NumPy、SciPy、Pandas、Scikit-learn、XGBoost 等組件,做數據採集和預處理都非常方便,並且之後的模型訓練階段可以和 TensorFlow 等基於 Python 的深度學習框架完美銜接。
表 2-1 和圖 2-1 所示為對主流的深度學習框架 TensorFlow、Caffe、CNTK、Theano、Torch 在各個維度的評分,本書 2.2 節會對各個深度學習框架進行比較詳細的介紹。
表2-2 主流深度學習框架在各個維度的評分
圖2-1 主流深度學習框架對比圖
各深度學習框架簡介
在本節,我們先來看看目前各流行框架的異同,以及各自的特點和優勢。
TensorFlow
TensorFlow 是相對高階的機器學習庫,用戶可以方便地用它設計神經網絡結構,而不必為了追求高效率的實現親自寫 C++或 CUDA 代碼。它和 Theano 一樣都支持自動求導,用戶不需要再通過反向傳播求解梯度。其核心代碼和 Caffe 一樣是用 C++編寫的,使用 C++簡化了線上部署的複雜度,並讓手機這種內存和CPU資源都緊張的設備可以運行複雜模型(Python 則會比較消耗資源,並且執行效率不高)。除了核心代碼的 C++接口,TensorFlow 還有官方的 Python、Go 和 Java 接口,是通過 SWIG(Simplified Wrapper and Interface Generator)實現的,這樣用戶就可以在一個硬體配置較好的機器中用 Python進行實驗,並在資源比較緊張的嵌入式環境或需要低延遲的環境中用 C++部署模型。SWIG 支持給 C/C++代碼提供各種語言的接口,因此其他腳本語言的接口未來也可以通過 SWIG 方便地添加。不過使用 Python 時有一個影響效率的問題是,每一個 mini-batch 要從 Python 中 feed 到網絡中,這個過程在 mini-batch 的數據量很小或者運算時間很短時,可能會帶來影響比較大的延遲。現在 TensorFlow 還有非官方的 Julia、Node.js、R 的接口支持,地址如下。
Julia: http://github.com/malmaud/TensorFlow.jl
Node.js: http://github.com/node-tensorflow/node-tensorflow
R: http://github.com/rstudio/tensorflow
TensorFlow 也有內置的 TF.Learn 和 TF.Slim 等上層組件可以幫助快速地設計新網絡,並且兼容 Scikit-learn estimator 接口,可以方便地實現 evaluate、grid search、cross validation 等功能。同時 TensorFlow 不只局限於神經網絡,其數據流式圖支持非常自由的算法表達,當然也可以輕鬆實現深度學習以外的機器學習算法。事實上,只要可以將計算表示成計算圖的形式,就可以使用 TensorFlow 。用戶可以寫內層循環代碼控制計算圖分支的計算,TensorFlow 會自動將相關的分支轉為子圖並執行迭代運算。TensorFlow 也可以將計算圖中的各個節點分配到不同的設備執行,充分利用硬體資源。定義新的節點只需要寫一個 Python 函數,如果沒有對應的底層運算核,那麼可能需要寫 C++或者 CUDA 代碼實現運算操作。
在數據並行模式上,TensorFlow 和 Parameter Server 很像,但 TensorFlow 有獨立的 Variable node,不像其他框架有一個全局統一的參數伺服器,因此參數同步更自由。TensorFlow 和 Spark 的核心都是一個數據計算的流式圖,Spark 面向的是大規模的數據,支持 SQL 等操作,而 TensorFlow 主要面向內存足以裝載模型參數的環境,這樣可以最大化計算效率。
TensorFlow 的另外一個重要特點是它靈活的移植性,可以將同一份代碼幾乎不經過修改就輕鬆地部署到有任意數量 CPU 或 GPU 的 PC、伺服器或者行動裝置上。相比於 Theano,TensorFlow 還有一個優勢就是它極快的編譯速度,在定義新網絡結構時,Theano 通常需要長時間的編譯,因此嘗試新模型需要比較大的代價,而 TensorFlow 完全沒有這個問題。TensorFlow 還有功能強大的可視化組件 TensorBoard,能可視化網絡結構和訓練過程,對於觀察複雜的網絡結構和監控長時間、大規模的訓練很有幫助。TensorFlow 針對生產環境高度優化,它產品級的高質量代碼和設計都可以保證在生產環境中穩定運行,同時一旦 TensorFlow 廣泛地被工業界使用,將產生良性循環,成為深度學習領域的事實標準。
除了支持常見的網絡結構(卷積神經網絡(Convolutional Neural Network,CNN)、循環神經網絡(Recurent Neural Network,RNN))外,TensorFlow 還支持深度強化學習乃至其他計算密集的科學計算(如偏微分方程求解等)。TensorFlow 此前不支持 symbolic loop,需要使用 Python 循環而無法進行圖編譯優化,但最近新加入的 XLA 已經開始支持 JIT 和 AOT,另外它使用 bucketing trick 也可以比較高效地實現循環神經網絡。TensorFlow 的一個薄弱地方可能在於計算圖必須構建為靜態圖,這讓很多計算變得難以實現,尤其是序列預測中經常使用的 beam search。
TensorFlow 的用戶能夠將訓練好的模型方便地部署到多種硬體、作業系統平臺上,支持 Intel 和 AMD 的 CPU,通過 CUDA 支持 NVIDIA 的 GPU (最近也開始通過 OpenCL 支持 AMD 的 GPU,但沒有 CUDA 成熟),支持 Linux 和 Mac,最近在 0.12 版本中也開始嘗試支持 Windows。在工業生產環境中,硬體設備有些是最新款的,有些是用了幾年的老機型,來源可能比較複雜,TensorFlow 的異構性讓它能夠全面地支持各種硬體和作業系統。同時,其在 CPU 上的矩陣運算庫使用了 Eigen 而不是 BLAS 庫,能夠基於 ARM 架構編譯和優化,因此在行動裝置(Android 和 iOS)上表現得很好。
TensorFlow 在最開始發布時只支持單機,而且只支持 CUDA 6.5 和 cuDNN v2,並且沒有官方和其他深度學習框架的對比結果。在 2015 年年底,許多其他框架做了各種性能對比評測,每次 TensorFlow 都會作為較差的對照組出現。那個時期的 TensorFlow 真的不快,性能上僅和普遍認為很慢的 Theano 比肩,在各個框架中可以算是墊底。但是憑藉 Google 強大的開發實力,很快支持了新版的 cuDNN (目前支持cuDNN v5.1),在單 GPU 上的性能追上了其他框架。表 2-3 所示為 https://github.com/soumith/convnet-benchmarks 給出的各個框架在 AlexNet 上單 GPU 的性能評測。
表2-3 各深度學習框架在 AlexNet 上的性能對比
目前在單 GPU 的條件下,絕大多數深度學習框架都依賴於 cuDNN,因此只要硬體計算能力或者內存分配差異不大,最終訓練速度不會相差太大。但是對於大規模深度學習來說,巨大的數據量使得單機很難在有限的時間完成訓練。這時需要分布式計算使 GPU 集群乃至 TPU 集群並行計算,共同訓練出一個模型,所以框架的分布式性能是至關重要的。TensorFlow 在 2016 年 4 月開源了分布式版本,使用 16 塊 GPU 可達單 GPU 的 15 倍提速,在 50 塊 GPU 時可達到 40 倍提速,分布式的效率很高。目前原生支持的分布式深度學習框架不多,只有 TensorFlow、CNTK、DeepLearning4J、MXNet 等。不過目前 TensorFlow 的設計對不同設備間的通信優化得不是很好,其單機的 reduction 只能用 CPU 處理,分布式的通信使用基於 socket 的 RPC,而不是速度更快的 RDMA,所以其分布式性能可能還沒有達到最優。
Google 在 2016 年 2 月開源了 TensorFlow Serving,這個組件可以將 TensorFlow 訓練好的模型導出,並部署成可以對外提供預測服務的 RESTful 接口,如圖 2-2 所示。有了這個組件,TensorFlow 就可以實現應用機器學習的全流程:從訓練模型、調試參數,到打包模型,最後部署服務,名副其實是一個從研究到生產整條流水線都齊備的框架。這裡引用 TensorFlow 內部開發人員的描述:「 TensorFlow Serving 是一個為生產環境而設計的高性能的機器學習服務系統。它可以同時運行多個大規模深度學習模型,支持模型生命周期管理、算法實驗,並可以高效地利用 GPU 資源,讓 TensorFlow 訓練好的模型更快捷方便地投入到實際生產環境」。除了 TensorFlow 以外的其他框架都缺少為生產環境部署的考慮,而 Google 作為廣泛在實際產品中應用深度學習的巨頭可能也意識到了這個機會,因此開發了這個部署服務的平臺。TensorFlow Serving 可以說是一副王牌,將會幫 TensorFlow 成為行業標準做出巨大貢獻。
圖2-2 TensorFlow Serving 架構
TensorBoard 是 TensorFlow 的一組 Web 應用,用來監控 TensorFlow 運行過程,或可視化 Computation Graph。TensorBoard 目前支持五種可視化:標量(scalars)、圖片(images)、音頻(audio)、直方圖(histograms)和計算圖(Computation Graph)。TensorBoard 的 Events Dashboard 可以用來持續地監控運行時的關鍵指標,比如 loss、學習速率(learning rate)或是驗證集上的準確率(accuracy);Image Dashboard 則可以展示訓練過程中用戶設定保存的圖片,比如某個訓練中間結果用 Matplotlib 等繪製(plot)出來的圖片;Graph Explorer 則可以完全展示一個 TensorFlow 的計算圖,並且支持縮放拖曳和查看節點屬性。TensorBoard 的可視化效果如圖 2-3 和圖 2-4 所示。
圖2-3 TensorBoard 的 loss 標量的可視化
圖2-4 TensorBoard 的模型結構可視化
TensorFlow 擁有產品級的高質量代碼,有 Google 強大的開發、維護能力的加持,整體架構設計也非常優秀。相比於同樣基於 Python 的老牌對手 Theano,TensorFlow 更成熟、更完善,同時 Theano 的很多主要開發者都去了 Google 開發 TensorFlow(例如書籍 Deep Learning 的作者 Ian Goodfellow,他後來去了 OpenAI)。Google 作為巨頭公司有比高校或者個人開發者多得多的資源投入到 TensorFlow 的研發,可以預見,TensorFlow 未來的發展將會是飛速的,可能會把大學或者個人維護的深度學習框架遠遠甩在身後。
Caffe
官方網址:http://caffe.berkeleyvision.org/
GitHub:http://github.com/BVLC/caffe
Caffe 全稱為 Convolutional Architecture for Fast Feature Embedding,是一個被廣泛使用的開源深度學習框架(在 TensorFlow 出現之前一直是深度學習領域 GitHub star 最多的項目),目前由伯克利視覺學中心(Berkeley Vision and Learning Center,BVLC)進行維護。Caffe 的創始人是加州大學伯克利的 Ph.D.賈揚清,他同時也是TensorFlow的作者之一,曾工作於 MSRA、NEC 和 Google Brain,目前就職於 Facebook FAIR 實驗室。Caffe 的主要優勢包括如下幾點。
容易上手,網絡結構都是以配置文件形式定義,不需要用代碼設計網絡。
訓練速度快,能夠訓練 state-of-the-art 的模型與大規模的數據。
組件模塊化,可以方便地拓展到新的模型和學習任務上。
Caffe 的核心概念是 Layer,每一個神經網絡的模塊都是一個 Layer。Layer 接收輸入數據,同時經過內部計算產生輸出數據。設計網絡結構時,只需要把各個 Layer 拼接在一起構成完整的網絡(通過寫 protobuf 配置文件定義)。比如卷積的 Layer,它的輸入就是圖片的全部像素點,內部進行的操作是各種像素值與 Layer 參數的 convolution 操作,最後輸出的是所有卷積核 filter 的結果。每一個 Layer 需要定義兩種運算,一種是正向(forward)的運算,即從輸入數據計算輸出結果,也就是模型的預測過程;另一種是反向(backward)的運算,從輸出端的 gradient 求解相對於輸入的 gradient,即反向傳播算法,這部分也就是模型的訓練過程。實現新 Layer 時,需要將正向和反向兩種計算過程的函數都實現,這部分計算需要用戶自己寫 C++或者 CUDA (當需要運行在 GPU 時)代碼,對普通用戶來說還是非常難上手的。正如它的名字 Convolutional Architecture for Fast Feature Embedding 所描述的,Caffe 最開始設計時的目標只針對於圖像,沒有考慮文本、語音或者時間序列的數據,因此 Caffe 對卷積神經網絡的支持非常好,但對時間序列 RNN、LSTM 等支持得不是特別充分。同時,基於 Layer 的模式也對 RNN 不是非常友好,定義 RNN 結構時比較麻煩。在模型結構非常複雜時,可能需要寫非常冗長的配置文件才能設計好網絡,而且閱讀時也比較費力。
Caffe 的一大優勢是擁有大量的訓練好的經典模型(AlexNet、VGG、Inception)乃至其他 state-of-the-art (ResNet等)的模型,收藏在它的 Model Zoo (http://github.com/BVLC/ caffe/wiki/Model-Zoo)。因為知名度較高,Caffe 被廣泛地應用於前沿的工業界和學術界,許多提供源碼的深度學習的論文都是使用 Caffe 來實現其模型的。在計算機視覺領域 Caffe 應用尤其多,可以用來做人臉識別、圖片分類、位置檢測、目標追蹤等。雖然 Caffe 主要是面向學術圈和研究者的,但它的程序運行非常穩定,代碼質量比較高,所以也很適合對穩定性要求嚴格的生產環境,可以算是第一個主流的工業級深度學習框架。因為 Caffe 的底層是基於 C++的,因此可以在各種硬體環境編譯並具有良好的移植性,支持 Linux、Mac 和 Windows 系統,也可以編譯部署到行動裝置系統如 Android 和 iOS 上。和其他主流深度學習庫類似,Caffe 也提供了 Python 語言接口 pycaffe,在接觸新任務,設計新網絡時可以使用其 Python 接口簡化操作。不過,通常用戶還是使用 Protobuf 配置文件定義神經網絡結構,再使用 command line 進行訓練或者預測。Caffe 的配置文件是一個 JSON 類型的 .prototxt 文件,其中使用許多順序連接的 Layer 來描述神經網絡結構。Caffe 的二進位可執行程序會提取這些 .prototxt 文件並按其定義來訓練神經網絡。理論上,Caffe 的用戶可以完全不寫代碼,只是定義網絡結構就可以完成模型訓練了。Caffe 完成訓練之後,用戶可以把模型文件打包製作成簡單易用的接口,比如可以封裝成 Python 或 MATLAB 的 API 。不過在 .prototxt 文件內部設計網絡節構可能會比較受限,沒有像 TensorFlow 或者 Keras 那樣在 Python 中設計網絡結構方便、自由。更重要的是,Caffe 的配置文件不能用編程的方式調整超參數,也沒有提供像 Scikit-learn 那樣好用的 estimator 可以方便地進行交叉驗證、超參數的 Grid Search 等操作。Caffe 在 GPU 上訓練的性能很好(使用單塊 GTX 1080 訓練 AlexNet 時一天可以訓練上百萬張圖片),但是目前僅支持單機多 GPU 的訓練,沒有原生支持分布式的訓練。慶幸的是,現在有很多第三方的支持,比如雅虎開源的 CaffeOnSpark,可以藉助 Spark 的分布式框架實現 Caffe 的大規模分布式訓練。
Theano
官方網址:http://www.deeplearning.net/software/theano/
GitHub:http://github.com/Theano/Theano
Theano 誕生於2008年,由蒙特婁大學 Lisa Lab 團隊開發並維護,是一個高性能的符號計算及深度學習庫。因其出現時間早,可以算是這類庫的始祖之一,也一度被認為是深度學習研究和應用的重要標準之一。Theano 的核心是一個數學表達式的編譯器,專門為處理大規模神經網絡訓練的計算而設計。它可以將用戶定義的各種計算編譯為高效的底層代碼,並連結各種可以加速的庫,比如 BLAS、CUDA 等。Theano 允許用戶定義、優化和評估包含多維數組的數學表達式,它支持將計算裝載到 GPU (Theano 在 GPU 上性能不錯,但是 CPU 上較差)。與 Scikit-learn 一樣,Theano 也很好地整合了 NumPy,對 GPU 的透明讓 Theano 可以較為方便地進行神經網絡設計,而不必直接寫 CUDA 代碼。Theano 的主要優勢如下。
集成 NumPy,可以直接使用 NumPy 的 ndarray,API 接口學習成本低。
計算穩定性好,比如可以精準地計算輸出值很小的函數(像 log(1+x))。
動態地生成 C 或者 CUDA 代碼,用以編譯成高效的機器代碼。
因為 Theano 非常流行,有許多人為它編寫了高質量的文檔和教程,用戶可以方便地查找 Theano 的各種 FAQ,比如如何保存模型、如何運行模型等。不過 Theano 更多地被當作一個研究工具,而不是當作產品來使用。雖然 Theano 支持 Linux、Mac 和 Windows,但是沒有底層 C++的接口,因此模型的部署非常不方便,依賴於各種 Python 庫,並且不支持各種行動裝置,所以幾乎沒有在工業生產環境的應用。Theano 在調試時輸出的錯誤信息非常難以看懂,因此 DEBUG 時非常痛苦。同時,Theano 在生產環境使用訓練好的模型進行預測時性能比較差,因為預測通常使用伺服器 CPU(生產環境伺服器一般沒有 GPU,而且 GPU 預測單條樣本延遲高反而不如 CPU),但是 Theano 在 CPU 上的執行性能比較差。
Theano 在單 GPU 上執行效率不錯,性能和其他框架類似。但是運算時需要將用戶的 Python 代碼轉換成 CUDA 代碼,再編譯為二進位可執行文件,編譯複雜模型的時間非常久。此外,Theano 在導入時也比較慢,而且一旦設定了選擇某塊 GPU,就無法切換到其他設備。目前,Theano 在 CUDA 和 cuDNN 上不支持多 GPU,只在 OpenCL 和 Theano 自己的 gpuarray 庫上支持多 GPU 訓練,速度暫時還比不上 CUDA 的版本,並且 Theano 目前還沒有分布式的實現。不過,Theano 在訓練簡單網絡(比如很淺的 MLP)時性能可能比 TensorFlow 好,因為全部代碼都是運行時編譯,不需要像 TensorFlow 那樣每次 feed mini-batch 數據時都得通過低效的 Python 循環來實現。
Theano 是一個完全基於 Python (C++/CUDA 代碼也是打包為 Python 字符串)的符號計算庫。用戶定義的各種運算,Theano 可以自動求導,省去了完全手工寫神經網絡反向傳播算法的麻煩,也不需要像 Caffe 一樣為 Layer 寫 C++或 CUDA 代碼。Theano 對卷積神經網絡的支持很好,同時它的符號計算 API 支持循環控制(內部名scan),讓 RNN 的實現非常簡單並且高性能,其全面的功能也讓 Theano 可以支持大部分 state-of-the-art 的網絡。Theano 派生出了大量基於它的深度學習庫,包括一系列的上層封裝,其中有大名鼎鼎的 Keras,Keras 對神經網絡抽象得非常合適,以至於可以隨意切換執行計算的後端(目前同時支持 Theano 和 TensorFlow)。Keras 比較適合在探索階段快速地嘗試各種網絡結構,組件都是可插拔的模塊,只需要將一個個組件(比如卷積層、激活函數等)連接起來,但是設計新模塊或者新的 Layer 就不太方便了。除 Keras 外,還有學術界非常喜愛的 Lasagne,同樣也是 Theano 的上層封裝,它對神經內網絡的每一層的定義都非常嚴謹。另外,還有 scikit-neuralnetwork、nolearn 這兩個基於 Lasagne 的上層封裝,它們將神經網絡抽象為兼容 Scikit-learn 接口的 classifier 和 regressor,這樣就可以方便地使用 Scikit-learn 中經典的 fit、transform、score 等操作。除此之外,Theano 的上層封裝庫還有 blocks、deepy、pylearn2 和 Scikit-theano,可謂是一個龐大的家族。如果沒有 Theano,可能根本不會出現這麼多好用的 Python 深度學習庫。同樣,如果沒有 Python 科學計算的基石 NumPy,就不會有 SciPy、Scikit-learn 和 Scikit-image,可以說 Theano 就是深度學習界的 NumPy,是其他各類 Python 深度學習庫的基石。雖然 Theano 非常重要,但是直接使用 Theano 設計大型的神經網絡還是太煩瑣了,用 Theano 實現 Google Inception 就像用 NumPy 實現一個支持向量機(SVM)。且不說很多用戶做不到用 Theano 實現一個 Inception 網絡,即使能做到但是否有必要花這個時間呢?畢竟不是所有人都是基礎科學工作者,大部分使用場景還是在工業應用中。所以簡單易用是一個很重要的特性,這也就是其他上層封裝庫的價值所在:不需要總是從最基礎的 tensor 粒度開始設計網絡,而是從更上層的 Layer 粒度設計網絡。
Torch
官方網址:http://torch.ch/
GitHub:http://github.com/torch/torch7
Torch 給自己的定位是 LuaJIT 上的一個高效的科學計算庫,支持大量的機器學習算法,同時以 GPU 上的計算優先。Torch 的歷史非常悠久,但真正得到發揚光大是在 Facebook 開源了其深度學習的組件之後,此後包括 Google、Twitter、NYU、IDIAP、Purdue 等組織都大量使用 Torch。Torch 的目標是讓設計科學計算算法變得便捷,它包含了大量的機器學習、計算機視覺、信號處理、並行運算、圖像、視頻、音頻、網絡處理的庫,同時和 Caffe 類似,Torch 擁有大量的訓練好的深度學習模型。它可以支持設計非常複雜的神經網絡的拓撲圖結構,再並行化到 CPU 和 GPU 上,在 Torch 上設計新的 Layer 是相對簡單的。它和 TensorFlow 一樣使用了底層 C++加上層腳本語言調用的方式,只不過 Torch 使用的是 Lua。Lua 的性能是非常優秀的(該語言經常被用來開發遊戲),常見的代碼可以通過透明的 JIT 優化達到 C 的性能的80%;在便利性上,Lua 的語法也非常簡單易讀,擁有漂亮和統一的結構,易於掌握,比寫 C/C++簡潔很多;同時,Lua 擁有一個非常直接的調用 C 程序的接口,可以簡便地使用大量基於 C 的庫,因為底層核心是 C 寫的,因此也可以方便地移植到各種環境。Lua 支持 Linux、Mac,還支持各種嵌入式系統(iOS、Android、FPGA 等),只不過運行時還是必須有 LuaJIT 的環境,所以工業生產環境的使用相對較少,沒有 Caffe 和 TensorFlow 那麼多。
為什麼不簡單地使用 Python 而是使用 LuaJIT 呢?官方給出了以下幾點理由。
LuaJIT 的通用計算性能遠勝於 Python,而且可以直接在 LuaJIT 中操作 C 的 pointers。
Torch 的框架,包含 Lua 是自洽的,而完全基於 Python 的程序對不同平臺、系統移植性較差,依賴的外部庫較多。
LuaJIT 的 FFI 拓展接口非常易學,可以方便地連結其他庫到 Torch 中。Torch 中還專門設計了 N-Dimension array type 的對象 Tensor,Torch 中的 Tensor 是一塊內存的視圖,同時一塊內存可能有許多視圖(Tensor)指向它,這樣的設計同時兼顧了性能(直接面向內存)和便利性。同時,Torch 還提供了不少相關的庫,包括線性代數、卷積、傅立葉變換、繪圖和統計等,如圖 2-5 所示。
圖2-5 Torch 提供的各種數據處理的庫
Torch 的 nn 庫支持神經網絡、自編碼器、線性回歸、卷積網絡、循環神經網絡等,同時支持定製的損失函數及梯度計算。Torc h因為使用了 LuaJIT,因此用戶在 Lua 中做數據預處理等操作可以隨意使用循環等操作,而不必像在 Python 中那樣擔心性能問題,也不需要學習 Python 中各種加速運算的庫。不過,Lua 相比 Python 還不是那麼主流,對大多數用戶有學習成本。Torch 在 CPU 上的計算會使用 OpenMP、SSE 進行優化,GPU 上使用 CUDA、cutorch、cunn、cuDNN 進行優化,同時還有 cuda-convnet 的 wrapper。Torch 有很多第三方的擴展可以支持 RNN,使得 Torch 基本支持所有主流的網絡。和 Caffe 類似的是,Torch 也是主要基於 Layer 的連接來定義網絡的。Torch 中新的 Layer 依然需要用戶自己實現,不過定義新 Layer 和定義網絡的方式很相似,非常簡便,不像 Caffe 那麼麻煩,用戶需要使用 C++或者 CUDA 定義新 Layer。同時,Torch 屬於命令式編程模式,不像 Theano、TensorFlow 屬於聲明性編程(計算圖是預定義的靜態的結構),所以用它實現某些複雜操作(比如 beam search)比 Theano 和 TensorFlow 方便很多。
Lasagne
官網網址:http://lasagne.readthedocs.io/
GitHub:http://github.com/Lasagne/Lasagne
Lasagne 是一個基於 Theano 的輕量級的神經網絡庫。它支持前饋神經網絡,比如卷積網絡、循環神經網絡、LSTM 等,以及它們的組合;支持許多優化方法,比如 Nesterov momentum、RMSprop、ADAM 等;它是 Theano 的上層封裝,但又不像 Keras 那樣進行了重度的封裝,Keras 隱藏了 Theano 中所有的方法和對象,而 Lasagne 則是借用了 Theano 中很多的類,算是介於基礎的 Theano 和高度抽象的 Keras 之間的一個輕度封裝,簡化了操作同時支持比較底層的操作。Lasagne 設計的六個原則是簡潔、透明、模塊化、實用、聚焦和專注。
Keras
官方網址:http://keras.io
GitHub:http://github.com/fchollet/keras
Keras 是一個崇尚極簡、高度模塊化的神經網絡庫,使用 Python 實現,並可以同時運行在 TensorFlow 和 Theano 上。它旨在讓用戶進行最快速的原型實驗,讓想法變為結果的這個過程最短。Theano 和 TensorFlow 的計算圖支持更通用的計算,而 Keras 則專精於深度學習。Theano 和 TensorFlow 更像是深度學習領域的 NumPy,而 Keras 則是這個領域的 Scikit-learn。它提供了目前為止最方便的 API,用戶只需要將高級的模塊拼在一起,就可以設計神經網絡,它大大降低了編程開銷(code overhead)和閱讀別人代碼時的理解開銷(cognitive overhead)。它同時支持卷積網絡和循環網絡,支持級聯的模型或任意的圖結構的模型(可以讓某些數據跳過某些 Layer 和後面的 Layer 對接,使得創建 Inception 等複雜網絡變得容易),從 CPU 上計算切換到 GPU 加速無須任何代碼的改動。因為底層使用 Theano 或 TensorFlow,用 Keras 訓練模型相比於前兩者基本沒有什麼性能損耗(還可以享受前兩者持續開發帶來的性能提升),只是簡化了編程的複雜度,節約了嘗試新網絡結構的時間。可以說模型越複雜,使用 Keras 的收益就越大,尤其是在高度依賴權值共享、多模型組合、多任務學習等模型上,Keras 表現得非常突出。Keras 所有的模塊都是簡潔、易懂、完全可配置、可隨意插拔的,並且基本上沒有任何使用限制,神經網絡、損失函數、優化器、初始化方法、激活函數和正則化等模塊都是可以自由組合的。Keras 也包括絕大部分 state-of-the-art 的 Trick,包括 Adam、RMSProp、Batch Normalization、PReLU、ELU、LeakyReLU 等。同時,新的模塊也很容易添加,這讓 Keras 非常適合最前沿的研究。Keras 中的模型也都是在 Python 中定義的,不像 Caffe、CNTK 等需要額外的文件來定義模型,這樣就可以通過編程的方式調試模型結構和各種超參數。在 Keras 中,只需要幾行代碼就能實現一個 MLP,或者十幾行代碼實現一個 AlexNet,這在其他深度學習框架中基本是不可能完成的任務。Keras 最大的問題可能是目前無法直接使用多 GPU,所以對大規模的數據處理速度沒有其他支持多 GPU 和分布式的框架快。Keras 的編程模型設計和 Torch 很像,但是相比 Torch,Keras 構建在 Python 上,有一套完整的科學計算工具鏈,而 Torch 的程式語言 Lua 並沒有這樣一條科學計算工具鏈。無論從社區人數,還是活躍度來看,Keras 目前的增長速度都已經遠遠超過了 Torch。
MXNet
官網網址:http://mxnet.io
GitHub:http://github.com/dmlc/mxnet
MXNet 是 DMLC(Distributed Machine Learning Community)開發的一款開源的、輕量級、可移植的、靈活的深度學習庫,它讓用戶可以混合使用符號編程模式和指令式編程模式來最大化效率和靈活性,目前已經是 AWS 官方推薦的深度學習框架。MXNet 的很多作者都是中國人,其最大的貢獻組織為百度,同時很多作者來自 cxxnet、minerva 和 purine2 等深度學習項目,可謂博採眾家之長。它是各個框架中率先支持多 GPU 和分布式的,同時其分布式性能也非常高。MXNet 的核心是一個動態的依賴調度器,支持自動將計算任務並行化到多個 GPU 或分布式集群(支持 AWS、Azure、Yarn 等)。它上層的計算圖優化算法可以讓符號計算執行得非常快,而且節約內存,開啟 mirror 模式會更加省內存,甚至可以在某些小內存 GPU 上訓練其他框架因顯存不夠而訓練不了的深度學習模型,也可以在行動裝置(Android、iOS)上運行基於深度學習的圖像識別等任務。此外,MXNet 的一個很大的優點是支持非常多的語言封裝,比如 C++、Python、R、Julia、Scala、Go、MATLAB 和 JavaScript 等,可謂非常全面,基本主流的腳本語言全部都支持了。在 MXNet 中構建一個網絡需要的時間可能比 Keras、Torch 這類高度封裝的框架要長,但是比直接用 Theano 等要快。MXNet 的各級系統架構(下面為硬體及作業系統底層,逐層向上為越來越抽象的接口)如圖2-6所示。
圖2-6 MXNet 系統架構
DIGITS
官方網址:http://developer.nvidia.com/digits
GitHub: http://github.com/NVIDIA/DIGITS
DIGITS(Deep Learning GPU Training System)不是一個標準的深度學習庫,它可以算是一個 Caffe 的高級封裝(或者 Caffe 的 Web 版培訓系統)。因為封裝得非常重,以至於你不需要(也不能)在 DIGITS 中寫代碼,即可實現一個深度學習的圖片識別模型。在 Caffe 中,定義模型結構、預處理數據、進行訓練並監控訓練過程是相對比較煩瑣的,DIGITS 把所有這些操作都簡化為在瀏覽器中執行。它可以算作 Caffe 在圖片分類上的一個漂亮的用戶可視化界面(GUI),計算機視覺的研究者或者工程師可以非常方便地設計深度學習模型、測試準確率,以及調試各種超參數。同時使用它也可以生成數據和訓練結果的可視化統計報表,甚至是網絡的可視化結構圖。訓練好的 Caffe 模型可以被 DIGITS 直接使用,上傳圖片到伺服器或者輸入 url 即可對圖片進行分類。
CNTK
官方網址:http://cntk.ai
GitHub:http://github.com/Microsoft/CNTK
CNTK(Computational Network Toolkit)是微軟研究院(MSR)開源的深度學習框架。它最早由 start the deep learning craze 的演講人創建,目前已經發展成一個通用的、跨平臺的深度學習系統,在語音識別領域的使用尤其廣泛。CNTK 通過一個有向圖將神經網絡描述為一系列的運算操作,這個有向圖中子節點代表輸入或網絡參數,其他節點代表各種矩陣運算。CNTK 支持各種前饋網絡,包括 MLP、CNN、RNN、LSTM、Sequence-to-Sequence 模型等,也支持自動求解梯度。CNTK 有豐富的細粒度的神經網絡組件,使得用戶不需要寫底層的 C++或 CUDA,就能通過組合這些組件設計新的複雜的 Layer。CNTK 擁有產品級的代碼質量,支持多機、多 GPU 的分布式訓練。
CNTK 設計是性能導向的,在 CPU、單 GPU、多 GPU,以及 GPU 集群上都有非常優異的表現。同時微軟最近推出的 1-bit compression 技術大大降低了通信代價,讓大規模並行訓練擁有了很高的效率。CNTK 同時宣稱擁有很高的靈活度,它和 Caffe 一樣通過配置文件定義網絡結構,再通過命令行程序執行訓練,支持構建任意的計算圖,支持 AdaGrad、RmsProp 等優化方法。它的另一個重要特性就是拓展性,CNTK 除了內置的大量運算核,還允許用戶定義他們自己的計算節點,支持高度的定製化。CNTK 在 2016 年 9 月發布了對強化學習的支持,同時,除了通過寫配置文件的方式定義網絡結構,CNTK 還將支持其他語言的綁定,包括 Python、C++和 C#,這樣用戶就可以用編程的方式設計網絡結構。CNTK 與 Caffe一樣也基於 C++並且跨平臺,大部分情況下,它的部署非常簡單。PC 上支持 Linux、Mac 和 Windows,但是它目前不支持 ARM 架構,限制了其在行動裝置上的發揮。圖 2-7 所示為 CNTK 目前的總體架構圖。
圖2-7 CNTK的總體架構圖
CNTK 原生支持多 GPU 和分布式,從官網公布的對比評測來看,性能非常不錯。在多 GPU 方面,CNTK 相對於其他的深度學習庫表現得更突出,它實現了 1-bit SGD 和自適應的 mini-batching。圖 2-8 所示為 CNTK 官網公布的在 2015 年 12 月的各個框架的性能對比。在當時,CNTK 是唯一支持單機 8 塊 GPU 的框架,並且在分布式系統中可以超越 8 塊 GPU 的性能。
圖2-8 CNTK與各個框架的性能對比
Deeplearning4J
官方網址:http://deeplearning4j.org/
GitHub: http://github.com/deeplearning4j/deeplearning4j
Deeplearning4J(簡稱DL4J)是一個基於 Java 和 Scala 的開源的分布式深度學習庫,由 Skymind 於 2014 年 6 月發布,其核心目標是創建一個即插即用的解決方案原型。埃森哲、雪弗蘭、博斯諮詢和 IBM 等都是 DL4J 的客戶。DL4J 擁有一個多用途的 n-dimensional array 的類,可以方便地對數據進行各種操作;擁有多種後端計算核心,用以支持 CPU 及 GPU 加速,在圖像識別等訓練任務上的性能與 Caffe 相當;可以與 Hadoop 及 Spark 自動整合,同時可以方便地在現有集群(包括但不限於AWS,Azure等)上進行擴展,同時 DL4J 的並行化是根據集群的節點和連接自動優化,不像其他深度學習庫那樣可能需要用戶手動調整。DL4J 選擇 Java 作為其主要語言的原因是,目前基於 Java 的分布式計算、雲計算、大數據的生態非常龐大。用戶可能擁有大量的基於 Hadoop 和 Spark 的集群,因此在這類集群上搭建深度學習平臺的需求便很容易被 DL4J 滿足。同時 JVM 的生態圈內還有數不勝數的 Library 的支持,而 DL4J 也創建了 ND4J,可以說是 JVM 中的 NumPy,支持大規模的矩陣運算。此外,DL4J 還有商業版的支持,付費用戶在出現問題時可以通過電話諮詢尋求支持。
Chainer
官方網址:http://chainer.org
GitHub:http://github.com/pfnet/chainer
Chainer 是由日本公司 Preferred Networks 於 2015 年 6 月發布的深度學習框架。Chainer 對自己的特性描述如下。
Powerful:支持 CUDA 計算,只需要幾行代碼就可以使用 GPU 加速,同時只需少許改動就可以運行在多 GPU 上。
Flexible:支持多種前饋神經網絡,包括卷積網絡、循環網絡、遞歸網絡,支持運行中動態定義的網絡(Define-by-Run)。
Intuitive:前饋計算可以引入 Python 的各種控制流,同時反向傳播時不受幹擾,簡化了調試錯誤的難度。
絕大多數的深度學習框架是基於「Define-and-Run」的,也就是說,需要首先定義一個網絡,再向網絡中 feed 數據(mini-batch)。因為網絡是預先靜態定義的,所有的控制邏輯都需要以 data 的形式插入網絡中,包括像 Caffe 那樣定義好網絡結構文件,或者像 Theano、Torch、TensorFlow 等使用程式語言定義網絡。而 Chainer 則相反,網絡是在實際運行中定義的,Chainer 存儲歷史運行的計算結果,而不是網絡的結構邏輯,這樣就可以方便地使用 Python 中的控制流,所以無須其他工作就可以直接在網絡中使用條件控制和循環。
Leaf
官方網址:http://autumnai.com/leaf/book
GitHub:http://github.com/autumnai/leaf
Leaf 是一個基於 Rust 語言的直觀的跨平臺的深度學習乃至機器智能框架,它擁有一個清晰的架構,除了同屬 Autumn AI 的底層計算庫 Collenchyma,Leaf 沒有其他依賴庫。它易於維護和使用,並且擁有非常高的性能。Leaf 自身宣傳的特點是為 Hackers 定製的,這裡的 Hackers 是指希望用最短的時間和最少的精力實現機器學習算法的技術極客。它的可移植性非常好,可以運行在 CPU、GPU 和 FPGA 等設備上,可以支持有任何作業系統的 PC、伺服器,甚至是沒有作業系統的嵌入式設備,並且同時支持 OpenCL 和 CUDA。Leaf 是 Autumn AI 計劃的一個重要組件,後者的目標是讓人工智慧算法的效率提高 100 倍。憑藉其優秀的設計,Leaf 可以用來創建各種獨立的模塊,比如深度強化學習、可視化監控、網絡部署、自動化預處理和大規模產品部署等。
Leaf 擁有最簡單的 API,希望可以最簡化用戶需要掌握的技術棧。雖然才剛誕生不久,Leaf 就已經躋身最快的深度學習框架之一了。圖 2-9 所示為 Leaf 官網公布的各個框架在單 GPU 上訓練 VGG 網絡的計算時間(越小越好)的對比(這是和早期的 TensorFlow 對比,最新版的 TensorFlow 性能已經非常好了)。
圖2-9 Leaf 和各深度學習框架的性能對比(深色為 forawrd,淺色為 backward)
DSSTNE
GitHub:http://github.com/amznlabs/amazon-dsstne
DSSTNE(Deep Scalable Sparse Tensor Network Engine)是亞馬遜開源的稀疏神經網絡框架,在訓練非常稀疏的數據時具有很大的優勢。DSSTNE 目前只支持全連接的神經網絡,不支持卷積網絡等。和 Caffe 類似,它也是通過寫一個 JSON 類型的文件定義模型結構,但是支持非常大的 Layer(輸入和輸出節點都非常多);在激活函數、初始化方式及優化器方面基本都支持了 state-of-the-art 的方法,比較全面;支持大規模分布式的 GPU 訓練,不像其他框架一樣主要依賴數據並行,DSSTNE 支持自動的模型並行(使用數據並行需要在訓練速度和模型準確度上做一定的 trade-off,模型並行沒有這個問題)。
在處理特徵非常多(上億維)的稀疏訓練數據時(經常在推薦、廣告、自然語言處理任務中出現),即使一個簡單的三個隱層的 MLP(Multi-Layer Perceptron)也會變成一個有非常多參數的模型(可能高達上萬億)。以傳統的稠密矩陣的方式訓練方法很難處理這麼多的模型參數,更不必提超大規模的數據量,而 DSSTNE 有整套的針對稀疏數據的優化,率先實現了對超大稀疏數據訓練的支持,同時在性能上做了非常大的改進。
在 DSSTNE 官方公布的測試中,DSSTNE 在 MovieLens 的稀疏數據上,在單 M40 GPU 上取得了比 TensorFlow 快 14.8 倍的性能提升(注意是和老版的 TensorFlow 比較),如圖 2-10 所示。一方面是因為 DSSTNE 對稀疏數據的優化;另一方面是 TensorFlow 在數據傳輸到 GPU 上時花費了大量時間,而 DSSTNE 則優化了數據在GPU內的保留;同時 DSSTNE 還擁有自動模型並行功能,而 TensorFlow 中則需要手動優化,沒有自動支持。
圖2-10 DSSTNE 在稀疏數據上與 TensorFlow 的性能對比
雷鋒網(公眾號:雷鋒網)按:在下周二(2月28日)雷鋒網硬創公開課欄目將會推出黃文堅老師的公開課《深度學習之經典卷積神經網絡的技術淺析》(點擊了解詳情),歡迎大家報名!
雷鋒網版權文章,未經授權禁止轉載。詳情見轉載須知。