Kaggle Notebook実行環境と仮想環境の運用について
概要
今回作ったKaggle Notebook実行環境の構成の紹介と、機械学習の実験環境におけるpython仮想環境の運用方法について書く。
経緯
これまでAnacondaでpytorch, tensorflowなどと主要なフレームワークごとに仮想環境を作り、複数のプロジェクトで使い回す運用をしていた。pytorchやpandasなどの基本的なパッケージが入っていればよく、また実験環境なのでパッケージの厳密なバージョンは特に気にしてなかったので特に大きな問題もなく運用できていた。
ところが、最近KaggleのOttoコンペをやるようになって、RAPIDSやらMarlinやら、数百Mのデータテーブルを効率的に捌くためのフレームワークが必要になってきて、仮想環境が何個も生えるようになった。
このくらいの数(4-5個)なら特に管理はしていけるだろうが、Anacondaの管理の問題点1も見えてきたので、そろそろちゃんと管理したいなと思っていた。
本腰を入れて対応しようと思ったきっかけは、Kaggle Notebookを手元で動かそうとして、環境の違いのせいで、実行できるようするための無駄なインフラ作業(機械学習と関係のない作業)が発生していたことである。
幸いKaggleは公式のdocker imageを公開しているし、dockerの構築方法についての情報もかなり出回っているので、Kaggle Notebookの実行環境のクローンを作りつつ、Anacondaの仮想環境管理からdockerによるイミュータブルなインフラ運用に移行することにした。
Kaggle Notebook実行環境のクローンを作る
dockerと公式のdocker imageのインストールについては公式のドキュメントや、個人のブログ記事などがすでに多くあるのでここでは書かない。
ここでは実際に作った構成の要件と運用イメージを述べるにとどめる。
要件
- Notebookの修正を最小限にする
- notebookの変更内容やnotebookのアウトプット(モデルの重みなど)はホスト環境に残したい
- データセットもホスト環境にダウロードしたものをコンテナからアクセスできるようにする
- コンテナ起動中に変更された構成はいつでも初期化できるようにする
2, 3はvolumeの設定でできるし、4はdockerコンテナを削除すればよい。 1はフォルダのパスをKaggleに合わせればほぼ問題ない。
コンテナ内のフォルダ構成
- /kaggle/working: ノートブックを保管する場所
- /kaggle/input: データセットを保管する場所
- /kaggle/jupyter_lab_config.py: jupyter lab の設定ファイル
運用イメージ
あるNotebookをこの環境で動かしたい場合、
- 依存しているKaggleのデータセットをKaggle APIで取得し、ホストマシンの
/kaggle/input
と同期されたディレクトリ内に展開する - Kaggleのnotebookページからダウンロードしたipynb形式のファイルをjupyter labの管理画面からアップロードする。アップロードしたノートブックはワークディレクトリ
/kaggle/working
に入り、ホストマシンと同期される。 - notebookを手動でステップ実行する。inputのパスが元のnotebookと異なる場合は適宜書き換える
- 実行結果は
/kaggle/working
と同期したホストマシン上のディレクトリに保持される - 実行完了後、コンテナを削除して状態を初期化する
ソースコード
今回作成したdockerの起動設定用の資材をGitHub2で公開する。セットアップ方法などはこちらに詳しく記載したので、参照実装として有効活用していただければと思う。
Anacondaを脱却してコンテナ+pipによる管理へ
今回の課題はKaggle Notebookのクローン環境を作ることだったわけだが、コンテナによる運用はKaggleに限らず、パッケージの厳密な依存性管理を必要としない任意の機械学習プロジェクト3に適用してメリットがあると考えている。以下にその理由を説明する。
各ツールの担当範囲
以下ではAnacondaとコンテナ+pipの運用を比較したいのだが、それぞれがどのレイヤを担当しているかを混同すると言ってることが理解しづらいと思うので、ツールごとの担当レイヤを表1に整理しておく。違いは、簡単にいうと、Anacondaはベースとなる環境とプロジェクトごとの差分に特に切り分けがないため全てpython仮想環境で担当しているが、コンテナ+pipの運用ではベース環境をdocker、プロジェクトごとの差分をpipで行うという点である4。
表1. 各ツールの担当範囲
担当範囲 \ 運用パターン | Anaconda | コンテナ+pip |
---|---|---|
ベースとなる環境の定義 | python仮想環境 | dockerコンテナ |
プロジェクトごとの差分の定義 | python仮想環境 | pip |
Anaconda運用のパターンと課題
Anacondaでは仮想環境でベースとなる環境もプロジェクトごとの差分も定義しなくてはならない。したがって、以下のどちらかのパターンで運用することになる。
- プロジェクトごとに独立した仮想環境を使う
- 複数のプロジェクトで共通の仮想環境を流用する
プロジェクトごとに独立した仮想環境を作る運用の課題は、リソースの重複が大きいことである。たとえばGPUに対応したpytorchは数Gバイトのディスク容量を消費するが、これがプロジェクトごとに重複して管理される。また、インストールしたパッケージの一覧があるわけではないので、何をインストールしたのかが分かりにくいという点がある。
逆に、複数のプロジェクトで共通の仮想環境を流用した場合(前述のpytorch共通環境のような運用イメージ)、あるプロジェクトで新しいパッケージをインストールしたくなった場合に共通環境にインストールすることになるが、インストールによって他のプロジェクトの構成にも影響が及ぶ可能性がある。たとえば、パッケージAをインストールすることで他のプロジェクトで使われているパッケージBのバージョンが代わり、他のプロジェクトが動かなくなる可能性がある。
Anacondaと比較したコンテナ+pip運用のメリット
コンテナ運用のメリットは以下である。
- リソースの重複が最小限
- 共通環境が変化しにくい
- 万が一環境を破壊してもすぐに元に戻せる
まず、地味なところではリソースの重複が少ない点が挙げられる。Anacondaは仮想環境とプロジェクトごとの差分を切り分ける手段がないので、プロジェクトごとに仮想環境を作る必要があるが、コンテナであればベースとなる環境をコンテナで管理し、プロジェクトごとの差分をpipで管理する、という切り分けができる。これによって、pytorchのように数GB消費するパッケージを何個もインストールする必要がなく、ディスク消費とインストールの時間を節約することができる。
また、Anacondaで「pytorch共通環境」のようなベース環境を用意した場合、pytorchプロジェクトでは同じ仮想環境を流用するので新しいパッケージをインストールするたびに共通環境が変化していく。コンテナ運用ならプロジェクトごとの差分はDockerfileに記述したpipでインストールするので、共通部分となるbase imageを変える必要がなく、デグレなど共通環境特有の心配がない。
さらに、たとえば、Anacondaの仮想環境にpipで誤ってパッケージをインストールしてしまった場合を想像して見てほしい。pipで手動でインストールした変更はAnacondaの管理外なので、これらをアンインストールするには、依存関係も含めて何が変わったのかを一つ一つ確認して切り戻す必要がある。戻せなければ仮想環境を一から作り直す必要がある。これに比べてコンテナは一度きりの使い捨てなので、コンテナを削除すれば起動中にインストールした変更を元に戻すことができる。
Anacondaと比較したコンテナ+pip運用のデメリット
注:元々「pipは依存性の管理ができない」という前提で書いていたが、これはpip 20.2以前の話で、20.3以降のバージョンでは依存関係リゾルバーが実装されている5。したがって元の記述は削除した。
まとめ
- Kaggle Notebookのクローン環境の要件と資材構成について共有した
- 仮想環境の管理方法についてAnacondaと比較したコンテナ運用のメリットについて主張した
補足: 記事の変更点について
この記事では最初「コンテナ+pipenvライクなツール」による運用管理のメリットについて書いていたが、そもそもpipenvやその類似ツールはプロジェクトごとにpython仮想環境を作成するため、「共通基盤の設定を流用してプロジェクトごとの差分のみを定義する」といった運用はできない。
このため、コンテナによる運用のパターンを「コンテナ+pip」と改め、適用範囲を「任意の機械学習プロジェクト」から「厳密なパッケージの依存性管理を必要としない任意の機械学習プロジェクト」と改めた。
また、「Anacondaと比較したコンテナ+pip運用のデメリット」の節を追加した。