Spark與深度學習框架——H2O、deeplearning4j、SparkNet
摘要: 引言:你可能對使用Spark服務比較感興趣。Spark已經提供了很多功能,也有一個好用的界面,而且背後有強大的社區,開發者十分活躍,這也是人們對Spark寄予厚望的原因。深度學習是當前正在進行中的Spark項目之一。
引言:你可能對使用Spark服務比較感興趣。Spark已經提供了很多功能,也有一個好用的界面,而且背後有強大的社區,開發者十分活躍,這也是人們對Spark寄予厚望的原因。深度學習是當前正在進行中的Spark項目之一。本文我們將介紹一些Spark能用的深度學習框架。
本文選自《Spark:大數據集群計算的生產實踐》。
深度學習因其高準確率及通用性,成為機器學習中最受關注的領域。這種演算法在2011—2012年期間出現,並超過了很多競爭對手。最開始,深度學習在音頻及圖像識別方面取得了成功。此外,像機器翻譯之類的自然語言處理或者畫圖也能使用深度學習演算法來完成。深度學習是自1980年以來就開始被使用的一種神經網路。神經網路被看作能進行普適近似(universal approximation)的一種機器。換句話說,這種網路能模仿任何其他函數。例如,深度學習演算法能創建一個識別動物圖片的函數:給一張動物的圖片,它能分辨出圖片上的動物是一隻貓還是一隻狗。深度學習可以看作是組合了許多神經網路的一種深度結構。
與其他已有的機器學習演算法相比,深度學習需要大量參數及訓練數據。這也是我們介紹能在Spark上運行的深度學習框架的原因。要想在企業環境中穩定地進行深度學習的訓練,必須要有一個可靠而快速的分散式引擎。 Spark被視為目前最適合運行深度學習演算法的平台,是因為:- 基於內存的處理架構對於使用機器學習的迭代計算,特別是深度學習,十分適合。
- Spark的幾個生態系統如MLlib及Tachyon對於開發深度學習模型很有用。
本文我們將介紹一些Spark能用的深度學習框架。這些框架和深度學習一樣,都是比較新的庫。很可能你在使用它們的過程中遇到一些bug或者缺少一些操作工具,但是報告問題(issue)及發送補丁將會使它更加成熟。
H2O
H2O是用h2o.ai開發的具有可擴展性的機器學習框架,它不限於深度學習。H2O支持許多API(例如,R、Python、Scala和Java)。當然它是開源軟體,所以要研究它的代碼及演算法也很容易。H2O框架支持所有常見的資料庫及文件類型,可以輕鬆將模型導出為各種類型的存儲。深度學習演算法是在另一個叫作sparkling-water的庫中實現的(http://h2o.ai/product/sparkling-water/)。它主要由h2o.ai開發。要運行sparkling-water,需要使用Spark 1.3或以上的版本。
安裝
1.首先需要從h2o網站下載最新的sparking-water。
(http://h2o-release.s3.amazonaws.com/sparkling-water/rel-1.3/1/index.html)2.把它指向Spark的安裝目錄。$ export Spark_HOME=/path/to/your/spark
3.啟動sparkling-shell,這個介面與spark-shell類似。
$ cd ~/Downloads$ unzip Sparkling-water-1.3.1.zip$ cd Sparkling-water-1.3.1$ bin/Sparkling-shell
sparkling-water源碼中包含幾個例子。不幸的是,有些例子在Spark 1.5.2版本上無法正常運行。深度學習的demo也有相同的問題。你得等待這些問題被解決,或者自己寫幾個能在Spark運行的補丁。
deeplearning4j
deeplearning4j是由Skymind開發的,Skymind是一家致力於為企業進行商業化深度學習的公司。deeplearning4j框架是創建來在Hadoop及Spark上運行的。這個設計用於商業環境而不是許多深度學習框架及庫目前所大量應用的研究領域。Skymind是主要的支持者,但deeplearning4j是開源軟體,因此也歡迎大家提交補丁。deeplearning4j框架中實現了如下演算法:
- 受限玻爾茲曼機(Restricted Boltzmann Machine)
- 卷積神經網路(Convolutional Neural Network)
- 循環神經網路(Recurrent Neural Network)
- 遞歸自編碼器(Recursive Autoencoder)
- 深度信念網路(Deep-Belief Network)
- 深度自編碼器(Deep Autoencoder)
- 棧式降噪自編碼(Stacked Denoising Autoencoder)
這裡要注意的是,這些模型能在細粒度級別進行配置。你可以設置隱藏的層數、每個神經元的激活函數以及迭代的次數。deeplearning4j提供了不同種類的網路實現及靈活的模型參數。Skymind也開發了許多工具,對於更穩定地運行機器學習演算法很有幫助。下面列出了其中的一些工具。
Canova (https://github.com/deeplearning4j/Canoba)是一個向量庫。機器學習演算法能以向量格式處理所有數據。所有的圖片、音頻及文本數據必須用某種方法轉換為向量。雖然訓練機器學習模型是十分常見的工作,但它會重新造輪子還會引起bug。Canova能為你做這種轉換。Canova當前支持的輸入數據格式為:
-- CSV--原始文本格式(推文、文檔)
--圖像(圖片、圖畫)--定製文件格式(例如MNIST)- 由於Canova主要是用Java編寫的,所以它能運行在所有的JVM平台上。因此,可以在Spark集群上使用它。即使你不做機器學習,Canova對你的機器學習任務可能也會有所裨益。
- nd4j(https://github.com/deeplearning4j/nd4j)**有點像是一個numpy,Python中的SciPy工具。**此工具提供了線性代數、向量計算及操縱之類的科學計算。它也是用Java編寫的。你可以根據自己的使用場景來搭配使用這些工具。需要注意的一點是,nd4j支持GPU功能。由於現代計算硬體還在不斷發展,有望達到更快速的計算。
- dl4j-spark-ml (https://github.com/deeplearning4j/dl4j-spark-ml)**是一個Spark包,使你能在Spark上輕鬆運行deeplearning4j。**使用這個包,就能輕鬆在Spark上集成deeplearning4j,因為它已經被上傳到了Spark包的公共代碼庫(http://spark-packages.org/package/deeplearning4j/dl4j-Spark-ml)。
因此,如果你要在Spark上使用deeplearning4j,我們推薦通過dl4j-spark-ml包來實現。與往常一樣,必須下載或自己編譯Spark源碼。這裡對Spark版本沒有特別要求,就算使用最早的版本也可以。deeplearning4j項目準備了樣例存儲庫。要在Spark上使用deeplearning4j,dl4j-Spark-ml-examples是可參考的最佳示例(https:// http://github.com/deeplearning4j/dl4j-Spark-ml-examples)。下面列出如何下載及編譯這個代碼庫。
$ git clone git@github.com:deeplearning4j/dl4j-spark-mlexamples.git$ cd dl4j-Spark-ml-examples$ mvn clean package -DSpark.version=1.5.2 -DHadoop.version=2.6.0
編譯類位於target目錄下,但是可以通過bin/run-example腳本運行這些例子。當前有三種類型的例子:
- ml.JavaIrisClassfication——鳶尾花(iris flower)數據集分類。
- ml.JavaLfwClassfication——LFW人臉資料庫分類。
- ml.JavaMnistClassfication——MNIST手寫數據分類。
我們選擇第3個例子,對MNIST手寫數據集運行分類模型的訓練。在運行這個示例之前,需要從MNIST站點下載訓練數據(Index of /exdb mnist/)。或者,你可以使用下面的命令下載:
## 下載手寫數據的圖像$ wget http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz$ gunzip train-images-idx3-ubyte## 下載與上述圖像對應的標籤$ wget http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz$ gunzip train-labels-idx1-ubyteAnd the put the two files on data direcotry under dj4j-spark-ml-examples.$ mv train-images-idx3-ubyte /path/to/dl4j-spark-ml-examples/data$ mv train-labels-idx1-ubyte /path/to/dj4j-spark-ml-examples/data
差不多可以開始運行訓練進程了。你需要注意的最後一點是Spark executor及driver的內存大小,因為 MNIST數據集和它的訓練模型將會很大。它們要用到大量內存,因此我們建議你提前修改bin/run-example腳本中設置的內存大小。可以通過如下命令修改bin/run-example腳本的最後一行:
exec spark-submit --packages "deeplearning4j:dl4j-spark-ml:0.4-rc0" --master $EXAMPLE_MASTER --class $EXAMPLE_CLASS --driver-memory 8G # <- Changed from 1G --executor-memory 8G # <- Changed from 4G "$SPARK_EXAMPLES_JAR" "$@"
現在開始訓練:
$ MASTER=local[4] bin/run-example ml.JavaMnistClassfication
為了指定本地Spark的master配置,我們已經在bin/run-example腳本的前面設置了MASTER環境變數。這種訓練需要花一些時間,由你的環境及機器規格決定。這個例子運行了一種叫作「卷積神經網路」的神經網路。其參數細節是通過MultiLayerConfiguration類設置的。由於deeplearning4j有一個Java介面,就算你不習慣Spark的Scala語言也沒關係,它是很容易引入的。下面簡單解釋一下這個例子中的卷積神經網路參數。
- seed——此神經網路會使用像初始網路參數這樣的隨機參數,這個種子就用於產生這些參數。有了這個種子參數,在開發機器學習模型的過程中更容易進行測試與調試。 batchSize——像遞度下降之類的迭代演算法,在更新模型之前會匯總一些更新值,batchSize指定進行更新值計算的樣本數。
- iterations——由一個迭代進程保持模型參數的更新。這個參數決定了此迭代處理的次數。通常來說,迭代越長,收斂的概率越高。
- optimizationAlgo——運行前述的迭代進程,必須用到幾種方法。隨機梯度下降(Stochastic Gradient Descent,SGD)是目前為止最先進的方法,這種方法相對來講不會落入局部最小值,還能持續搜索全局最小值。
- layer——它是深度學習演算法的核心配置。這個深度學習神經網路有幾個名為layer的網路組。這個參數決定了在每一層中使用哪種類型的層。例如,在卷積神經網路的案例中,ConvolutionLayer被用於從輸入的圖像中提取出特徵。這個層能學習一個給定的圖片有哪種類型的特徵。在一開始就放置這個層,將改善整個神經網路預測的精確性。每個層也能用給定的參數進行配置。new ConvolutionLayer.Builder(10, 10) .nIn(nChannels) // 輸入元素的數目 .nOut(6) // 輸出元素的數目 .weightInit(WeightInit.DISTRIBUTION) // 參數矩陣的初始化方法 .activation("sigmoid") // 激活函數的類型 *build())
上圖展現了神經網路的通用結構。由於ConvolutionalLayer也是一種神經網路,兩種網路的部件基本上是相同的。神經網路有一個輸入(x)及輸出(y)。它們都是向量格式的數據。在上圖中,輸入為一個四維向量,而輸出也是一個四維向量。輸出向量y是怎樣計算出來的呢?每層都有一個參數矩陣。在本例中,它們用W表示。x與W相乘得到下一個向量。為了增強這個模型的表達,這個向量被傳給某個非線性激活函數(σ),例如邏輯sigmoid函數(logistic sigmoid function)、Softmax函數。使用這個非線性函數,神經網路就能逼近任意類型的函數。然後用z與另一個參數矩陣W相乘,並再次應用激活函數σ 。
你可以看到ConvolutionLayer的每個配置。nIn及nOut是輸入向量vector(x)及輸出向量vector(z)的維度。activation是這個層的激活函數,由邏輯sigmoid函數與修正線性單元所選擇。根據你的問題,輸入及輸出的維度能被立即確定。其他參數應當通過網格搜索來優化,這一點將在後面講述。
每一層(layer)的選擇我們自己常常是很難決定的。這需要了解一些知識,而且對要解決的特定問題要有一定的研究。deeplearning4j項目也提供了一份介紹性文檔(http://deeplearning4j.org/convolutionalnets.html)。雖然理解這份文檔需要一點數學及線性代數知識,但它仍然是描述卷積神經網路工作原理的最簡單的文檔。
- backprop——反向傳播(backpropagation)是目前用於更新模型參數(W)最先進的方法。因此,這個參數應當總是true。
- pretrain——由於有預訓練(pretraining),多層網路能從輸入數據提取出特徵,獲得經過優化的初始參數。也推薦把它設為true。
在這裡我們無法描述機器學習的全部細節。但是通常來說,這些演算法主要用於圖像識別、文本處理及垃圾郵件過濾等場景。deeplearning4j的官方站點上(http://deeplearning4j.org)不僅有對如何deeplearning4j的介紹,也有對深度學習的一般討論,你還能學到前沿的技術與概念。
SparkNet
SparkNet由加州大學伯克利分校AMP實驗室於2015年11月發布。而Spark最早就是由AMP實驗室開發的。因此,說SparkNet 是「運行在Spark上的官方機器學習庫」一點兒也不為過。此庫提供了讀取RDD的介面,以及兼容深度學習框架Caffe(http://caffe.berkeleyvision.org/)的介面。SparkNet通過採用隨機梯度下降(Stochastic Gradient Descent)獲得了簡單的並行模式。SparkNet job能通過Spark-submit提交。你可以很輕鬆地使用這個新庫。
SparkNet的架構很簡單。SparkNet負責分散式處理,而核心的學習過程則委託給Caffe框架。SparkNet通過Java native訪問Caffee框架提供的C API。Caffee是用C++實現的,Caffe的C包裝器寫在SparkNet的libcaffe目錄下。所以SparkNet的整體代碼庫相對較小。Java代碼(CaffeLibrary.java)進一步包裝了這個庫。為了在Scala世界裡使用CaffeLibrary,Caffe還提供了CaffeNet。下圖展現了CaffeNet的層級。
閱讀原文請點擊推薦閱讀:
※關於零基礎學習 Python 有什麼好的建議?
※Python Django 開發web,是重寫的admin,還是用自帶的admin?
※django優秀的github項目推薦?
※Django 1.6 下模板怎麼用?