W&B のパブリック API を使用してデータをエクスポートまたはインポートします。
この機能を利用するには Python 3.8 以上が必要です。
W&B は MLFlow からのデータインポートをサポートしており、実験、run、アーティファクト、メトリクス、その他のメタデータを取り込むことができます。
依存関係をインストールします:
# 注意: py38以上が必要です
pip install wandb[importers]
W&B にログインします。初めてログインする場合は、表示される指示に従ってください。
既存の MLFlow サーバーからすべての run をインポートする:
from wandb.apis.importers.mlflow import MlflowImporter
importer = MlflowImporter(mlflow_tracking_uri="...")
runs = importer.collect_runs()
importer.import_runs(runs)
デフォルトでは、importer.collect_runs() は MLflow サーバーからすべての run を収集します。特定のサブセットだけをアップロードしたい場合は、独自の run のイテラブルを作成し、それを importer に渡すことができます。
import mlflow
from wandb.apis.importers.mlflow import MlflowRun
client = mlflow.tracking.MlflowClient(mlflow_tracking_uri)
runs: Iterable[MlflowRun] = []
for run in mlflow_client.search_runs(...):
runs.append(MlflowRun(run, client))
importer.import_runs(runs)
Databricks MLFlow からインポートする場合は、先に Databricks CLI を構成する 必要がある場合があります。前のステップで mlflow-tracking-uri="databricks" を設定してください。
アーティファクトのインポートをスキップするには、artifacts=False を引数として渡します。
importer.import_runs(runs, artifacts=False)
特定の W&B エンティティとプロジェクトにインポートするには、Namespace を指定します。
from wandb.apis.importers import Namespace
importer.import_runs(runs, namespace=Namespace(entity, project))
Public API を使用して、W&B に保存したデータをエクスポートしたり更新したりできます。この API を使用する前に、スクリプトからデータをログしてください。詳細については クイックスタート を参照してください。
Public API のユースケース
- データのエクスポート: Jupyter Notebook でのカスタム分析用に dataframe(データフレーム)を取得します。データを分析した後、新しい分析 run を作成して結果をログすることで、知見を同期できます。例:
wandb.init(job_type="analysis")
- 既存の Runs の更新: W&B の run に関連付けてログされたデータを更新できます。たとえば、一連の runs の config を更新して、アーキテクチャや、元々はログしていなかったハイパーパラメータなどの追加情報を含めることができます。
利用可能な関数の詳細については、Generated Reference Docs を参照してください。
APIキーは、マシンをW&Bに対して認証します。
APIキーを作成するには、Personal API key または Service Account API key タブを選択して詳細を確認します。
Personal API key
Service account API key
ユーザーIDに紐づく個人用APIキーを作成するには、次の手順を実行します。
- W&B にログインし、ユーザープロフィールアイコンをクリックしてから User Settings をクリックします。
- Create new API key をクリックします。
- APIキーのわかりやすい名前を入力します。
- Create をクリックします。
- 表示されたAPIキーをすぐにコピーし、安全な場所に保管します。
サービスアカウントが所有するAPIキーを作成するには、次の手順を実行します。
- チームまたは組織の設定の Service Accounts タブに移動します。
- 一覧から対象のサービスアカウントを探します。
- アクションメニュー(
...)をクリックし、Create API key をクリックします。
- APIキーの名前を入力し、Create をクリックします。
- 表示されたAPIキーをすぐにコピーして、安全な場所に保管します。
- Done をクリックします。
異なる環境やワークフローをサポートするために、1つのサービスアカウントに対して複数のAPIキーを作成できます。
完全なAPIキーは作成時に一度だけ表示されます。ダイアログを閉じると、完全なAPIキーを再度表示することはできません。設定で表示されるのは、キーID(キーの先頭部分)のみです。完全なAPIキーを紛失した場合は、新しいAPIキーを作成する必要があります。
安全に保管する方法については、APIキーを安全に保管するを参照してください。
APIキーはW&Bアカウントへのアクセス手段となるため、パスワードと同様に保護する必要があります。次のベストプラクティスに従ってください。
- Git などのバージョン管理システムに APIキーを決してコミットしないでください。
- APIキーをプレーンテキストの設定ファイルに保存しないでください。
ps のような OS コマンドの出力に表示されてしまうため、コマンドラインで APIキーを渡さないでください。
- メール、チャット、その他の暗号化されていないチャネルで APIキーを共有することは避けてください。
- ソースコード内に APIキーをハードコードしないでください。
APIキーが漏えいした場合は、ただちに W&B アカウントからその APIキーを削除し、support か AISE に連絡してください。
コード内でAPIキーを使用するときは、環境変数経由で渡してください。
export WANDB_API_KEY="your-api-key-here"
この方法を使うと、キーをソースコードから分離でき、必要に応じてローテーションしやすくなります。
コマンドと同じ行で環境変数を設定するのは避けてください。その方法では、ps などの OS コマンドの出力に値が表示されてしまいます。# このパターンは避けてください。APIキーがプロセス一覧に表示される可能性があります
export WANDB_API_KEY="your-api-key-here" ./my-script.sh
新しい APIキー は従来のキーよりも長くなっています。古いバージョンの wandb または weave SDK で認証する場合、APIキー の長さに関するエラーが発生する場合があります。
解決策: SDK を新しいバージョンに更新してください。
-
wandb SDK v0.22.3+
pip install --upgrade wandb==0.22.3
-
weave SDK v0.52.17+
pip install --upgrade weave==0.52.17
すぐに SDK をアップグレードできない場合は、回避策として WANDB_API_KEY 環境変数を使って APIキー を設定してください。
Public API を使用する場合、多くの場合は <entity>/<project>/<run_id> という形式の run パスが必要になります。アプリの UI で run のページを開き、Overview タブ をクリックして run パスを確認します。
完了済みまたは実行中の run からデータをダウンロードできます。代表的な利用例としては、Jupyter Notebook でのカスタム解析用にデータフレームをダウンロードしたり、自動化された環境でカスタムロジックから利用したりするケースなどがあります。
import wandb
api = wandb.Api()
run = api.run("<entity>/<project>/<run_id>")
run オブジェクトでもっともよく使用される属性は次のとおりです:
| Attribute | Meaning |
|---|
run.config | run の設定情報を格納する辞書。たとえば、学習 run のハイパーパラメータや、データセットアーティファクトを作成する run の前処理手法などです。run の入力と考えてください。 |
run.history() | モデルが学習している間に変化する値(損失など)を保存するための辞書のリストです。run.log() コマンドはこのオブジェクトに追記します。 |
run.summary | run の結果を要約する情報を格納する辞書です。精度や損失といったスカラー値や、大きなファイルを含むこともできます。デフォルトでは、run.log() はログされた時系列データの最終値を summary に設定します。summary の内容は直接設定することもできます。summary は run の出力と考えてください。 |
過去の run のデータを変更または更新することもできます。デフォルトでは、単一の API オブジェクトインスタンスがすべてのネットワークリクエストをキャッシュします。実行中のスクリプトでリアルタイムな情報が必要な場合は、api.flush() を呼び出して最新の値を取得してください。
次のコードスニペットは、run を作成してデータをログに記録し、その後で run の属性にアクセスする方法を示しています。
import wandb
import random
with wandb.init(project="public-api-example") as run:
n_epochs = 5
config = {"n_epochs": n_epochs}
run.config.update(config)
for n in range(run.config.get("n_epochs")):
run.log(
{"val": random.randint(0, 1000), "loss": (random.randint(0, 1000) / 1000.00)}
)
次のセクションでは、上記の run オブジェクトの各属性に対するさまざまな出力について説明します
run.config
{
"_runtime": 4,
"_step": 4,
"_timestamp": 1644345412,
"_wandb": {"runtime": 3},
"loss": 0.041,
"val": 525,
}
デフォルトの history メソッドでは、メトリクスを固定数のサンプルにサンプリングします(デフォルトは 500 で、samples 引数で変更できます)。大規模な run のすべてのデータをエクスポートしたい場合は、run.scan_history() メソッドを使用できます。詳細については、API Reference を参照してください。
DataFrame と CSV
MongoDB スタイル
このサンプルスクリプトは、特定のプロジェクトを指定して、run の名前・config・サマリ統計情報を含む CSV を出力します。<entity> と <project> を、それぞれあなたの W&B の entity とプロジェクト名に置き換えてください。import pandas as pd
import wandb
api = wandb.Api()
entity, project = "<entity>", "<project>"
runs = api.runs(entity + "/" + project)
summary_list, config_list, name_list = [], [], []
for run in runs:
# .summary には、accuracy などの
# メトリクスの出力キー・値が含まれます。
# 大きなファイルを含めないように ._json_dict を呼び出します。
summary_list.append(run.summary._json_dict)
# .config にはハイパーパラメータが含まれます。
# 先頭が _ の特殊な値は削除します。
config_list.append({k: v for k, v in run.config.items() if not k.startswith("_")})
# .name は run の人間が読める名前です。
name_list.append(run.name)
runs_df = pd.DataFrame(
{"summary": summary_list, "config": config_list, "name": name_list}
)
runs_df.to_csv("project.csv")
run.finish()
W&B API では、api.runs() を使ってプロジェクト内の run を横断的にクエリする方法も提供しています。最も一般的なユースケースは、カスタム分析のために run のデータをエクスポートすることです。クエリインターフェースは MongoDB が使用しているもの と同じです。runs = api.runs(
"username/project",
{"$or": [{"config.experiment_name": "foo"}, {"config.experiment_name": "bar"}]},
)
print(f"Found {len(runs)} runs")
api.runs を呼び出すと、繰り返し処理が可能でリストのように扱える Runs オブジェクトが返されます。デフォルトでは、このオブジェクトは必要に応じて一度に 50 個ずつ run を順番に読み込みますが、per_page キーワード引数で 1 ページあたりに読み込む数を変更できます。
api.runs は order キーワード引数も受け取ります。デフォルトの順序は -created_at です。昇順で並べ替えるには +created_at を指定します。config や summary の値でソートすることもできます。たとえば summary.val_acc や config.experiment_name などです。
W&B サーバーとの通信中にエラーが発生すると、wandb.CommError が送出されます。元の例外は exc 属性を通じて参照できます。
API を使って最新の git commit を取得する
UI で対象の run をクリックし、run ページの Overview タブをクリックすると、最新の git commit を確認できます。最新の git commit はファイル wandb-metadata.json にも含まれています。public API を使う場合は、run.commit で git のハッシュ値を取得できます。
run 実行中に run の name と ID を取得する
wandb.init() を呼び出したあと、スクリプト内からランダムな run ID や、人間が読みやすい run name には次のようにアクセスできます:
- 一意の run ID(8 文字のハッシュ):
run.id
- ランダムな run name(人間が読みやすい):
run.name
run に対して有用な識別子をどう設定するか検討している場合は、次のように設定することをおすすめします:
- Run ID: 生成されたハッシュのままにします。これは、プロジェクト内の run 間で一意である必要があります。
- Run name: 短く、読みやすく、可能であれば一意なものにしてください。チャート上の異なる線を見分けられるようにするためです。
- Run notes: run で何をしているかを簡潔に説明するのに最適な場所です。
wandb.init(notes="your notes here") で設定できます。
- Run tags: run tags で動的に情報を追跡し、UI のフィルターを使って、関心のある run だけにテーブルを絞り込めます。スクリプトからタグを設定し、その後 UI の runs テーブルおよび run ページの overview タブの両方で編集できます。詳細な手順はこちらを参照してください。
matplotlib または seaborn で可視化するためのデータをエクスポートする
一般的なエクスポートパターンについては、API examples を参照してください。カスタムプロットまたは拡大表示した Runs テーブルでダウンロードボタンをクリックして、ブラウザから CSV ファイルをダウンロードすることもできます。
この例では、"<entity>/<project>/<run_id>" に保存されている run から、run.log({"accuracy": acc}) で保存されたタイムスタンプと精度を出力します。
import wandb
api = wandb.Api()
run = api.run("<entity>/<project>/<run_id>")
if run.state == "finished":
for i, row in run.history().iterrows():
print(row["_timestamp"], row["accuracy"])
MongoDB Query Language を使用して run を絞り込むことができます。
runs = api.runs(
"<entity>/<project>",
{"$and": [{"created_at": {"$lt": "YYYY-MM-DDT##", "$gt": "YYYY-MM-DDT##"}}]},
)
run から特定のメトリクスを取得するには、keys 引数を使用します。run.history() を使用する場合のデフォルトのサンプル数は 500 です。特定のメトリクスを含まないログされたステップは、出力データフレームでは NaN として表示されます。keys 引数を指定すると、API は指定したメトリクスキーを含むステップをより高い頻度でサンプリングします。
import wandb
api = wandb.Api()
run = api.run("<entity>/<project>/<run_id>")
if run.state == "finished":
for i, row in run.history(keys=["accuracy"]).iterrows():
print(row["_timestamp"], row["accuracy"])
これにより、run1 と run2 の間で異なる config パラメータが出力されます。
import pandas as pd
import wandb
api = wandb.Api()
# <entity>、<project>、<run_id> を実際の値に置き換えてください
run1 = api.run("<entity>/<project>/<run_id>")
run2 = api.run("<entity>/<project>/<run_id>")
df = pd.DataFrame([run1.config, run2.config]).transpose()
df.columns = [run1.name, run2.name]
print(df[df[run1.name] != df[run2.name]])
出力例:
c_10_sgd_0.025_0.01_long_switch base_adam_4_conv_2fc
batch_size 32 16
n_conv_layers 5 4
optimizer rmsprop adam
この例では、既存の run の accuracy を 0.9 に設定します。また、既存の run の accuracy ヒストグラムを、numpy_array のヒストグラムに変更します。
import wandb
api = wandb.Api()
run = api.run("<entity>/<project>/<run_id>")
run.summary["accuracy"] = 0.9
run.summary["accuracy_histogram"] = wandb.Histogram(numpy_array)
run.summary.update()
この例では、テーブルのサマリー列の名前を変更します。
import wandb
api = wandb.Api()
run = api.run("<entity>/<project>/<run_id>")
run.summary["new_name"] = run.summary["old_name"]
del run.summary["old_name"]
run.summary.update()
列名の変更はテーブルにのみ適用されます。チャートではメトリクスは引き続き元の名前で参照されます。
この例では、設定の一つを更新します。
import wandb
api = wandb.Api()
run = api.run("<entity>/<project>/<run_id>")
run.config["key"] = updated_value
run.update()
システムリソース使用量を CSV ファイルにエクスポートする
以下のスニペットは、システムリソースの使用量を取得し、CSV ファイルに保存します。
import wandb
with wandb.Api().run("<entity>/<project>/<run_id>") as run:
system_metrics = run.history(stream="events")
system_metrics.to_csv("sys_metrics.csv")
サンプリングされていないメトリックデータを取得する
history からデータを取得すると、デフォルトでは 500 個のポイントにサンプリングされます。run.scan_history() を使うと、ログされたすべてのデータポイントを取得できます。以下は、history にログされたすべての loss データポイントをダウンロードする例です。
import wandb
api = wandb.Api()
run = api.run("<entity>/<project>/<run_id>")
history = run.scan_history()
losses = [row["loss"] for row in history]
history からページングされたデータを取得する
バックエンドでのメトリクスの取得が遅い場合や API リクエストがタイムアウトする場合は、scan_history のページサイズを小さくして、各リクエストがタイムアウトしないようにしてみてください。デフォルトのページサイズは 500 なので、どのサイズが最適か確認するために、さまざまなサイズを試してみてください。
import wandb
api = wandb.Api()
run = api.run("<entity>/<project>/<run_id>")
run.scan_history(keys=sorted(cols), page_size=100)
プロジェクト内のすべての run のメトリクスを CSV ファイルにエクスポートする
このスクリプトは、指定したプロジェクト内の run を取得し、run の名前、config、サマリー統計を含むデータフレームと CSV ファイルを生成します。<entity> と <project> を、それぞれあなたの W&B のエンティティとプロジェクト名に置き換えてください。
import pandas as pd
import wandb
api = wandb.Api()
entity, project = "<entity>", "<project>"
runs = api.runs(entity + "/" + project)
summary_list, config_list, name_list = [], [], []
for run in runs:
# .summary には、accuracyなどのメトリクスの出力キーと値が含まれます。
# 大きなファイルを省略するために ._json_dict を呼び出します。
summary_list.append(run.summary._json_dict)
# .config にはハイパーパラメータが含まれます。
# _ で始まる特殊な値は除外します。
config_list.append({k: v for k, v in run.config.items() if not k.startswith("_")})
# .name は run の人間が読める名前です。
name_list.append(run.name)
runs_df = pd.DataFrame(
{"summary": summary_list, "config": config_list, "name": name_list}
)
runs_df.to_csv("project.csv")
このコードスニペットでは、run が作成された時刻を取得します。
import wandb
api = wandb.Api()
run = api.run("entity/project/run_id")
start_time = run.created_at
以下のコードスニペットでは、選択したファイルを完了した run にアップロードします。
import wandb
api = wandb.Api()
run = api.run("entity/project/run_id")
run.upload_file("file_name.extension")
これは、cifar プロジェクト内の run ID uxte44z7 に関連付けられたファイル「model-best.h5」を取得してローカルに保存します。
import wandb
api = wandb.Api()
run = api.run("<entity>/<project>/<run_id>")
run.file("model-best.h5").download()
指定した run に関連付けられているすべてのファイルを取得し、ローカルに保存します。
import wandb
api = wandb.Api()
run = api.run("<entity>/<project>/<run_id>")
for file in run.files():
file.download()
このスニペットでは、特定のスイープに紐づくすべての run をダウンロードします。
import wandb
api = wandb.Api()
sweep = api.sweep("<entity>/<project>/<sweep_id>")
sweep_runs = sweep.runs
次のスニペットでは、指定したスイープから最良の run を取得します。
import wandb
api = wandb.Api()
sweep = api.sweep("<entity>/<project>/<sweep_id>")
best_run = sweep.best_run()
best_run は、スイープ設定の metric パラメータで指定されたメトリクスが最も良い値を取る run です。
スイープから最良のモデルファイルをダウンロードする
このスニペットは、モデルファイルを model.h5 として保存した run を含むスイープから、検証精度が最も高いモデルファイルをダウンロードします。
import wandb
api = wandb.Api()
sweep = api.sweep("<entity>/<project>/<sweep_id>")
runs = sorted(sweep.runs, key=lambda run: run.summary.get("val_acc", 0), reverse=True)
val_acc = runs[0].summary.get("val_acc", 0)
print(f"Best run {runs[0].name} with {val_acc}% val accuracy")
runs[0].file("model.h5").download(replace=True)
print("Best model saved to model-best.h5")
run から指定した拡張子を持つファイルをすべて削除する
このスニペットは、run から指定した拡張子を持つファイルをすべて削除します。
import wandb
api = wandb.Api()
run = api.run("<entity>/<project>/<run_id>")
extension = ".png"
files = run.files()
for file in files:
if file.name.endswith(extension):
file.delete()
このスニペットは、特定の run に対するすべてのシステムリソース使用状況メトリクスを含むデータフレームを生成し、その後 CSV ファイルとして保存します。
import wandb
api = wandb.Api()
run = api.run("<entity>/<project>/<run_id>")
system_metrics = run.history(stream="events")
system_metrics.to_csv("sys_metrics.csv")
辞書を渡してサマリーメトリクスを更新できます。
summary.update({"key": val})
各 run では、その run の起動に使用されたコマンドが run の概要ページに記録されています。API からこのコマンドを取得するには、次を実行します。
import wandb
api = wandb.Api()
run = api.run("<entity>/<project>/<run_id>")
meta = json.load(run.file("wandb-metadata.json").download())
program = ["python"] + [meta["program"]] + meta["args"]