[英語版]

小・中規模ラボにおけるデータ管理の現実

機械学習問題に取り組む上で、巨大なデータを適切に管理することは重要です。 機械学習を実際にプロダクションで扱う企業では、MLOpsMLSysといった考え方を 用いてデータを管理していると思います。 一方で、大学の研究室ではどうでしょうか?企業と異なり、大学の研究室はインフラ整備やデータ管理に人員を割けない場面が多いと思います。 特に、大規模演算が専門ではない小・中規模の研究室では、秘伝のラボサーバをなんとか維持し、 アドホックにデータを管理しているという状況が多いのではないでしょうか。 そのような研究室では、可能な限りシンプルで簡単なデータ管理が求められています。

本記事では、Data Version Control (DVC) およびAmazon S3 を用いて ラボサーバのデータ管理問題を解決する試みを紹介します。 これにより、なかなか人員もコストも割けない小・中規模ラボにおいて、小数の管理者による機械的な管理の実現を目指します。 紹介する技術は試行錯誤の段階です。改善点などがあれば是非松井までご連絡ください。

さて、ラボ計算機環境ですが、次のような典型的な構成を見てみましょう。

ここでは以下の三つの環境があります。

  • ローカルマシン
    • 各学生(ここではRussell)は自分のノートPCを持っています。
    • このPCにも計算環境が出来ていて、簡単な実験やプロトタイピングを行います。
    • 実験に使うデータセットもダウンロードしてあります。
  • ラボサーバ
    • 研究室には、ラボが管理するオンプレの共有計算サーバがあります。
    • 共有サーバなので、home以下には各学生の領域があります。
    • 学生は、主たる計算をこのサーバ上で行います。
    • データセットに関しては、ラボの他のメンバーも使うため、共有領域に配置してあります。
  • クラウドサーバ
    • 大規模な実験を行う際は、クラウド上のサーバを使います。産総研のABCIや、Lambda GPU Cloudなどです。
    • このサーバ上でも、ラボサーバと同様の環境が構築されています。

ここでやりたいことは、可能な限り三つの計算機環境を同じように揃える(i.e., データを同期させ、可能な限りバージョン管理する)ということです。 そして、それを管理者にとっても利用者にとっても可能な限り簡単に行うことを目指します。 例えば、クラウドサーバで訓練したモデルを使ってラボサーバで推論を行い、その結果のデータを手元のマシンで解析する、といった要望があります。 そのようなときに、マシン間でしっかり同期をとる仕組みを構築する必要があります。

ここで、考えるべきデータは次の3つです。これらをどう管理するかを考えていきます。

データタイプ 管理する人 データサイズ  例
ソースコード 各ユーザ 小さい train.py
訓練後のモデルなど、ユーザのデータ 各ユーザ 大きい model.pt
データセット 管理者 大きい dog_and_cat ディレクトリ

ありがちな構成

これに対して、ありがちな解法は次のようなものです。

  • ソースコード (train.py)
    • ソースコードはGitHub/Bitbucket/GitLabによりgitで管理することが出来ます。これは問題ありません。
  • ユーザのデータ (model.pt)
    • 巨大なバイナリデータはgitで管理できないため問題です。
    • マシンが二台だけであれば、片方をマスターとしてrsyncを用いてなんとか管理できるでしょう。しかし環境が3つ以上になると、rsyncでの管理は非常に複雑になります。
  • データセット (dog_and_cat)
    • データセットの管理は大変です。例えば上記の例では、ユーザからの要請に従いfishというデータセットをクラウドサーバにダウンロードしたとします。このデータセットはどのようにラボサーバと同期すればよいでしょうか?管理者が常時整合性を保ちながらrsyncを行うのは、手間がかかります。
    • 多くのラボでは、アドホックに必要なときに必要な場所にだけデータをダウンロードしていると思います。その場合、違う環境のデータセット同士が果たして同じなのかどうか検証できないため、危険です。例えば、クラウドサーバのdog_and_catデータセットは今年ダウンロードした「ver 3」なのに、ラボサーバのdog_and_catデータセットは去年ダウンロードした「ver 1」かもしれません。その場合、全く同じアルゴリズムを用いても、クラウドサーバ上で行った実験とラボサーバ上で行った実験の結果が一致しません。このような差異は検知しづらいです。

提案方式:DVCとS3でデータ同期

これに対して、提案する、DVCとS3を使った構成例を次に示します。

ここでは、管理者がAWSと契約するとします。そして各ユーザがAmazon S3を使える状態であると仮定します。 ここでAmazon S3とは、AWS上で最も基本となるストレージサービスです。一言でいうと、ネットワーク上に存在するハードディスクです。

管理者は各ユーザの領域をS3上に事前に作っておきます。 すなわち、S3上にhome的な領域を作り、その下に各ユーザの領域があり、適切なアクセス制限を設けておきます。上の図でいう左下の緑色のs3-homeの部分です。 ここを、各ユーザのマスター領域とします。

この構成の元、データは下記のように二通りにわけて管理します。

  • ソースコード (train.py)およびユーザのデータ (model.pt)
    • ソースコードは従来通りgitで管理出来ます。
    • ユーザのデータについては、Amazon S3で管理します。
    • 各ユーザは、自分用のS3領域に自由にデータをアップロードし、必要に応じてダウンロードします。
    • このように、シンプルにネットワークストレージをマスターとすることで、個人領域の同期ができます。
    • ここではソースコードも同期させてもいいですし、コードはgitのみの管理でもいいでしょう。領域の使い方はユーザに任せます。
    • 慣れているユーザは、次に述べるDVCをこの個人領域管理でも使うことができます。
  • データセット (dog_and_cat)
    • 各ユーザの自由裁量に任せるユーザ領域と違い、共用データセットはもっとしっかりと管理したいです。
    • そこで、Data Version Control (DVC) を使います。DVCは、「データに関するバージョン管理」を実現するものです。軽量なコマンドラインツールであるdvcを用いてデータを管理します。
    • データの実体はS3上におきます。ここでは右下の茶色の枠で囲まれたs3-dvc-storageの部分です。共有したいデータがmd5sumハッシュ値にリネームされ保存されています。
    • dvcにより、三つの環境の間でデータセットを同期させることができます。

さて、上記の二通りの方式をそれぞれ見てみましょう。

ユーザ領域の管理(S3)

各ユーザ領域の管理は各ユーザに任せます。awscliの各種コマンドを使うことで、簡単にファイルのアップロード・ダウンロードが行えます。例えば ローカルのディレクトリ内容をs3に同期(sync to)するときは次のようにします。

$ aws s3 sync . s3://YOUR-LAB-s3-home/russell/myproj --delete   # sync to

逆に、s3の中身を手元に同期させる(sync from)するといは次のようにします。

$ aws s3 sync s3://YOUR-LAB-s3-home/russell/myproj . --delete   # sync from

また、vscodeのaws拡張を用いると、GUIを用いてアップロード・ダウンロードを行うことも可能です。

共用データセットの管理(DVC + S3)

さて、datasetsをどう作るかについて詳しくみていきましょう。 ポイントは、データセットをmd5sumによるハッシュ値として表現し、そのハッシュ値のみをgitでバージョン管理するという点です。 そして、データセットそのものはS3などの外部ストレージに保存します。

それでは実際にリポジトリを作っていきます。datasetsは、単一のgitリポジトリで管理されます。 そのリポジトリは、ラボメンバーが誰でも読み書きできるようにしておきます。 ここでは、そのようなdatasetsを1から作っていきましょう。

初期設定

まず、ラボのgithub上に、datasetsというラボメン全員が書き込み可能な空のリポジトリを作っておきます。 そして、管理者が手元で次のようにコマンドを実行します。

$ git clone https://github.com/YOUR_ORGANIZATION/datasets.git
$ cd datasets
$ pip install dvc boto3   # 依存ライブラリのインストール

次に、このディレクトリ上で、dvcの初期化を行います。

$ dvc init  # DVCの初期化
$ dvc remote add -d s3_storage s3://YOUR-LAB-s3-dvc-storage  # データを保存するS3の指定

ここで、s3://YOUR-LAB-s3-dvc-storageはデータセットを置いておくストレージ用のS3領域です。これは事前に準備しておきます。 すると、ディレクトリ構成は以下のようになります。

$ tree -a -L 2
.
├── .dvc
│   ├── .gitignore
│   ├── config
│   ├── plots
│   └── tmp
├── .dvcignore
└── .git

ここで、.dvcディレクトリにはdvcの設定ファイルが入っています。.dvc/configには先ほど指定したS3領域へのパスが含まれています。

$ cat .dvc/config
[core]
    remote = s3_storage
['remote "s3_storage"']
    url = s3://YOUR-LAB-s3-dvc-storage

この段階で一度リポジトリを更新しておきます。これで初期設定が終わりです。

git add .dvc      # .dvcそのものはバージョン管理します
git commit -m "Initialize DVC"
git push origin main

データセットの追加

さて、データセットを追加してみましょう。ここでは6枚の画像が含まれるdog_and_catディレクトリを追加します。 ディレクトリは以下のようになります。

$ tree -a -L 2
.
├── .dvc
├── .dvcignore
├── .git
└── dog_and_cat
    ├── 0000.jpg
    ├── 0001.jpg
    ├── 0002.jpg
    ├── 0003.jpg
    ├── 0004.jpg
    └── 0005.jpg

これらの画像全てをバージョン管理したいのですが、バイナリファイルをgitで管理することは推奨されません。 そこで、dvcコマンドを用います。

$ dvc add dog_and_cat

これにより、dog_and_cat.dvcというファイルが作られます。その中身は、dog_and_catディレクトリをmd5sumによる ハッシュ値にしたものです。

$ tree -a -L 2
.
├── .dvc
├── .dvcignore
├── .git
├── .gitignore
├── dog_and_cat
│   ├── 0000.jpg
│   ├── 0001.jpg
│   ├── 0002.jpg
│   ├── 0003.jpg
│   ├── 0004.jpg
│   └── 0005.jpg
└── dog_and_cat.dvc   # これはただのファイル

$ cat dog_and_cat.dvc
- md5: 8d52124bbbf2371ebfd8e636038431ca.dir
  size: 404150
  nfiles: 6
  path: dog_and_cat

また、.gitignoreには、「dog_and_cat本体をgitでバージョン管理するな」という追記がなされます。

$ cat .gitignore
/dog_and_cat

あとは、上記の2ファイルをgitで管理します。

$ git add dog_and_cat .gitignore
$ git commit -m "Added dog_and_cat dataset"
$ git push origin main

これにより、git側からは、データセットのmd5sumの値のみをテキストとしてバージョン管理することになります。 今後データセットが更新されたり追加されるときも、上記のようにmd5sumのみを管理するため、gitでの管理が可能になります。

さて、それではデータ本体はどうするのでしょうか?ここでは、dvc pushによりデータをS3に転送します。

$ dvc push

これにて、データそのものはS3に保存できました。この内容を確認してみましょう。

$ aws s3 ls s3://YOUR-LAB-s3-dvc-storage
                           PRE 6b/
                           PRE 8d/
                           PRE 94/
                           PRE a7/
                           PRE cc/
                           PRE d3/
                           PRE f9/

このように、データはmd5sumの値にリネームされ、保存されました。 データセットを増やしたいときは、上記と同じ方法でfishといったディレクトリを作ればOKです。

別の場所でデータセットを展開

さて、上記のdatasetsを別の場所で使う場合にはどうすればよいでしょうか。 ここでは、一般ユーザ(ラボメン)が上記のdatasetを 自分の個人PCで使うことを考えます。 作業ディレクトリに移動したうえで、datasetsディレクトリをgit cloneします。

$ cd SOMEWHERE
$ git clone https://github.com/YOUR_ORGANIZATION/datasets.git 
$ cd datasets
$ tree -a -L 1
.
├── .dvc
├── .dvcignore
├── .git
├── .gitignore
└── dog_and_cat.dvc

ここでわかる通り、データセットのハッシュ値を含むdog_and_cat.dvcはリポジトリに含まれています。 一方、ファイルの実体すなわちdog_and_catディレクトリは、リポジトリに含まれていません(含まれていないから、gitで管理できます)。 ここで、dog_and_catディレクトリをS3から引っ張ってくるには次のようにします。これにより、完全なデータセットが同期されます。

$ dvc pull dog_and_cat   # データセット本体をS3からもってくる

$ tree -a -L 1
.
├── .dvc
├── .dvcignore
├── .git
├── .gitignore
├── dog_and_cat
└── dog_and_cat.dvc

出来ました!これにより、コマンドラインツールであるgitdvcのみで、適切に巨大なファイルをバージョン管理できます。 この方式は、アドホックにラボサーバのデータセットをrsyncする方式に比べて、datasetsという管理リポジトリがあるので安全です。 データが一致することも保証されます。

また、管理者は、ラボサーバでもクラウド計算機でも、上記の方式を用いてデータセットを管理することができます。 すなわち、共用スペースにdatasetsを展開することで、git管理された状態でデータを管理・同期できます。

この方式は、DVC公式のSharing Data and Model Files、およびData Registriesのユースケースを参考にしています。

議論点

  • なぜS3なのか?他のAWSサービスはどうか?
    • 一番簡単な仕組みがS3だからです。他のもっと良い、簡単に使えるAWSサービスがあれば是非教えてください。。。FSx for Lustre?
    • 実用上は、S3は (1) セットアップがほとんど必要ない、(2) 単一のawscliコマンドで操作が出来る、(3) vscodeで直接見れる、といったメリットがあるので、S3で十分という状態ではあります。
  • S3の保管コストはどうか?
    • 東京リージョン(以下、料金は全て東京リージョンを仮定)ですと最初の50TB/月が0.025 USD/GBです。よって、ざっくり1USD=100円とすると1TBあたり2,500円/月です。これを高いと思うか安いと思うかは状況次第ですが、ラボの秘伝のHDDを維持するよりはよっぽど気持ちが楽なのは確かです。
    • また、S3 Intelligent-Tieringという仕組みを使うことで、使われていないデータは自動的に格安プランに変更して保存することが出来るようです。最も安い状態(S3 Glacier Deep Archive)ですとひと月あたり0.002 USD/GBですので、1TBあたり200円/月です。すなわち、通常のS3の1/10以下になります。これはかなり安いです。
  • S3の転送コストはどうか?
    • データをS3にアップロードするのは無料です。
    • データをS3から取り出すときに、0.114 USD/GB がかかります。これは安くはないです。500GBのデータセットを引っ張ってこようとするとそれだけで5,700円かかります。
    • 今回提案する仕組みの弱点がこの部分です。もしここを安く済ませる方式を知っている方がいらしましたら是非ご連絡ください。
  • Google Cloud Storage (GCS) などの類似サービスはどうか?
    • GCSでも良いと思います。DVCのバックエンドにはGCSも選べます。GCSでは、上記のS3 Intelligent-Tieringのような仕組みがなく、似た挙動をさせるには「触られないままある程度時間が経過したら自動的にプランを変更する」という処理を自分で書く必要があります。
    • 実は、ABCIのクラウドストレージ(ABCIが提供するS3互換の仕組み)が一番安いです。1TBあたり料金で言うとS3が約2500円、ABCI Cloud Storageが600円なので、格安です。ABCIからの使用が多い場合、最も楽です。ですが、マスターデータをABCIに依存させるのが少し怖いため、今回はAWSを選びました。
  • AWSの設定が大変ではないか?
    • 大変です。管理者側は、AWSの知識が必要です。各ユーザに対し、適切なIAMを設定しなければなりません。また、各ユーザにsecret access keyなどを配る必要があります。
    • そもそも「研究室環境を簡単に管理したい」という要望で始めているのに、AWSの設定が大変では本末転倒だという意見もあるでしょう。ですが、大変なのは管理者だけで、使う学生側としてはawscliを勉強するだけで済みます。そして、秘伝のオンプレシステム維持に比べ、AWSベースにする利点は完全なクラウド環境前提なので、物理インフラの管理が不要である点です。これは非常に大きく、便利です。
    • また、AWSの知識が必要である一方で、逆にPI本人のみ(あるいは本当に少数の管理者)が仕組みを知っていれば、回るという点があります。複雑な物理的ラボインフラを、人数をかけて運営する必要がなくなります。
    • そして、AWSの初期設定は大変なのですが、そこをクリアすればDVC + S3を用いたデータ管理そのものは管理者にとっても非常にクリアで楽です。
  • ユーザのデータ管理にもDVCは使えるか?
    • 使えます。
  • DVC以外の候補はどうか?
    • 自分が調べた限りでは、最もシンプルな「データのgit」の提供という点ではDVCが一番のようでした。機械学習の文脈でモデル管理を提供する他の仕組みとしてはPachydermmlflowなどがあるようですが、より高機能な反面、複雑なようです。唯一、DVCより簡単なものはGit-LFSですが、Git-LFSは裏側のクラウドストレージの設定に自由度が少なく、機械学習のワークフローにはなかなか適さないようです。サービス比較ページが参考になります。

LabOps

本記事の内容のように、研究室において研究を円滑に進めるための技術体系をLabOpsと定義することとします。 DevOpsやMLOpsの研究室版です。 今後もLabOpsに関する記事を公開していく予定です。