This page shows you how to create and log plots from your machine learning experiments so that you can visualize metrics, evaluate models, and share interactive charts in W&B. This page is for you if you already log runs with the W&B Python SDK (wandb) and want to add custom or built-in visualizations to your experiments.
In W&B Models, methods in wandb.plot let you track charts with wandb.Run.log(), including charts that change over time during training. To learn more about the custom charting framework, see the custom charts walkthrough.
Basic charts
This section covers the general workflow for creating a W&B chart and provides examples of common chart types (line, scatter, bar, histogram, and multi-line plots) that you can use to visualize metrics and results.
To create a W&B chart:
- Create a
wandb.Table object and add the data you want to visualize.
- Generate a plot using one of W&B’s built-in helper functions.
- Log the plot with
wandb.Run.log().
Use the following basic charts to construct basic visualizations of metrics and results.
Line
Scatter
Bar
Histogram
Multi-line
Log a custom line plot, a list of connected and ordered points on arbitrary axes.import wandb
with wandb.init() as run:
data = [[x, y] for (x, y) in zip(x_values, y_values)]
table = wandb.Table(data=data, columns=["x", "y"])
run.log(
{
"my_custom_plot_id": wandb.plot.line(
table, "x", "y", title="Custom Y versus X line plot"
)
}
)
Use this to log curves on any two dimensions. If you plot two lists of values against each other, the number of values in the lists must match exactly. For example, each point must have an x and a y.For more information, see the Creating Custom Line Plots With W&B report.Run the code Log a custom scatter plot, a list of points (x, y) on a pair of arbitrary axes x and y.import wandb
with wandb.init() as run:
data = [[x, y] for (x, y) in zip(class_x_scores, class_y_scores)]
table = wandb.Table(data=data, columns=["class_x", "class_y"])
run.log({"my_custom_id": wandb.plot.scatter(table, "class_x", "class_y")})
Use this to log scatter points on any two dimensions. If you plot two lists of values against each other, the number of values in the lists must match exactly. For example, each point must have an x and a y.For more information, see the Creating Custom Scatter Plots With W&B report.Run the code Log a custom bar chart (a list of labeled values as bars) in a few lines:import wandb
with wandb.init() as run:
data = [[label, val] for (label, val) in zip(labels, values)]
table = wandb.Table(data=data, columns=["label", "value"])
run.log(
{
"my_bar_chart_id": wandb.plot.bar(
table, "label", "value", title="Custom bar chart"
)
}
)
Use this to log arbitrary bar charts. The number of labels and values in the lists must match exactly. Each data point must have both.For more information, see the Custom Bar Charts report.Run the code Log a custom histogram (sort a list of values into bins by count or frequency of occurrence) in a few lines. If you have a list of prediction confidence scores (scores), you can visualize the distribution like this:import wandb
with wandb.init() as run:
data = [[s] for s in scores]
table = wandb.Table(data=data, columns=["scores"])
run.log({"my_histogram": wandb.plot.histogram(table, "scores", title="Histogram")})
Use this to log arbitrary histograms. data is a list of lists, which supports a 2D array of rows and columns.For more information, see the Creating Custom Histograms With W&B report.Run the code Plot multiple lines, or multiple different lists of x-y coordinate pairs, on one shared set of x-y axes:import wandb
with wandb.init() as run:
run.log(
{
"my_custom_id": wandb.plot.line_series(
xs=[0, 1, 2, 3, 4],
ys=[[10, 20, 30, 40, 50], [0.5, 11, 72, 3, 41]],
keys=["metric Y", "metric Z"],
title="Two Random Metrics",
xname="x units",
)
}
)
The number of x and y points must match exactly. You can supply one list of x values to match multiple lists of y values, or a separate list of x values for each list of y values.For more information, see the Custom Multi-Line Plots report.
Model evaluation charts
This section describes preset charts you can use to evaluate model performance, including precision-recall curves, ROC curves, and confusion matrices.
These preset charts have built-in wandb.plot() methods that let you log charts directly from your script and see the information you want in the UI.
Precision-recall curves
ROC curves
Confusion matrix
Create a Precision-Recall curve in one line:import wandb
with wandb.init() as run:
# ground_truth is a list of true labels, predictions is a list of predicted scores.
# For example ground_truth = [0, 1, 1, 0], predictions = [0.1, 0.4, 0.35, 0.8]
ground_truth = [0, 1, 1, 0]
predictions = [0.1, 0.4, 0.35, 0.8]
run.log({"pr": wandb.plot.pr_curve(ground_truth, predictions)})
You can log this whenever your code has access to:
- A model’s predicted scores (
predictions) on a set of examples.
- The corresponding ground truth labels (
ground_truth) for those examples.
- (Optional) A list of the labels or class names. For example,
labels=["cat", "dog", "bird"], if label index 0 means cat, 1 means dog, 2 means bird.
- (Optional) A subset (still in list format) of the labels to visualize in the plot.
For more information, see the Plot Precision Recall Curves With W&B report.Run the code Create an ROC curve in one line:import wandb
with wandb.init() as run:
# ground_truth is a list of true labels, predictions is a list of predicted scores.
# For example ground_truth = [0, 1, 1, 0], predictions = [0.1, 0.4, 0.35, 0.8]
ground_truth = [0, 1, 1, 0]
predictions = [0.1, 0.4, 0.35, 0.8]
run.log({"roc": wandb.plot.roc_curve(ground_truth, predictions)})
You can log this whenever your code has access to:
- A model’s predicted scores (
predictions) on a set of examples.
- The corresponding ground truth labels (
ground_truth) for those examples.
- (Optional) A list of the labels or class names. For example,
labels=["cat", "dog", "bird"], if label index 0 means cat, 1 means dog, 2 means bird.
- (Optional) A subset (still in list format) of these labels to visualize on the plot.
For more information, see the Plot ROC Curves With W&B report.Run the code Create a multi-class confusion matrix in one line:import wandb
cm = wandb.plot.confusion_matrix(
y_true=ground_truth, preds=predictions, class_names=class_names
)
with wandb.init() as run:
run.log({"conf_mat": cm})
You can log this wherever your code has access to:
- A model’s predicted labels on a set of examples (
preds) or the normalized probability scores (probs). The probabilities must have the shape (number of examples, number of classes). You can supply either probabilities or predictions but not both.
- The corresponding ground truth labels for those examples (
y_true).
- A full list of the labels or class names as strings in
class_names. For example, class_names=["cat", "dog", "bird"], if index 0 is cat, 1 is dog, 2 is bird.
For more information, see the Confusion Matrix: Usage and Examples report.Run the code
Interactive custom charts
This section describes how to log data to a custom chart preset so that you can fully control how the chart is rendered in the W&B UI.
For full customization, tweak a built-in Custom Chart preset or create a new preset, then save the chart. Use the chart ID to log data to that custom preset directly from your script.
import wandb
# Create a table with the columns to plot.
table = wandb.Table(data=data, columns=["step", "height"])
# Map from the table's columns to the chart's fields.
fields = {"x": "step", "value": "height"}
# Use the table to populate the new custom chart preset.
# To use your own saved chart preset, change the vega_spec_name.
# To edit the title, change the string_fields.
my_custom_chart = wandb.plot_table(
vega_spec_name="carey/new_chart",
data_table=table,
fields=fields,
string_fields={"title": "Height Histogram"},
)
with wandb.init() as run:
# Log the custom chart.
run.log({"my_custom_chart": my_custom_chart})
Run the code
Matplotlib and Plotly plots
This section describes how to log charts that you have already generated with matplotlib or Plotly, instead of building charts with the W&B custom charts framework.
Instead of using W&B Custom Charts with wandb.plot(), you can log charts generated with matplotlib and Plotly.
import wandb
import matplotlib.pyplot as plt
with wandb.init() as run:
# Create a simple matplotlib plot.
plt.figure()
plt.plot([1, 2, 3, 4])
plt.ylabel("some interesting numbers")
# Log the plot to W&B.
run.log({"chart": plt})
Pass a matplotlib plot or figure object to wandb.Run.log(). By default, W&B converts the plot into a Plotly plot. To log the plot as an image instead, pass the plot into wandb.Image. W&B also accepts Plotly charts directly.
If you get an error like “You attempted to log an empty plot”, store the figure separately from the plot with fig = plt.figure() and then log fig in your call to wandb.Run.log().
Log custom HTML to W&B Tables
This section describes how to embed interactive charts inside a W&B Table by logging them as HTML. Use this approach when you want to keep chart interactivity alongside other tabular data.
W&B supports logging interactive charts from Plotly and Bokeh as HTML and adding them to Tables. The following sections describe how to log Plotly and Bokeh figures.
You can log interactive Plotly charts to W&B Tables by converting them to HTML.
import wandb
import plotly.express as px
# Initialize a new run.
with wandb.init(project="log-plotly-fig-tables", name="plotly_html") as run:
# Create a table.
table = wandb.Table(columns=["plotly_figure"])
# Create path for Plotly figure.
path_to_plotly_html = "./plotly_figure.html"
# Example Plotly figure.
fig = px.scatter(x=[0, 1, 2, 3, 4], y=[0, 1, 4, 9, 16])
# Write Plotly figure to HTML.
# Set auto_play to False prevents animated Plotly charts
# from playing in the table automatically.
fig.write_html(path_to_plotly_html, auto_play=False)
# Add Plotly figure as HTML file into Table.
table.add_data(wandb.Html(path_to_plotly_html))
# Log table.
run.log({"test_table": table})
You can log interactive Bokeh charts to W&B Tables by converting them to HTML.
from scipy.signal import spectrogram
import holoviews as hv
import panel as pn
from scipy.io import wavfile
import numpy as np
from bokeh.resources import INLINE
hv.extension("bokeh", logo=False)
import wandb
def save_audio_with_bokeh_plot_to_html(audio_path, html_file_name):
sr, wav_data = wavfile.read(audio_path)
duration = len(wav_data) / sr
f, t, sxx = spectrogram(wav_data, sr)
spec_gram = hv.Image((t, f, np.log10(sxx)), ["Time (s)", "Frequency (hz)"]).opts(
width=500, height=150, labelled=[]
)
audio = pn.pane.Audio(wav_data, sample_rate=sr, name="Audio", throttle=500)
slider = pn.widgets.FloatSlider(end=duration, visible=False)
line = hv.VLine(0).opts(color="white")
slider.jslink(audio, value="time", bidirectional=True)
slider.jslink(line, value="glyph.location")
combined = pn.Row(audio, spec_gram * line, slider).save(html_file_name)
html_file_name = "audio_with_plot.html"
audio_path = "hello.wav"
save_audio_with_bokeh_plot_to_html(audio_path, html_file_name)
wandb_html = wandb.Html(html_file_name)
with wandb.init(project="audio_test") as run:
my_table = wandb.Table(columns=["audio_with_plot"], data=[[wandb_html]])
run.log({"audio_table": my_table})