Jupyter Notebook + Spark(PySpark)で作った機械学習プログラムの実行方法いろいろ

R&D部のmatsushitasです。絶賛機械学習勉強中です。

機械学習プログラムの開発・実行環境として有名なJupyter Notebookと、Sparkの機械学習ライブラリであるMLlib。
この2つを組み合わせるケースはそれなりにあるんじゃないかと思いますが、その実行方法は何パターンかあるようです。
サンプルプログラムを使っていくつか紹介します。

サンプルプログラム

https://github.com/romiogaku/jupyter-notebook-spark-sample

Sparkに依存するpythonプログラムです。サンプルなので実際の学習は行いませんが、本来は大量の学習データをDataFrameで前処理したり、Spark MLlibで学習モデル作ったりする想定です。

外部jarに依存する例も示したかったので、今回は Elasticsearch-Hadoopコネクタを利用してみます。Spark用のjarファイルを読み込めば、SparkのDataFrameをElasticsearchに書き込んだりできるようになります。

前準備

事前にSparkとpipenvのインストールが必要です。(Sparkは2.2.0で動作を確認しました)

$ pipenv install

で依存ライブラリを仮想環境内にインストールできます。

また、Elasticsearchを使うのでdockerで起動しておきます。

$ docker-compose up -d

http://localhost:9200でElasticsearchが、http://localhost:5601 でKibanaが起動します。

実行方法1: pysparkコマンドでJupyterNotebookを起動させる

PySparkを使う際のインタプリタとしてJupyter Notebookを使うように環境変数を設定します。

PYSPARK_DRIVER_PYTHON="jupyter" PYSPARK_DRIVER_PYTHON_OPTS="notebook" pipenv run pyspark --jars /path/to/jupyter-notebook-spark-sample/elasticsearch-hadoop-6.3.2/dist/elasticsearch-spark-20_2.11-6.3.2.jar

外部jarファイルは相対パスだとうまくいかないことがあったので、絶対パスで指定しています。お使いの環境に合わせてください。

pipenvを利用している場合は.envファイルを読み込んで環境変数をセットしてくれるので、以下のような.envファイルを用意してもOKです。

PYSPARK_DRIVER_PYTHON="jupyter"
PYSPARK_DRIVER_PYTHON_OPTS="notebook"

実行方法2: .pyファイルに変換してspark-submitコマンドで実行させる

spark-submitコマンドはpythonプログラムも実行できます。
まずは.ipynbファイルを.pyファイルに変換します。

$ pipenv run jupyter nbconvert --to script sample.ipynb

以下のコマンドで実行できます。

$ pipenv run spark-submit --jars /path/to/jupyter-notebook-spark-sample/elasticsearch-hadoop-6.3.2/dist/elasticsearch-spark-20_2.11-6.3.2.jar sample.py

実行方法3: Jupyter NotebookからSparkを起動させる

通常のJupyter Notebook起動コマンドです。

$ pipenv run jupyter notebook

立ち上がったらSparkをJupyter上で実行するための準備として、コード内の以下のCell全体をコメントインしてください。

import sys

spark_home = os.environ.get('SPARK_HOME', None)
sys.path.insert(0, spark_home + "/python")
# py4j-0.10.7-src.zipのバージョンは適宜変更してください
sys.path.insert(0, os.path.join(spark_home, "python/lib/py4j-0.10.4-src.zip"))

あとは通常通りJupyter Notebook上でステップごとに実行できます。

実行方法4: Jupyter Notebookをそのまま実行させる

これも方法3と同じく、SparkをJupyter上で実行するためコードがコメントインされている必要があります。
この方法ではブラウザでJupyter Notebookを起動させず、コマンドラインで.ipynbファイルを直接実行します。

$ pipenv run jupyter nbconvert --to notebook --execute sample.ipynb --output sample-output.ipynb --allow-errors --debug

nbconvertの代わりにpapermillを使うこともできます。

$ pipenv run papermill sample.ipynb sample-output.ipynb

出力結果はどちらも.ipynbファイルで出力されるので、HTMLに変換して見てみましょう。

$ pipenv run jupyter nbconvert --to html sample-output.ipynb

おわりに

複数の実行方法を紹介してきましたが、実行する環境によって使い分けるのが良さそうです。
例えば開発時はJupyter Notebookを使いたいので方法1、または方法3。
バッチプログラムとして定期実行させたい本番運用時は方法2、または方法4が良いかと思います。

フロントやったりバックエンドやったり。 最近の趣味は自作キーボード。 PHP, JS, Go, Scala