メディアとオブジェクトのログ化
画像、ビデオ、オーディオなど、さまざまなメディアに対応しています。豊富なメディアをログ化して、結果を探索し、run、モデル、データセットを視覚的に比較してみてください。以下に例とハウツーガイドをご紹介します。
各種メディアタイプのリファレンスドキュメントをお探しですか?このページをご覧ください。
これらのメディアオブジェクトをすべてログ化するための動作コードは、このColabノートブックでご覧いただけます。wandb.aiでの結果の見た目はこちらで確認できます。ビデオチュートリアルも上記リンクからご覧いただけます。
画像
入力、出力、フィルターの重み、活性化関数などをトラッキングするために画像をログ化しましょう!
画像は、NumPy配列から直接、PIL画像として、またはファイルシステムからログ化できます。
トレーニング中のログ化がボトルネックにならないように、1ステップあたり50枚以下の画像をログ化することをお勧めします。また、結果を表示する際に画像の読み込みがボトルネックにならないようにするためにもこの枚数にしてください。
- 配列を画像としてログに記録
- PIL画像をログに記録
- ファイルからの画像をログに記録
手動で画像を作成する際に、例えば torchvision
からの make_grid
を使用して、配列を直接提供します。
配列は、Pillowを使用してpngに変換されます。
images = wandb.Image(
image_array,
caption="Top: Output, Bottom: Input"
)
wandb.log({"examples": images}
最後の次元が1の場合、画像をグレースケールと仮定し、3の場合は RGB とし、4の場合は RGBA とします。配列に float が含まれている場合、0
から 255
までの整数に変換します。画像を異なる方法で正規化したい場合は、mode
を手動で指定するか、このパネルの "PIL画像をログに記録" タブで説明されているように、PIL.Image
を提供してください。
配列を画像に変換する際の完全な制御が必要な場合は、 PIL.Image
を自分で作成し、直接提供してください。
images = [PIL.Image.fromarray(image) for image in image_array]
wandb.log({"examples": [wandb.Image(image) for image in images]}
im = PIL.fromarray(...)
rgb_im = im.convert('RGB')
rgb_im.save('myimage.jpg')
wandb.log({"example": wandb.Image("myimage.jpg")})
画像オーバーレイ
- セグメンテーションマスク
- バウンディングボックス
W&B UI を介してセマンティックセグメンテーションマスクをログし、それらと対話します(不透明度の変更、時間の経過に伴う変化の表示など)。
オーバーレイをログに記録するには、wandb.Image
の masks
キーワード引数に、次のキーと値を持つ辞書を提供する必要があります。
- 画像マスクを表す2つのキーのうちの1つ:
"mask_data"
:各ピクセルに対して整数のクラスラベルを持つ2D NumPy配列"path"
:(文字列)保存された画像マスクファイルへのパス
"class_labels"
:(オプション)画像マスク内の整数クラスラベルを読みやすいクラス名にマッピングする辞書
複数のマスクをログに記録するには、以下のコードスニペットのように、複数のキーを持つマスク辞書をログに記録します。
mask_data = np.array([[1, 2, 2, ... , 2, 2, 1], ...])
class_labels = {
1: "tree",
2: "car",
3: "road"
}
mask_img = wandb.Image(image, masks={
"predictions": {
"mask_data": mask_data,
"class_labels": class_labels
},
"ground_truth": {
...
},
...
})
バウンディングボックスをログに記録するには、以下のキーと値を持つ辞書を wandb.Image
の boxes キーワード引数に提供する必要があります。
box_data
:各ボックス用の辞書のリスト。ボックス辞書の形式は以下で説明します。position
:以下で説明する2つの形式のうちの1つで、ボックスの位置とサイズを表す辞書。すべてのボックスが同じ形式を使用する必要はありません。- オプション1:
{"minX", "maxX", "minY", "maxY"}
。各ボックスの次元の上限と下限を定義する座標のセットを提供します。 - オプション2:
{"middle", "width", "height"}
。middle
座標を[x, y]
として指定し、width
とheight
をスカラーとして指定する座標のセットを提供します。
- オプション1:
class_id
:ボックスのクラスIDを表す整数。以下のclass_labels
キーを参照してください。scores
: スコア用の文字列ラベルと数値値の辞書。UIでボックスをフィルタリングするために使用できます。domain
: ボックス座標の単位/形式を指定します。 "pixel"に設定してください。ボックス座標がピクセル空間で表現されている場合(つまり、画像の次元の境界内で整数として)。デフォルトでは、ドメインは画像の分数/パーセンテージ(0から1の浮動小数点数)と仮定されます。box_caption
:(オプション)このボックスのラベルテキストとして表示される文字列
class_labels
:(オプション)class_id
を文字列にマッピングする辞書。デフォルトでは、class_0
、class_1
などのクラスラベルが生成されます。
この例をチェックしてください。
class_id_to_label = {
1: "car",
2: "road",
3: "building",
....
}
img = wandb.Image(image, boxes={
"predictions": {
"box_data": [{
# default relative/fractional domainで表現された1つのボックス
"position": {
"minX": 0.1,
"maxX": 0.2,
"minY": 0.3,
"maxY": 0.4
},
"class_id" : 2,
"box_caption": class_id_to_label[2],
"scores" : {
"acc": 0.1,
"loss": 1.2
},
# ピクセルドメインで表現された別のボックス
# (説明目的のみで、すべてのボックスが同じドメイン/形式になる可能性があります)
"position": {
"middle": [150, 20],
"width": 68,
"height": 112
},
"domain" : "pixel",
"class_id" : 3,
"box_caption": "a building",
"scores" : {
"acc": 0.5,
"loss": 0.7
},
...
# 必要なだけボックスをログに記録する
}
],
"class_labels": class_id_to_label
},
# 各意味のあるボックスのグループを一意のキー名でログに記録する
"ground_truth": {
...
}
})
wandb.log({"driving_scene": img})
テーブル内の画像オーバーレイ
- セグメンテーションマスク
- バウンディングボックス
テーブル内にセグメンテーションマスクをログするには、各行に対してwandb.Image
オブジェクトを提供する必要があります。
以下のコードスニペットで例を示しています。
table = wandb.Table(columns=['ID', 'Image'])
for id, img, label in zip(ids, images, labels):
mask_img = wandb.Image(img, masks = {
"prediction" : {
"mask_data" : label,
"class_labels" : class_labels
},
...
})
table.add_data(id, img)
wandb.log({"Table" : table})
テーブルにバウンディングボックス付きの画像をログするには、テーブルの各行にwandb.Image
オブジェクトを提供する必要があります。
以下のコードスニペットに例が示されています。
table = wandb.Table(columns=['ID', 'Image'])
for id, img, boxes in zip(ids, images, boxes_set):
box_img = wandb.Image(img, boxes = {
"prediction" : {
"box_data" : [{
"position" :{
"minX" : box["minX"],
"minY" : box["minY"],
"maxX" : box["maxX"],
"maxY" : box["maxY"]
},
"class_id" : box["class_id"],
"box_caption" : box["caption"],
"domain" : "pixel"
}
for box in boxes
],
"class_labels" : class_labels
}
})
- 基本的なヒストグラムのログ記録
- 柔軟なヒストグラムのログ記録
- サマリー内のヒストグラム
数値のシーケンス(例: リスト、配列、テンソル)が最初の引数として提供される場合、np.histogram
を呼び出すことで自動的にヒストグラムが作成されます。注意していただきたいのは、すべての配列/テンソルが平坦化されることです。デフォルトの64
ビンを上書きするために、オプションのnum_bins
キーワード引数を使用することができます。サポートされているビンの最大数は512
です。
UIでは、ヒストグラムはトレーニングステップをx軸に、メトリック値をy軸に、カウントを色で表現し、トレーニング全体でログ記録されたヒストグラムの比較が容易になるようにプロットされます。一度だけのヒストグラムをログに記録する詳細については、このパネルの"Histograms in Summary"タブを参照してください。
wandb.log({"gradients": wandb.Histogram(grads)})
もし、より多くのコントロールが必要な場合、np.histogram
を呼び出し、返されたタプルをnp_histogram
キーワード引数に渡してください。
np_hist_grads = np.histogram(grads, density=True, range=(0., 1.))
wandb.log({"gradients": wandb.Histogram(np_hist_grads)})
wandb.run.summary.update( # サマリーのみの場合、概要タブでのみ表示される
{"final_logits": wandb.Histogram(logits)})
ヒストグラムがサマリーに含まれている場合、Runページ の概要タブに表示されます。ヒストリに含まれている場合は、チャートタブに時間をかけたビンのヒートマップが表示されます。
3D可視化
- 3Dオブジェクト
- ポイントクラウド
- 分子
ログファイルは、'obj'
, 'gltf'
, 'glb'
, 'babylon'
, 'stl'
, 'pts.json'
の形式で、ランが終了したときにUIでレンダリングされます。
wandb.log({"generated_samples":
[wandb.Object3D(open("sample.obj")),
wandb.Object3D(open("sample.gltf")),
wandb.Object3D(open("sample.glb"))]})
3DポイントクラウドやLidarシーンにバウンディングボックスを付けてログを取ります。レンダリングするポイントの座標と色を含むNumPy配列を渡します。UIでは、30万ポイントに切り捨てます。
point_cloud = np.array([[0, 0, 0, COLOR...], ...])
wandb.log({"point_cloud": wandb.Object3D(point_cloud)})
柔軟なカラースキームに対応するために、3つの異なる形状のNumPy配列がサポートされています。
[[x, y, z], ...]
nx3
[[x, y, z, c], ...]
nx4
| cはカテゴリ
の範囲は[1, 14]
(セグメンテーションに便利)[[x, y, z, r, g, b], ...]
nx6 | r,g,b
は赤、緑、青のカラーチャンネルの範囲[0,255]
の値です。
以下はログ記録コードの例です:
points
は、上記のシンプルなポイントクラウドレンダラと同じフォーマットのNumPy配列です。boxes
は、3つの属性を持つPython辞書のNumPy配列です:corners
- 8つの角のリストlabel
- ボックス上にレンダリングされるラベルを表す文字列 (オプション)color
- ボックスの色を表すrgb値
type
は、レンダリングするシーンタイプを表す文字列です。現在サポートされている唯一の値はlidar/beta
です
# W&Bにポイントとボックスをログ
point_scene = wandb.Object3D({
"type": "lidar/beta",
"points": np.array( # ポイントクラウドのようにポイントを追加
[
[0.4, 1, 1.3],
[1, 1, 1],
[1.2, 1, 1.2]
]
),
"boxes": np.array( # 3Dボックスを描画
[
{
"corners": [
[0,0,0],
[0,1,0],
[0,0,1],
[1,0,0],
[1,1,0],
[0,1,1],
[1,0,1],
[1,1,1]
],
"label": "Box",
"color": [123, 321, 111],
},
{
"corners": [
[0,0,0],
[0,2,0],
[0,0,2],
[2,0,0],
[2,2,0],
[0,2,2],
[2,0,2],
[2,2,2]
],
"label": "Box-2",
"color": [111, 321, 0],
}
]
),
"vectors": np.array( # 3Dベクターを追加
[
{"start": [0, 0, 0], "end": [0.1, 0.2, 0.5]}
]
)
})
wandb.log({"point_scene": point_scene})
wandb.log({"protein": wandb.Molecule("6lu7.pdb")}
10種類のファイルタイプの分子データをログすることができます:pdb
, pqr
, mmcif
, mcif
, cif
, sdf
, sd
, gro
, mol2
, mmtf
.
Weights & Biasesは、SMILES文字列、rdkit
mol
ファイル、およびrdkit.Chem.rdchem.Mol
オブジェクトからの分子データのログもサポートしています。
resveratrol = rdkit.Chem.MolFromSmiles("Oc1ccc(cc1)C=Cc1cc(O)cc(c1)O")
wandb.log(
{
"resveratrol": wandb.Molecule.from_rdkit(resveratrol),
"green fluorescent protein": wandb.Molecule.from_rdkit("2b3p.mol"),
"acetaminophen": wandb.Molecule.from_smiles("CC(=O)Nc1ccc(O)cc1"),
}
)
runが終了すると、UIで分子の3D可視化と対話することができます。
その他のメディア
Weights & Biasesは、さまざまなメディアタイプのログもサポートしています。
- オーディオ
- ビデオ
- テキスト
- HTML
wandb.log({
"クジラの歌": wandb.Audio(
np_array,
caption="OooOoo",
sample_rate=32)})
ステップごとにログできるオーディオクリップの最大数は100です。
wandb.log(
{"video": wandb.Video(numpy_array_or_path_to_video, fps=4, format="gif")})
もしnumpy配列が与えられた場合、次の順番で次元が与えられると仮定します:時間、チャンネル、幅、高さ。デフォルトでは、4 fpsのgif画像を作成します(numpyオブジェクトを渡す場合、ffmpeg
と moviepy
Pythonライブラリが必要です)。対応しているフォーマットは、"gif"
、"mp4"
、"webm"
、"ogg"
です。wandb.Video
に文字列を渡すと、ファイルが存在し、対応するフォーマットであることを確認してからwandbにアップロードされます。BytesIO
オブジェクトを渡すと、指定されたフォーマットを拡張子として一時ファイルが作成されます。
UIに表示されるテーブル内のテキストをログに記録するには、wandb.Table
を使用します。デフォルトでは、列のヘッダーは ["Input", "Output", "Expected"]
です。最適なUIパフォーマンスを確保するために、デフォルトの最大行数は10,000に設定されています。ただし、ユーザーは wandb.Table.MAX_ROWS = {DESIRED_MAX}
を明示的に上書きして最大値を変更することができます。
columns = ["Text", "Predicted Sentiment", "True Sentiment"]
# 方法 1
data = [["I love my phone", "1", "1"], ["My phone sucks", "0", "-1"]]
table = wandb.Table(data=data, columns=columns)
wandb.log({"examples": table})
# 方法 2
table = wandb.Table(columns=columns)
table.add_data("I love my phone", "1", "1")
table.add_data("My phone sucks", "0", "-1")
wandb.log({"examples": table})
また、pandas の DataFrame
オブジェクトを渡すこともできます。
table = wandb.Table(dataframe=my_dataframe)
wandb.log({"custom_file": wandb.Html(open("some.html"))})
wandb.log({"custom_string": wandb.Html('<a href="https://mysite">Link</a>')})
カスタムHTMLは任意のキーに記録することができ、これによってrunページにHTMLパネルが表示されます。デフォルトではデフォルトのスタイルが挿入されますが、inject=False
を渡すことでデフォルトのスタイルを無効にすることができます。
wandb.log({"custom_file": wandb.Html(open("some.html"), inject=False)})
よくある質問
エポックやステップをまたいで画像やメディアを比較する方法は?
ステップから画像をログするたびに、それらをUIで表示するために保存します。画像パネルを展開し、ステップスライダーを使用して、異なるステップの画像を表示します。これにより、トレーニング中にモデルの出力がどのように変化するかを簡単に比較することができます。
プロジェクトにW&Bを統合したいが、画像やメディアをアップロードしたくない場合は?
W&Bは、スカラーのみをログするプロジェクトでも使用できます。明示的にアップロードするファイルやデータを指定します。画像をログしないPyTorchの簡単な例がこちらになります。
PNGを記録する方法は?
wandb.Image
は、デフォルトでnumpy
配列やPILImage
のインスタンスをPNGに変換します。
wandb.log({"example": wandb.Image(...)})
# 複数の画像を表示
wandb.log({"example": [wandb.Image(...) for img in images]})
動画をログにする方法は?
動画は、wandb.Video
データ型を使ってログに記録されます:
wandb.log({"example": wandb.Video("myvideo.mp4")})
これでメディアブラウザで動画を表示できます。プロジェクトのワークスペース、runのワークスペース、またはレポートに移動し、「可視化を追加」をクリックしてリッチメディアパネルを追加してください。
点群をナビゲートしてズームする方法は?
コントロールキーを押しながらマウスを使って空間内を移動できます。
分子の2Dビューをログにする方法は?
wandb.Image
データ型とrdkit
を使用して、分子の2Dビューをログに記録できます:
molecule = rdkit.Chem.MolFromSmiles("CC(=O)O")
rdkit.Chem.AllChem.Compute2DCoords(molecule)
rdkit.Chem.AllChem.GenerateDepictionMatching2DStructure(molecule, molecule)
pil_image = rdkit.Chem.Draw.MolToImage(molecule, size=(300, 300))
wandb.log({"acetic_acid": wandb.Image(pil_image)})