LoginSignup
38
20

More than 3 years have passed since last update.

Papermillでノートブックをバッチ実行して分散環境におけるハイパーパラメータ探索を効率化する方法

Last updated at Posted at 2020-08-27

1. はじめに

こんにちは,(株) 日立製作所 Lumada Data Science Lab. の露木です。

今回はJupyterノートブックで引数付きのバッチ実行を可能にし,ハイパーパラメータ探索などを効率化するPapermill というOSSを紹介します。Papermillの設計思想や他ツールと組み合わせたシステムの全体像については,開発元のNetflixが詳細な記事 を公開しているのでそちらもぜひご覧ください。

1.1. Jupyterの利点

データサイエンス分野の方々であれば,機械学習スクリプトの試作やレポート作成のためにJupyterノートブックの形式でコーディングをすることはよくあるかと思います。Jupyterノートブックであれば,図1のようにMarkdownの形式の説明文とともにソースコードと実行結果をまとめられるため,第三者に計算の内容と結果をわかりやすく伝えられます (いわゆる文芸的プログラミングを自然に実践できます)。

jupyter1.png
図1. Jupyterノートブックによるコーディング例

1.2. 問題提起: ノートブックの引数にパラメータを与えられない

ところで,一般にモデルの学習処理には時間がかかります。その上,ハイパーパラメータを変えながらモデルの汎化性能が最も高くなる条件を探索するとなれば,ハイパーパラメータの組み合わせの数に,テストデータと訓練データの分割を変えた交差検証の回数を掛け算した回数だけ学習処理を実行しなければなりません。例えば,SVMの2種類のハイパーパラメータ $\gamma$ と $C$ についてそれぞれ6種類ずつ組み合わせをとり,さらに交差検証を5回実施するのであれば, $6 \times 6 \times 5 = 180$ 回の学習処理を実行することになります。

このようなハイパーパラメータ探索のための学習処理は (ベイズ最適化のようなテクニックを使わなければ) 基本的に独立していますから,並列化によって効率化しやすい処理です。先程の180回の学習処理であっても,引数が異なるバッチジョブとしてジョブスケジューラに登録し,180台の計算ノードで並列処理すれば1回分の学習処理と同じ時間で終了します。

しかし,Jupyterノートブックは人間がインタラクティブに操作することを前提にしているため,このようなバッチ実行をしにくい問題があります。細かい話をすれば,Jupyterでもコマンドラインで jupyter nbconvert --to notebook --execute --inplace hoge.ipynb とすればバッチ実行できます。しかし,一般のPythonスクリプトのように引数を与えられません。つまり,先程のデータサイエンスのユースケースで言えば,ハイパーパラメータやデータセットのファイル名などが異なった多数のノートブックを作成しなければなりません (図2参照)。

jupyter_problem.png
図2. Jupyterノートブックのバッチ実行における課題。 Jupyterだけだとパラメータをノートブックに埋め込まなければならないので,バッチ実行前に多数作成しなければならない。

1.3. 対策: Papermillをつかう

この問題に対処するために,Netflixが開発したOSSのPapermill を利用できます。Papermillを使えば,ノートブックに引数を与えた上でバッチ実行できる (図3参照) ため,パラメータごとにノートブックを作成せずに済みます。そこで,本稿ではPapermillを使ったノートブックの実行方法を説明します。

papermill.png
図3. Papermillの利点1。 パラメータをバッチ実行時の引数として指定できるので,ノートブックを多数作成する必要がない

2. Papermillの使い方

2.1. 環境準備

最初にノートブックを実行したいマシン (お手元のノートPCや計算ノードなど) にPapermillをインストールします。インストールは以下のコマンド実行で可能です。

インストールのためのコマンド
pip3 install 'papermill[all]'

2.2. ノートブックの準備

まず,バッチ実行するためのノートブックを準備します。今回は単にPapermillの動作確認をするだけですので,設定したパラメータを表示するだけの図4のようなノートブックを作ります。

input.png
図4. バッチ実行するノートブックの例

次に,Papermillに対応するためにこのノートブックを修正します。といっても修正するのは変数を指定する部分のみです。

具体的には,ノートブックのどこか1つのセルで引数としたい変数をまとめて定義するように修正します。図4の例であれば,1つのセル内で以下のように alpharatio といった変数を指定するように修正します。なお,Papermill実行時に引数の指定がなかった場合は,このセルで定義した値 (以下のコードでは 0.1) がデフォルト値として利用されます。

paramters
alpha = 0.1
ratio = 0.1

そして,この変数定義をしたセルをPapermillが認識できるように parameters の値を「タグ」として指定します。タグはJupyterノートブックの基本機能としてある,セルのメタ情報を管理する仕組みです。なお,parameters のタグを複数のセルに付与しても,Papermillに認識されるのは一つだけ (一番上のセルのみ) である点はご注意ください。

Jupyter Notebookの場合,セルにタグを付与する手順は以下のとおりです。この手順に対応する画面操作は図5を参照ください。

  • (1) メニューバーの ViewCell ToolbarTags をクリッしてタグ入力欄を追加する
  • (2) タグ入力欄にタグ名 parameters を入力
  • (3) Add tagボタンをクリックして,タグを確定する
  • (4) セルの左上に parameters タグの追加を確認したら,
  • (5) ノートブックを上書き保存する

papermill_01_tag.png
papermill_02_tag-nb.png

図5. JupyterLabにおけるタグ設定方法

一方,JupyterLab (Version 2.1.5) の場合は以下の手順でタグを指定できます。この手順に対応する画面操作は図6を参照ください。

  • (1) タグを指定したいセルをクリックして選択
  • (2) 左サイドバーの プロパティ設定ボタンをクリック
  • (3) 左サイドバーの「Add Tag」の欄をクリックして parameters を入力したら,
  • (4) + ボタンをクリックしてタグを確定する。
  • (5) parameters タグの確定を確認したら,
  • (6) ノートブックを上書き保存する

papermill_03_tag-nb.png
図6. JupyterLabにおけるタグ設定方法

2.3. ノートブックの実行

Papermillでは,PythonAPIとCLIコマンドの2種類のインターフェイスが提供されています。今回はinput.ipynb のファイル名で保存したノートブックをバッチ実行し,実行結果をoutput.ipynb のファイル名で保存するものとして実行方法を示します。

(a) PythonAPIを使う方法

まず,PapermillのPythonAPIを利用する場合は,以下のようなコードをPythonスクリプトに埋め込んで実行してください。

PythonAPIによる実行例
import papermill as pm

pm.execute_notebook(
   'input.ipynb',
   'output.ipynb',
   parameters=dict(alpha=5, ratio=7)
)

Papermillのexecute_notebook関数は,一番目の引数に実行したいノートブックのファイル名,二番目の引数に保存先のファイル名を受け取ります。また,引数parametersで辞書型の変数を受けており,ノートブック内のparametersタグを付けたセルの変数alpharatioの値をそれぞれ57に変更しています。

上記のPythonスクリプトを実行すると,実行結果として output.ipynb が保存されます。output.ipynbをJupyterで開くと,図7のようにalphaとratioの値が上書きされて実行されていることがわかります。

result.png
図7. Papermillの実行結果として保存される output.ipynb の中身

(b) CLIコマンドを使う方法

次にPapermillのCLIコマンドを使用する方法を示します。Papermillのコマンドでは -p オプションで以下のようにパラメータを指定します。また, --request-save-on-cell-execute--prepare-executeオプションで保存先のノートブックにセルの実行結果を保存せよと指定しています。

CLIコマンドによる実行例
papermill input.ipynb output.ipynb \
          --request-save-on-cell-execute --prepare-execute \
          -p alpha 5 \
          -p ratio 7

こちらのCLIコマンドでも,実行後にはファイル名 output.ipynb で図7のような実行結果が保存されます。

なお,Papermillのコマンドに --log-output オプションを追加すれば,セルの実行結果を標準出力に表示します。また,--progress-bar オプションを追加すれば実行状況を出力します。どちらも,CLIコマンドとしてノートブックをバッチ実行する際に便利です。

2.4. オブジェクトストレージの読み書き

最後に,Papermillのユニークな機能を紹介します。Papermillは図8のように外部オブジェクトストレージ (AWSのS3など) からノートブックを直接に読み書きする機能を持っています。これにより,計算ノードのファイルシステムとして外部オブジェクトストレージをマウントしなくても済むので,ジョブスケジューラで束ねた計算機クラスタやCI/CDシステムでノートブックを実行する際に便利です。

s3.png
図8. Papermillの利点2。 AWSのS3のような外部オブジェクトストレージからノートブックを直接に読み書きできるので,s3fsなどと組み合わせて計算ノードにオブジェクトストレージをマウントする操作などの手間はかからない

オブジェクトストレージの準備

ここでは,AWS S3互換のオブジェクトストレージとしてOSSであるMinIOをつかう例を示します。自分でMinIOを起動すれば無償で,お手元のノートPCで利用できるので簡単な試用目的にに適しています。また,MinIOを社内のサーバで起動すれば,お客様からお預かりした機密データや社外秘情報を含むノートブックを社外に送信するリスクを回避できますので,情報管理の観点からも活用する価値があります。

MinIO開発元が提供しているイメージを使って,MinIOをDockerコンテナとして起動します。コンテナ起動は以下のコマンド実行で可能です。ただし,ACCESSKEYSECRETKEY は適宜,ご自分で設定したいパスワードに置き換えてください。

MinIOのDockerfile
docker run -p 80:9000 \
  -e "MINIO_ACCESS_KEY=ACCESSKEY" \
  -e "MINIO_SECRET_KEY=SECRETKEY" \
  minio/minio server /data

コンテナを起動したら,動作確認のために http://localhost にWebブラウザで接続します。MinIOを起動したサーバとWebブラウザが動作するノートPCが別のサーバである場合,は localhost をサーバのIPアドレスで読み替えてください。このとき以下の図9のようにMinIOがパスワード入力を促す画面が表示されれば成功です。このログイン画面でコンテナ起動時に設定した MINIO_ACCESS_KEYMINIO_SECRET_KEY の値を入力すればログインできます。

minio.png
図9. MinIOのパスワード入力画面

MinIOにログインしたら,任意の名称 (ここでは notebooks ) でBucketを作成し,バッチ実行したいノートブック input.ipynb をアップロードします。

s3_1.png
図10. バッチ実行したいノートブック input.ipynb をアップロードした状態のMinIO

ノートブックの実行

ここまで準備ができたら,Papermillを使ってノートブックを実行できます。MinIOへの接続情報を環境変数で設定するために,以下のコマンドを実行してください。ただし,パスワードやURLの値はコメントを参考に適宜,お手元の環境に合わせて変更してください。

環境変数の設定
# 環境変数でパスワードを指定する (Papermillが呼び出すboto3ライブラリの機能)
export AWS_ACCESS_KEY_ID=ACCESSKEY      # docker run時に指定したMINIO_ACCESS_KEYの値に合わせて設定してください
export AWS_SECRET_ACCESS_KEY=SECRETKEY  # docker run時に指定したMINIO_SECRET_KEYの値に合わせて設定してください

# 環境変数で接続先URLを指定する (Papermill限定の機能)
export BOTO3_ENDPOINT_URL=http://localhost:80  # MinIOサーバのIPアドレスとポートを設定してください

# (会社等でHTTP Proxyを利用している場合のみ)
# MinIOに正しく接続するためHTTP Proxyを経由しないように設定する
export no_proxy=localhost

後はPapemillコマンドを実行するだけです。以下のように s3://<バケット名>/<ファイル名>の形式で入出力用ノートブックを指定して実行すれば,Papermillが自動的にMinIOから input.ipynb をダウンロードし,その実行結果を output.ipynb としてアップロードします。

Papermillの実行コマンド
papermill s3://notebooks/input.ipynb s3://notebooks/outout.ipynb \
          -p alpha 5 -p ratio 7

papermillコマンドの実行後にMinIOの画面を確認すると,図11のように実行結果 output.ipynb がアップロードされていることがわかります。

s3_2.png
図11. 実行結果のノートブック output.ipynb をアップロードした状態のMinIO

3. おわりに

今回はPapermillを使ってノートブックをバッチ実行する方法を示しました。今回のようなツールと,以前紹介した ジョブスケジューラPBSProを構築して計算ジョブを投入する方法を組み合わせるとパイパーパラメータ探索などを効率的に実行できます。よろしければぜひ試してみてください。

4. 参考URL

Papermillのコンセプトに関して

Papermillの使い方に関して

PapermillとMinIOを組み合わせて使う方法に関して

38
20
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
38
20