Apache Spark上でBigDLのtutorialを動かしてみたのでメモ。BigDLの設定とtutorialを動かすところまでを書きます。BigDLのAPIとかプログラミング部分はノータッチです。

BigDLとは?

Apache Spark上で動作するTorchをモデルにしたディープラーニングライブラリ。Spark上で動作するのでHadoopのエコシステムと相性が良さそう。

どういう比較条件かは分からないが、単一のXeon上で動作するCaffe、TorchまたはTensorFlowより高速らしい。BigDLはスケールするから単一マシンで動作するそれらよりは当然早いと思う。CUDAのクラスタとかそれに合わせたアプリケーションを用意するよりSparkクラスタで動作するほうが、個人的にはお手軽なので良いと思うが、BigDLの学習コストが高そう。

詳しくは、BigDL READMEを参照してください。

環境

  • Debian 16.04.2 LTS (Xenial Xerus)
  • Java 1.8.0_121
  • Apache Spark 2.0.2

Known issuesにCentOSの問題がいくつか記載されていてめんどくさそうなのでDebianを使うことにした。

JavaとMavenのインストール

BigDLのビルドとSparkを動かすために使うJDKとMavenをインストールする。

$ sudo apt update -y
$ sudo apt install openjdk-8-jdk maven -y

Apache Sparkインストール

tutorialのサンプルはJavaアプリとしても動作させることが出来るので、Sparkが不要であればこの手順は無視してください。

$ wget http://d3kbcqa49mib13.cloudfront.net/spark-2.0.2-bin-hadoop2.7.tgz
$ tar zxfv spark-2.0.2-bin-hadoop2.7.tgz
$ sudo mv spark-2.0.2-bin-hadoop2.7 /usr/local/
$ cd /usr/local/spark-2.0.2-bin-hadoop2.7/
$ sudo cp conf/spark-env.sh.template conf/spark-env.sh
$ sudo chmod +x conf/spark-env.sh
$ sudo cp conf/spark-defaults.conf.template conf/spark-defaults.conf
$ export PATH=$PATH:/usr/local/spark-2.0.2-bin-hadoop2.7/bin

プロセスを起動します。MasterのIPアドレスは適宜読み替えてください。

/usr/local/spark-2.0.2-bin-hadoop2.7/sbin/start-master.sh
/usr/local/spark-2.0.2-bin-hadoop2.7/sbin/start-slave.sh "spark://localhost:7077"

学習用のデータをメモリに全てロードして処理するらしく、executorに割り当てるメモリが少ないとHeapが足りないと言われJobがコケてしまうので2GBくらい割り当てたほうが良いです。

$ sudo echo "SPARK_EXECUTOR_INSTANCES=2" >> conf/spark-env.sh
$ sudo echo "SPARK_EXECUTOR_MEMORY=2G" >> conf/spark-env.sh
$ sudo echo "SPARK_DRIVER_MEMORY=2G" >> conf/spark-env.sh

BigDL

BigDLをbuildします。buildには15分くらいかかります。

$ git clone https://github.com/intel-analytics/BigDL.git
$ export MAVEN_OPTS="-Xmx2g -XX:ReservedCodeCacheSize=512m"
$ cd BigDL
$ bash make-dist.sh -P spark_2.0

BUILD SUCCESSと表示されればOKです。

tutorial

LeNet5 Model on MNISTを動かしてみます。

データのダウンロード

トレーニングとテストで使うデータをダウンロードします。

$ wget http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz
$ wget http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz
$ wget http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz
$ wget http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz
$ mkdir mnist model
$ gunzip t10k-images-idx3-ubyte.gz \
t10k-labels-idx1-ubyte.gz \
train-images-idx3-ubyte.gz \
train-labels-idx1-ubyte.gz
$ mv *-ubyte mnist/

学習させる

Sparkを使ってBigDLにデータをくわせてネットワークを学習させます。

./dist/bin/bigdl.sh -- spark-submit --master local[1] \
--driver-class-path dist/lib/bigdl-0.1.0-SNAPSHOT-jar-with-dependencies.jar \
--class com.intel.analytics.bigdl.models.lenet.Train \
./dist/lib/bigdl-0.1.0-SNAPSHOT-jar-with-dependencies.jar \
-f ./mnist/ --core 1 --node 1 --env spark --checkpoint ./model

Sparkを使わない場合は次の通り。

dist/bin/bigdl.sh -- java -cp dist/lib/bigdl-0.1.0-SNAPSHOT-jar-with-dependencies-and-spark.jar \
com.intel.analytics.bigdl.models.lenet.Train -f ./mnist/ --core 1 \
--node 1 --env local --checkpoint ./model -b 1

時間はかかりますが学習が終わるまで待ちます。何回か実行しましたが、全てEpoch 15までで止まりました。止まると次の様に表示されます。

2017-03-12 16:33:46 INFO  DistriOptimizer$:243 - [Epoch 15 59952/60000][Iteration 74997][Wall Clock 3175.96207633s] Train 12 in 0.021189853seconds. Throughput is 566.308789400285 records/second. Loss is 0.0012443860759958625. Current learning rate is 0.05.
2017-03-12 16:33:46 INFO DistriOptimizer$:243 - [Epoch 15 59964/60000][Iteration 74998][Wall Clock 3175.983266183s] Train 12 in 0.025899406seconds. Throughput is 463.33108952382923 records/second. Loss is 0.0018258094787597656. Current learning rate is 0.05.
2017-03-12 16:33:47 INFO DistriOptimizer$:243 - [Epoch 15 59976/60000][Iteration 74999][Wall Clock 3176.009165589s] Train 12 in 0.023225649seconds. Throughput is 516.6701692598557 records/second. Loss is 0.001348257064819336. Current learning rate is 0.05.
2017-03-12 16:33:47 INFO DistriOptimizer$:243 - [Epoch 15 59988/60000][Iteration 75000][Wall Clock 3176.032391238s] Train 12 in 0.023787667seconds. Throughput is 504.4630900541865 records/second. Loss is 5.4836273193359375E-5. Current learning rate is 0.05.
2017-03-12 16:33:47 INFO DistriOptimizer$:286 - [Epoch 15 59988/60000][Iteration 75000][Wall Clock 3176.032391238s] Epoch finished. Wall clock time is 3193550.324218ms
2017-03-12 16:33:47 INFO DistriOptimizer$:431 - [Wall Clock 3193.550324218s] Validate model...
2017-03-12 16:34:02 INFO DistriOptimizer$:471 - top1 accuracy is Accuracy(correct: 9889, count: 10000, accuracy: 0.9889)
[Wall Clock 3193.550324218s] Save model to ./model

テストする

学習で作成したmodelを使ってテストを実行します。modelにはmodelディレクトリ以下にあるファイルを指定してください。コマンドを実行すると次のようにテスト結果が表示されます。

$ ./dist/bin/bigdl.sh -- spark-submit --master local[1] \
--class com.intel.analytics.bigdl.models.lenet.Test \
./dist/lib/bigdl-0.1.0-SNAPSHOT-jar-with-dependencies.jar \
-f mnist/ --model ./model/model.75001 --nodeNumber 1 --core 1 --env spark -b 1
Set engine type to mkl_blas
2017-03-12 16:50:19 INFO ThreadPool$:87 - Set mkl threads to 1 on thread 1
2017-03-12 16:50:19 INFO ThreadPool$:87 - Set mkl threads to 1 on thread 1
2017-03-12 16:50:21 INFO ThreadPool$:87 - Set mkl threads to 1 on thread 1
2017-03-12 16:50:22 WARN Utils$:36 - Warning: for better training speed, total batch size(1) is recommended to be at least two times of node number(1) * core number(1), please tune your batch size accordingly
2017-03-12 16:50:22 INFO DistriValidator$:50 - model thread pool size is 1
top1 accuracy is Accuracy(correct: 9887, count: 10000, accuracy: 0.9887)

他のデータを取り込んでどう判定されるか試したいのですが・・・Top1AccuracyとかDistriValidatorをどう変更すればいいのかがいまいちわからなかったのでここまでで終わります。

まとめ

学習させるデータが大きい場合は、学習に時間がかかるので入力データを減らしたり大きなクラスタを用意する必要がありそうです。大きなクラスタはEMRのスポットインスタンスを使えば簡単に用意できますが、VGGの場合は1回学習させるのに数百円かかったので地味に痛いです。

RNNの実装も用意されていますが、なるほどわからんって感じです。とりあえず、CNNとか確率的勾配降下法とかを学習しながらWIKIが整備されるのを待とうかなと思います。

おわり。

参考

  1. https://github.com/intel-analytics/BigDL