wandb.Table を使用して、W&B で可視化およびクエリの実行ができるデータを記録します。このガイドでは、次の内容について説明します:
- テーブルを作成する
- データを追加する
- データを取得する
- テーブルを保存する
テーブルを定義するには、各データ行に対して表示したい列を指定します。各行は、学習データセット内の単一アイテム、学習中の特定のステップまたはエポック、テストアイテムに対してモデルが行った予測、モデルが生成したオブジェクトなどを表すことができます。各列には、数値、テキスト、ブール値、画像、動画、音声などの固定された型があります。あらかじめ型を指定しておく必要はありません。各列に名前を付け、その列には必ずその型のデータだけを渡すようにしてください。より詳細な例については、W&B Tables ガイド を参照してください。
wandb.Table コンストラクタは次のいずれかの方法で使用します。
-
行のリスト:
名前付き列とデータの行をログします。たとえば、次のコードスニペットは 2 行 3 列のテーブルを生成します:
wandb.Table(columns=["a", "b", "c"], data=[["1a", "1b", "1c"], ["2a", "2b", "2c"]])
-
Pandas DataFrame:
wandb.Table(dataframe=my_df) を使用して DataFrame をログします。列名は DataFrame から抽出されます。
# モデルが4枚の画像に対して予測を返したと仮定する
# 以下のフィールドが利用可能:
# - 画像ID
# - wandb.Image()でラップされた画像ピクセル
# - モデルの予測ラベル
# - 正解ラベル
my_data = [
[0, wandb.Image("img_0.jpg"), 0, 0],
[1, wandb.Image("img_1.jpg"), 8, 0],
[2, wandb.Image("img_2.jpg"), 7, 1],
[3, wandb.Image("img_3.jpg"), 1, 1],
]
# 対応するカラムでwandb.Table()を作成する
columns = ["id", "image", "prediction", "truth"]
test_table = wandb.Table(data=my_data, columns=columns)
Tables は可変です。スクリプトの実行中に、最大 200,000 行までテーブルにデータを追加できます。テーブルにデータを追加する方法は 2 つあります。
- 行を追加する:
table.add_data("3a", "3b", "3c")。新しい行はリストとしては表現されない点に注意してください。行がリスト形式の場合は、アスタリスク記法 * を使って、そのリストを位置引数として展開します: table.add_data(*my_row_list)。行には、テーブル内の列数と同じ数の要素が含まれている必要があります。
- 列を追加する:
table.add_column(name="col_name", data=col_data)。col_data の長さは、テーブルの現在の行数と等しくなければならない点に注意してください。ここで col_data は、リスト形式のデータ、または NumPy の NDArray で指定できます。
次のコードサンプルは、W&B テーブルを段階的に作成してデータを追加する方法を示します。あらかじめ、すべてのラベルに対する信頼度スコアを含む列を定義しておき、推論中に 1 行ずつデータを追加します。run を再開したときにも、テーブルにデータを段階的に追加することができます。
# テーブルの列を定義する(各ラベルの信頼スコアを含む)
columns = ["id", "image", "guess", "truth"]
for digit in range(10): # 各数字(0〜9)の信頼スコア列を追加する
columns.append(f"score_{digit}")
# 定義した列でテーブルを初期化する
test_table = wandb.Table(columns=columns)
# テストデータセットを反復処理し、テーブルに1行ずつデータを追加する
# 各行には画像ID、画像、予測ラベル、正解ラベル、信頼スコアが含まれる
for img_id, img in enumerate(mnist_test_data):
true_label = mnist_test_data_labels[img_id] # 正解ラベル
guess_label = my_model.predict(img) # 予測ラベル
test_table.add_data(
img_id, wandb.Image(img), guess_label, true_label
) # テーブルに行データを追加する
再開した run では、アーティファクトから既存のテーブルを読み込み、最後の行のデータを取得して更新されたメトリクスを追加することで、W&B テーブルを段階的に更新できます。その後、互換性を保つためにテーブルを再初期化し、更新版を W&B に再度ログします。
import wandb
# runを初期化する
with wandb.init(project="my_project") as run:
# アーティファクトから既存のテーブルを読み込む
best_checkpt_table = run.use_artifact(table_tag).get(table_name)
# 再開用にテーブルの最終行データを取得する
best_iter, best_metric_max, best_metric_min = best_checkpt_table.data[-1]
# 必要に応じてベストメトリクスを更新する
# 更新されたデータをテーブルに追加する
best_checkpt_table.add_data(best_iter, best_metric_max, best_metric_min)
# 互換性を確保するため、更新されたデータでテーブルを再初期化する
best_checkpt_table = wandb.Table(
columns=["col1", "col2", "col3"], data=best_checkpt_table.data
)
# runを初期化する
with wandb.init() as run:
# 更新されたテーブルをW&Bにログする
run.log({table_name: best_checkpt_table})
データが Table に保存されたら、列または行単位でアクセスできます。
- Row Iterator: ユーザーは
for ndx, row in table.iterrows(): ... のように Table の行イテレーターを使用して、データの各行を効率的に繰り返し処理できます。
- Get a Column: ユーザーは
table.get_column("col_name") を使ってデータの列を取得できます。便利な機能として、convert_to="numpy" を渡すことで、その列をプリミティブ型の NumPy NDArray に変換できます。列に wandb.Image などのメディアタイプが含まれている場合、元のデータに直接アクセスできるため便利です。
スクリプト内でデータのテーブル(例: モデル予測のテーブル)を生成したら、そのテーブルを W&B に保存して、結果をリアルタイムで可視化します。
wandb.Run.log() を使って、次のようにテーブルを run に記録します。
with wandb.init() as run:
my_table = wandb.Table(columns=["a", "b"], data=[["1a", "1b"], ["2a", "2b"]])
run.log({"table_key": my_table})
同じキーにテーブルをログするたびに、新しいバージョンのテーブルが作成され、バックエンドに保存されます。これは、同じテーブルを複数の学習ステップにわたってログして、時間の経過とともにモデルの予測がどのように改善されるかを確認したり、同じキーにログしている限り、異なる run 間でテーブルを比較したりできることを意味します。最大で 200,000 行までログできます。
200,000 行を超えてログするには、次のように上限を変更できます:wandb.Table.MAX_ARTIFACT_ROWS = Xただし、その場合、UI でのクエリが遅くなるなどのパフォーマンス問題が発生する可能性があります。
バックエンドでは、Tables はアーティファクトとして保存されます。特定のバージョンにアクセスしたい場合は、アーティファクト API を使用できます。
with wandb.init() as run:
my_table = run.use_artifact("run-<run-id>-<table-name>:<tag>").get("<table-name>")
Artifacts の詳細については、Developer Guide の「Artifacts」章を参照してください。
この方法でログされたテーブルは、Workspace の Run ページと Project ページの両方に表示されます。詳細については、テーブルの可視化と分析を参照してください。
artifact.add() を使用して、テーブルをワークスペースではなく run の Artifacts セクションに記録します。これは、一度だけ記録しておき、今後の run から参照したいデータセットがある場合に便利です。
with wandb.init(project="my_project") as run:
# 意味のある各ステップに対してwandb アーティファクトを作成する
test_predictions = wandb.Artifact("mnist_test_preds", type="predictions")
# [上記と同様に予測データを構築する]
test_table = wandb.Table(data=data, columns=columns)
test_predictions.add(test_table, "my_test_key")
run.log_artifact(test_predictions)
画像データを用いた artifact.add() の詳細な例についてはこの Colab を、Artifacts と Tables を使って表形式データのバージョン管理と重複排除を行う方法の例についてはこのレポート を参照してください。
ローカルで作成したテーブル、または他のアーティファクトから取得したテーブルを、wandb.JoinedTable(table_1, table_2, join_key) を使って結合できます。
| Args | Description |
|---|
| table_1 | (str, wandb.Table, ArtifactEntry) アーティファクト内の wandb.Table へのパス、テーブルオブジェクト、または ArtifactEntry |
| table_2 | (str, wandb.Table, ArtifactEntry) アーティファクト内の wandb.Table へのパス、テーブルオブジェクト、または ArtifactEntry |
| join_key | (str, [str, str]) 結合を行うときに使用するキー、またはキーのリスト |
アーティファクトのコンテキストで以前にログした 2 つの Table を結合するには、それらをアーティファクトから取得し、その結果を新しい Table に結合します。
たとえば、次のコード例では、'original_songs' というオリジナル楽曲の Table と、同じ楽曲の合成バージョンの Table である 'synth_songs' を読み込みます。コードは 2 つのテーブルを "song_id" で結合し、その結果得られたテーブルを新しい W&B Table としてアップロードします。
import wandb
with wandb.init(project="my_project") as run:
# オリジナル曲のテーブルを取得
orig_songs = run.use_artifact("original_songs:latest")
orig_table = orig_songs.get("original_samples")
# 合成曲のテーブルを取得
synth_songs = run.use_artifact("synth_songs:latest")
synth_table = synth_songs.get("synth_samples")
# "song_id" でテーブルを結合
join_table = wandb.JoinedTable(orig_table, synth_table, "song_id")
join_at = wandb.Artifact("synth_summary", "analysis")
# テーブルをアーティファクトに追加して W&B にログ
join_at.add(join_table, "synth_explore")
run.log_artifact(join_at)
このチュートリアルでは、異なるアーティファクトオブジェクトに保存されている 2 つの既存のテーブルを結合する方法の一例が示されています。