見出し画像

MLプロジェクトにおけるデータ管理

Weights & Biases のnoteをフォローしてください

こんにちは、Weights & Biases(WandB)の鎌田です。この記事では、WandBの便利なデータ管理機能であるアーティファクト(Artifacts)について解説をします。


MLプロジェクトにおけるデータ管理のポイント

データはMLモデルの貴重な資源であることは言うまでもなく、MLモデルはデータの量や質によってモデルの性能が変化します。MLはその性質上、試行錯誤が伴います。ETL(この章の最後に用語説明があります)で整備されたデータを使用できることもあれば、開発段階ではデータラベルの不備を修正する必要性が発生したり、追加のデータが必要となることで、ELTに近い形でデータ準備を進めることを余儀なくされることもあるでしょう。

最近では、DatabricksやSnowflakeなどが、データレイクの柔軟性とデータウェアハウスのデータ管理の両面を兼ね備えたデータレイクハウスというソリューションも出していますが、モデル構築の前のデータ管理・処理においても様々なツールやプラクティスが登場するなど、これらの課題・ニーズは大きく、MLプロジェクトにおいて非常に重要な領域になります。

柔軟性や試行錯誤が重要となるMLプロジェククトのデータ管理ですが、
そのプラクティスとして、データリネージという概念が提唱されています。日本語版が2023年8月30日に出版されたオライリー・ジャパンの機械学習システムデザインでは、データリネージについて以下のように説明しています。

データリネージ
…それぞれのデータサンプルの出どころとラベルを追跡できるようにしておくことをお勧めします。この手法はデータリネージ(data lineage)と呼ばれており、データの潜在的なバイアスを検出し、モデルをデバックする役に立ちます。たとえば、最近に手に入れたデータサンプルを使うとモデルがよく失敗するようになってしまった場合、新しいデータの入手方法や入手経路を調査すると良いでしょう。私は、問題の原因がモデルにあるわけではなく、最近手に入れたデータでラベルの誤りが非常に多いためであったという状況を幾度も目にしてきました。

オライリー・ジャパン 機械学習システムデザイン

モデル開発者がスプレッドシートでデータを管理するという属人的なデータ管理の方法は言うまでもなくベストプラクティスではありません。WandBでは、モデル開発者が自身のコードを使いながらシームレスに、そしてチームとしてはそれを一元的なプラットフォームでデータを管理することができるアーティファクトという機能を提供しています。以降の章では、そのアーティファクトについてみていきましょう。

用語説明
ETL:  データを抽出(Extract)して、分析に利用可能な形式に変換(Transform)し、格納(Load)すること。分析に利用可能な形式に変換されたデータをデータウェアハウスに保存しておくことで、早く分析を行うことができたり、データサイエンティストやアナリストがアクセスできるデータを制限することでセキュリティを高める効果もあります。
ELT: データを抽出(Extract)して、データレイクに格納(Load)してから、分析に利用可能な形式に変換(Transform)すること。ETLと違い、構造化データ、非構造化データ、半構造化データ、ローデータといったあらゆる種類の未加工データをデータストレージに格納してから都度変換を行います。柔軟性はありますが、分析に時間がかかる上、情報漏洩・コンプライアンス違反のリスクがあります。

Weights & Biasesを用いたML開発におけるデータ管理

WandBのアーティファクトは大きく下図に示す3つのことを実現してくれます。順番にみていきましょう。

WandBにバージョン管理されたデータフォルダをログする

アーティファクトの利用方法からみていきましょう。下図は、アーティファクトの大まかなフローを示しており、run.log_artifact()でデータを保存し、run.use_artifact()で保存したデータを使うという非常にシンプルなフローになっています。

以下ではアーティファクトの活用フローを順に説明していきます。
Step1: WandBにログイン

WandBライブラリをインポートし、WandBにログインします。まだ登録していない場合は、WandBアカウントを作成する必要があります。

import wandb
wandb.login()

Step2: runの初期化
wandb.init() APIを使って、バックグラウンドプロセスを生成し、WandB runとしてデータを同期およびログに記録します。ここでは、プロジェクト名とジョブタイプを指定してください(job_typeは実行には影響しませんが、後でわかりやすい名前をつけておくことをお勧めします)。

# W&B Runを作成します。ここでは、データセットアーティファクトの作成方法を示すため、
# ジョブタイプとして'dataset'を指定しています。
run = wandb.init(project="artifacts-example", job_type="upload-dataset")

Step3: アーティファクトオブジェクトの作成
wandb.Artifact() APIを使ってアーティファクトオブジェクトを作成します。アーティファクトに名前を付け、ファイルタイプの説明をnameおよびtypeパラメータにそれぞれ指定してください。例えば、以下のコードスニペットは、‘dataset’ラベルの‘bicycle-dataset’というアーティファクトを作成する方法を示しています。

artifact = wandb.Artifact(name="bicycle-dataset", type="dataset")

アーティファクトの構築方法についての詳細は、アーティファクトの構築を参照してください。

Step4: データセットをアーティファクトに追加

アーティファクトにファイルを追加します。一般的なファイルタイプには、モデルやデータセットがあります。以下の例では、ローカルマシンに保存されているdataset.h5という名前のデータセットをアーティファクトに追加しています。

# アーティファクトの内容にファイルを追加
artifact.add_file(local_path="dataset.h5")

フォルダを追加することも可能です。フォルダを追加する際は、artifact.add_dir()を使用してください。

!!!!重要!!!!
上記の方法は、データをWandBサーバーに保存する方法になりますが、大きな画像や動画のファイルであると、WandBサーバーに毎回データをアップロードするのは非現実的です。WanbBには、WandBサーバーの外に保存されたファイルをトラッキングするリファレンスアーティファクトという、ファイルのパスを管理する方法があります。この方法では、アーティファクトは、URL、サイズ、チェックサムなどのファイルのメタデータのみを保存します。実際のデータはシステムから離れることはありません。また、ローカルファイルだけではなく、Amazon S3と互換性のあるインターフェース(MinIOを含む)をサポートしたクラウドストレージ上のファイルパスも管理することができます。下記がそのサンプル例です。詳しくはこちらをご確認ください。

import wandb

run = wandb.init()
artifact = wandb.Artifact('mnist', type='dataset')
artifact.add_reference('s3://my-bucket/datasets/mnist')
run.log_artifact(artifact)

Step5: データセットをログする
WandBのrunオブジェクトの状態を永続的ににロックメソッドを使って、アーティファクトのバージョンを保存し、そのアーティファクトをrunの出力として宣言します。最後に、wandb.finish()またはrun.finish()でRunを終了することを忘れないでください。

# アーティファクトのバージョンをW&Bに保存し、
# このrunの出力としてマークする
run.log_artifact(artifact)
...
run.finish()

アーティファクトをログすると、デフォルトで'latest'エイリアスが作成されます。アーティファクトのエイリアスとバージョンについての詳細は、それぞれカスタムエイリアスの作成新しいアーティファクトバージョンの作成(2023/9時点では英語版が最新になっています)をご覧ください。

Step6: アーティファクトのダウンロードと使用
以下のコード例は、ログしたアーティファクトを使用するための手順を示しています。

  1. 最初に、wandb.init()で新しいrunオブジェクトを初期化します。

  2. 次に、runオブジェクトのuse_artifact()メソッドを使って、WandBにどのアーティファクトを使用するか指示します。これによってアーティファクトオブジェクトが返されます(パスを取得する箇所は、この後スクリーンショットで解説をします)。

  3. 最後に、アーティファクトのdownload()メソッドを使って、アーティファクトの内容をダウンロードします。

# W&B Runを作成します。ここでは'type'に'training'を指定しています
# なぜなら、このrunでトレーニングのトラッキングを行うためです。
run = wandb.init(project="artifacts-example", job_type="training")

# アーティファクトをW&Bから取得し、このrunの入力としてマークします
artifact = run.use_artifact("bicycle-dataset:latest")

# アーティファクトの内容をダウンロードします
artifact_dir = artifact.download()

代わりに、公開API(wandb.Api)を使用して、WandB外部のRun以外ですでに保存されているデータをエクスポート(または更新)することもできます。詳細については、外部ファイルのトラッキングを参照してください。

WandB上で確認
以下のスクリーンショットは、Weights_&_Biases_Experiment_Tracking_Pytorch_JPのサンプルを回した後のWandBの画面です。プロジェクト右下の"Artifacts"をクリックすると、そのプロジェクトで保存されたデータを確認することができます。データだけではなく、構築されたモデルやモデル構築途中で得られるモデルのチェックポイント、WandBで実行できるジョブなど、生成される全てのアセットを管理することができます。モデルについては、組織で最終的にどのモデルを活用しているかをプロジェクトを跨いで管理することができるモデルレジストリという機能もWandBは提供しています。モデルレジストリについては、別ブログで紹介をします。各データをクリックすると、データの基本情報が現れますが、ここでエイリアスの変更などを行うことが可能です。

Artifacts - Version

Filesタブをクリックすると、その中の実際のファイルを確認することができます。こちらの記事で紹介しているTableフォーマットで保存をすると、Artiractsの中でTable形式でデータをインタラクティブに確認することも可能です。

Artifacts - Files

Usageタブをクリックすると、このデータを使用するためのパスやコードが表示されます。このコードやパスをもとに、保存したデータを使用してください。

Artifacts - Usage


ステップ間の関係を追跡する

先ほどの例で、Lineageタブをクリックすると、自動作成されたデータリネージのグラフを確認することができます。WandBのアーティファクトを使用すると、このようにデータリネージが自動生成されるため、追跡可能性高く、再現性高くデータ管理を行うことができ、誰が見ても一目でどの処理でどのデータを利用したかがわかるようになります !

Artifacts - Lineage


新しいバージョンを追加し、自動的に重複を削除する

新しいアーティファクトのバージョン追加は非常に簡単で、同じアーティファクトの名前を使用する限り、v1, v2,..と自動でバージョン管理されます。

バージョン管理のイメージ

まずは、最もシンプルな方法を見ていきましょう。以下の方法ではアーティファクト内の全てのファイルを扱うランで新しいバージョンのアーティファクトをログします。

# runの中で使用する場合
with wandb.init() as run:
    artifact = wandb.Artifact("artifact_name", "artifact_type")

    # Add Files and Assets to the artifact using
    # `.add`, `.add_file`, `.add_dir`, and `.add_reference`
    artifact.add_file("image1.png")
    run.log_artifact(artifact)


# runの外で使用する場合
artifact = wandb.Artifact("artifact_name", "artifact_type")
# Add Files and Assets to the artifact using
# `.add`, `.add_file`, `.add_dir`, and `.add_reference`
artifact.add_file("image1.png")
artifact.save()

実は、全てのファイルを保存する以外に、前回との差分だけを登録する方法もあります。前のアーティファクトバージョンから一部のファイルを追加、変更、または削除するときに、変更されなかったファイルを再インデックスする必要はありません。前のアーティファクトバージョンから一部のファイルを追加、変更、または削除すると、インクリメンタルアーティファクトとして新しいアーティファクトバージョンが作成されます。

インクリメンタルアーティファクトのイメージ

以下は、インクリメンタルアーティファクトの実行フローです。詳しくは、公式ドキュメントを確認してください。

# WandB Public APIを使用して、インクリメンタル変更を行いたいアーティファクトバージョンを取得します
client = wandb.Api()
saved_artifact = client.artifact("my_artifact:latest")

# 以下のようにドラフトを作成します
draft_artifact = saved_artifact.new_draft()

# 次のバージョンで見たい任意のインクリメンタル変更を実行します。既存のエントリを追加、削除、または変更することができます。
## add
draft_artifact.add_file("file_to_add.txt")
## remove
draft_artifact.remove("file_to_remove.txt") 
## modify
draft_artifact.remove("modified_file.txt")
draft_artifact.add_file("modified_file.txt")

# 最後に、変更をログまたは保存します。以下のタブは、W&Bランの内外で変更を保存する方法を示しています
## runの中で実行
run.log_artifact(draft_artifact)

## runの外で実行
draft_artifact.save()

それ以外に、複数のrunsがバージョンを共同で作成することができます(分散処理を行う際などに使用します)。コラボレーティブモードを使用する際には、次の2つの重要な点を理解しておく必要があります。

  1. コレクション内の各Runは、同じ一意のID(distributed_idと呼ばれる)を認識して、同じバージョンで協力する必要があります。デフォルトでは、WandBは、wandb.init(group=GROUP)で設定されたrunのgroupをdistributed_idとして使用します(もしある場合)。

  2. 状態を永続的にロックするバージョンを"コミット"する最終的なrunが必要です。次のRun 1・Run2・Run3は、これらの流れを示した例です。log_artifactを使う代わりに、upsert_artifactを使ってコラボレーションアーティファクトを追加し、finish_artifactを使ってコミットを確定します。Run3については、Run 1およびRun 2が完了した後に実行する必要があります。finish_artifactを呼び出すRunでは、アーティファクトにファイルを含めることができますが、必ずしも含める必要はありません。

######  Run1  ######
with wandb.init() as run:
    artifact = wandb.Artifact("artifact_name", "artifact_type")
    # アーティファクトにファイルやアセットを追加する方法は
    # `.add`, `.add_file`, `.add_dir`, そして `.add_reference` を使います
    artifact.add_file("image1.png")
    run.upsert_artifact(artifact, distributed_id="my_dist_artifact")



######  Run2  ######
with wandb.init() as run:
    artifact = wandb.Artifact("artifact_name", "artifact_type")
    # アーティファクトにファイルやアセットを追加するには、
    # `.add``.add_file``.add_dir``.add_reference`を使用します
    artifact.add_file("image2.png")
    run.upsert_artifact(artifact, distributed_id="my_dist_artifact")



######  Run3  ######
with wandb.init() as run:
    artifact = wandb.Artifact("artifact_name", "artifact_type")
    # アーティファクトにファイルやアセットを追加する
    # `.add`, `.add_file`, `.add_dir`, および `.add_reference`
    artifact.add_file("image3.png")
    run.finish_artifact(artifact, distributed_id="my_dist_artifact")

以上の機能を駆使することで、WandBのアーティファクトを最大限に利用し、MLプロジェクトにおける属人的にならないデータ管理を実現することができます。

まとめ

この記事では、WandBの強力なデータ管理機能であるアーティファクトについて解説をしました。最後に、ユーザー様の声を紹介します。

モデルパイプラインのすべてを保存することは、デバッグ・出どころ・再現性の観点で機械学習のために不可欠です。W&Bはこれを遂行するのに最適なツールです
—Richard Socher, fmr Chief Data Scientist, Saleforce

実験の設定や結果だけではなく、それらを生み出すデータやそこから生み出された結果も合わせて管理することで、再現性や透明性が上がり、個人・チームのML開発が大きく前に進みます。是非みなさんもWandBのアーティファクトを活用してください!

この記事が気に入ったらサポートをしてみませんか?