Documentation
Search…
Logging FAQs
Common questions about logging data with W&B

How can I organize my logged charts and media in the W&B UI?

We treat / as a separator for organizing logged panels in the W&B UI. By default, the component of the logged item's name before a / is used to define a group of panel called a "Panel Section".
1
wandb.log({'val/loss': 1.1, 'val/acc': 0.3}) # charts in val/ Panel Section
2
wandb.log({'train/loss': 0.1, 'train/acc': 0.94}) # charts in train/ Panel Section
Copied!
In the Workspace settings, you can change whether panels are grouped by just the first component or by all components separated by /.

How can I compare images or media across epochs or steps?

Each time you log images from a step, we save them to show in the UI. Expand the image panel, and use the step slider to look at images from different steps. This makes it easy to compare how a model's output changes during training.

What if I want to log some metrics on batches and some metrics only on epochs?

If you'd like to log certain metrics in every batch and standardize plots, you can log x axis values that you want to plot with your metrics. Then in the custom plots, click edit and select a custom x-axis.
1
wandb.log({'batch': batch_idx, 'loss': 0.3})
2
wandb.log({'epoch': epoch, 'val_acc': 0.94})
Copied!

How do I log a list of values?

Logging lists directly is not supported. Instead, list-like collections of numerical data are converted to histograms. To log all of the entries in a list, give a name to each entry in the list and use those names as keys in a dictionary, as below.
Using a dictionary
As a histogram
1
wandb.log({f"losses/loss-{ii}": loss for ii, loss in enumerate(losses)})
Copied!
1
wandb.log({"losses": wandb.Histogram(losses)}) # converts losses to a histogram
Copied!

How do I plot multiple lines on a plot with a legend?

Multi-line custom chart can be created by using wandb.plot.line_series(). You'll need to navigate to the project page to see the line chart. To add a legend to the plot, pass the keys argument within wandb.plot.line_series(). For example:
1
wandb.log({"my_plot" : wandb.plot.line_series(
2
xs = x_data,
3
ys = y_data,
4
keys = ["metric_A", "metric_B"])}]
Copied!
You can find more information about Multi-line plots here under the Multi-line tab.

How do I add Plotly/Bokeh Charts into Tables?

Adding Plotly/Bokeh figures to Tables directly is not yet supported. Instead, write the figure to HTML and then add the HTML to the Table. Examples with interactive Plotly and Bokeh charts below.
Using Plotly
Using Bokeh
1
import wandb
2
import plotly.express as px
3
4
# Initialize a new run
5
run = wandb.init(project="log-plotly-fig-tables", name="plotly_html")
6
7
# Create a table
8
table = wandb.Table(columns = ["plotly_figure"])
9
10
# Create path for Plotly figure
11
path_to_plotly_html = "./plotly_figure.html"
12
13
# Example Plotly figure
14
fig = px.scatter(x = [0, 1, 2, 3, 4], y = [0, 1, 4, 9, 16])
15
16
# Write Plotly figure to HTML
17
fig.write_html(path_to_plotly_html, auto_play = False) # Setting auto_play to False prevents animated Plotly charts from playing in the table automatically
18
19
# Add Plotly figure as HTML file into Table
20
table.add_data(wandb.Html(path_to_plotly_html))
21
22
# Log Table
23
run.log({"test_table": table})
24
wandb.finish()How do I use custom x-axes?
Copied!
1
from scipy.signal import spectrogram
2
import holoviews as hv
3
import panel as pn
4
from scipy.io import wavfile
5
import numpy as np
6
from bokeh.resources import INLINE
7
hv.extension("bokeh", logo=False)
8
import wandb
9
10
def save_audio_with_bokeh_plot_to_html(audio_path, html_file_name):
11
sr, wav_data = wavfile.read(audio_path)
12
duration = len(wav_data)/sr
13
f, t, sxx = spectrogram(wav_data, sr)
14
spec_gram = hv.Image((t, f, np.log10(sxx)), ["Time (s)", "Frequency (hz)"]).opts(width=500, height=150, labelled=[])
15
audio = pn.pane.Audio(wav_data, sample_rate=sr, name='Audio', throttle=500)
16
slider = pn.widgets.FloatSlider(end=duration, visible=False)
17
line = hv.VLine(0).opts(color='white')
18
slider.jslink(audio, value='time', bidirectional=True)
19
slider.jslink(line, value='glyph.location')
20
combined = pn.Row(audio, spec_gram * line, slider).save(html_file_name)
21
22
23
html_file_name = 'audio_with_plot.html'
24
audio_path = 'hello.wav'
25
save_audio_with_bokeh_plot_to_html(audio_path, html_file_name)
26
27
wandb_html = wandb.Html(html_file_name)
28
run = wandb.init(project='audio_test')
29
my_table = wandb.Table(columns=['audio_with_plot'], data=[[wandb_html], [wandb_html]])
30
run.log({"audio_table": my_table})
31
run.finish()
Copied!

Why is nothing showing up in my graphs?

If you're seeing "No visualization data logged yet" that means that we haven't gotten the first wandb.log call from your script yet. This could be because your run takes a long time to finish a step. If you're logging at the end of each epoch, you could log a few times per epoch to see data stream in more quickly.

Why is the same metric appearing more than once?

If you're logging different types of data under the same key, we have to split them out in our database. This means you'll see multiple entries of the same metric name in a dropdown in the UI. The types we group by are number, string, bool, other (mostly arrays), and any wandb data type (Histogram, Image, etc). Send only one type to each key to avoid this behavior.
We store metrics in a case-insensitive fashion, so make sure you don't have two metrics with the same name like "My-Metric" and "my-metric".

How can I access the data logged to my runs directly and programmatically?

The history object is used to track metrics logged by wandb.log. Using our API, you can access the history object via run.history().
1
api = wandb.Api()
2
run = api.run("username/project/run_id")
3
print(run.history())
Copied!

What happens when I log millions of steps to W&B? How is that rendered in the browser?

The more points you send us, the longer it will take to load your graphs in the UI. If you have more than 1000 points on a line, we sample down to 1000 points on the backend before we send your browser the data. This sampling is nondeterministic, so if you refresh the page you'll see a different set of sampled points.
If you'd like all the original data, you can use our data API to pull down unsampled data.
Guidelines
We recommend that you try to log less than 10,000 points per metric. If you log more than 1 million points in a line, it will take us while to load the page. For more on strategies for reducing logging footprint without sacrificing accuracy, check out this Colab. If you have more than 500 columns of config and summary metrics, we'll only show 500 in the table.

What if I want to integrate W&B into my project, but I don't want to upload any images or media?

W&B can be used even for projects that only log scalars — you specify any files or data you'd like to upload explicitly. Here's a quick example in PyTorch that does not log images.

What happens if I pass a class attribute into wandb.log()?

It is generally not recommended to pass class attributes into wandb.log() as the attribute may change before the network call is made. If you are storing metrics as the attribute of a class, it is recommended to deep copy the attribute to ensure the metric logged matches the value of the attribute at the time that wandb.log() was called.

Why am I seeing fewer data points than I logged?

If you are visualizing your metrics against something other than Step on your X-Axis, you might see fewer data points than you expect. This is because we require the metrics to be plotted against one another to be logged at the same Step - that is how we keep your metrics synchronized, i.e., we only sample metrics that are logged at the same Step while interpolating in between samples. Guidelines We recommend you bundle your metrics into the same log() call. If your code looks like this:
1
wandb.log({"Precision" : precision})
2
...
3
wandb.log({"Recall" : recall})
Copied!
It would be better to log it as:
1
wandb.log({
2
"Precision" : precision,
3
"Recall" : recall
4
})
Copied!
Alternatively, you can manually control the step parameter and synchronize your metrics in your own code:
1
wandb.log({"Precision" : precision}, step = step)
2
...
3
wandb.log({"Recall" : recall}, step = step)
Copied!
If the value of step is the same in both the calls to log(), your metrics will be logged under the same step and be sampled together. Please note that step must be monotonically increasing in each call, otherwise the step value is ignored during your call to log().