> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wandb.ai/llms.txt
> Use this file to discover all available pages before exploring further.

> Create and track plots from machine learning experiments.

# Create and track plots from 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](/models/app/features/custom-charts/walkthrough/).

### Basic charts

To create a W\&B chart:

1. Create a `wandb.Table` object and add the data you want to visualize.
2. Generate a plot using one of the W\&B's built-in [helper functions](/models/ref/python/custom-charts)
3. Log the plot with `wandb.Run.log()`.

The following basic charts can be used to construct basic visualizations of metrics and results.

<Tabs>
  <Tab title="Line">
    Log a custom line plot, a list of connected and ordered points on arbitrary axes.

    ```python theme={null}
    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"
                )
            }
        )
    ```

    You can use this to log curves on any two dimensions. If you're plotting 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.

    <Frame>
      <img src="https://mintcdn.com/wb-21fd5541/_OEDykSS2PIumrEw/images/track/line_plot.png?fit=max&auto=format&n=_OEDykSS2PIumrEw&q=85&s=9808ee611e7d6cea084d05903e83f5a6" alt="Custom line plot" width="1930" height="1228" data-path="images/track/line_plot.png" />
    </Frame>

    For more information, see the [Creating Custom Line Plots With W\&B](https://wandb.ai/wandb/plots/reports/Custom-Line-Plots--VmlldzoyNjk5NTA) report.

    [Run the code](https://tiny.cc/custom-charts)
  </Tab>

  <Tab title="Scatter">
    Log a custom scatter plot, a list of points (x, y) on a pair of arbitrary axes x and y.

    ```python theme={null}
    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")})
    ```

    You can use this to log scatter points on any two dimensions. If you're plotting 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.

    <Frame>
      <img src="https://mintcdn.com/wb-21fd5541/_OEDykSS2PIumrEw/images/track/demo_scatter_plot.png?fit=max&auto=format&n=_OEDykSS2PIumrEw&q=85&s=536a7c7c0796e3de6a56b17535566156" alt="Custom scatter plot" width="2194" height="940" data-path="images/track/demo_scatter_plot.png" />
    </Frame>

    For more information, see the [Creating Custom Scatter Plots With W\&B](https://wandb.ai/wandb/plots/reports/Custom-Scatter-Plots--VmlldzoyNjk5NDQ) report.

    [Run the code](https://tiny.cc/custom-charts)
  </Tab>

  <Tab title="Bar">
    Log a custom bar chart (a list of labeled values as bars) natively in a few lines:

    ```python theme={null}
    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"
                )
            }
        )
    ```

    You can 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.

    <Frame>
      <img src="https://mintcdn.com/wb-21fd5541/6bJLb4DIApn2yeFO/images/track/basic_charts_bar.png?fit=max&auto=format&n=6bJLb4DIApn2yeFO&q=85&s=ce4fc3ee16167f8f8c9fd87dc0043c70" alt="Custom bar chart" width="1286" height="552" data-path="images/track/basic_charts_bar.png" />
    </Frame>

    For more information, see the [Custom Bar Charts](https://wandb.ai/wandb/plots/reports/Custom-Bar-Charts--VmlldzoyNzExNzk) report.

    [Run the code](https://tiny.cc/custom-charts)
  </Tab>

  <Tab title="Histogram">
    Log a custom histogram (sort a list of values into bins by count or frequency of occurrence) natively in a few lines. If you have a list of prediction confidence scores (`scores`), you can visualize the distribution like this:

    ```python theme={null}
    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")})
    ```

    You can use this to log arbitrary histograms. Note that `data` is a list of lists, intended to support a 2D array of rows and columns.

    <Frame>
      <img src="https://mintcdn.com/wb-21fd5541/_OEDykSS2PIumrEw/images/track/demo_custom_chart_histogram.png?fit=max&auto=format&n=_OEDykSS2PIumrEw&q=85&s=53afbd7a9439705cd7997e6a52c7cce0" alt="Custom histogram" width="1252" height="558" data-path="images/track/demo_custom_chart_histogram.png" />
    </Frame>

    For more information, see the [Creating Custom Histograms With W\&B](https://wandb.ai/wandb/plots/reports/Custom-Histograms--VmlldzoyNzE0NzM) report.

    [Run the code](https://tiny.cc/custom-charts)
  </Tab>

  <Tab title="Multi-line">
    Plot multiple lines, or multiple different lists of x-y coordinate pairs, on one shared set of x-y axes:

    ```python theme={null}
    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",
                )
            }
        )
    ```

    Note that 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.

    <Frame>
      <img src="https://mintcdn.com/wb-21fd5541/6bJLb4DIApn2yeFO/images/track/basic_charts_histogram.png?fit=max&auto=format&n=6bJLb4DIApn2yeFO&q=85&s=c554f1978caabbd7d05322ef59f399c8" alt="Multi-line plot" width="537" height="339" data-path="images/track/basic_charts_histogram.png" />
    </Frame>

    For more information, see the [Custom Multi-Line Plots](https://wandb.ai/wandb/plots/reports/Custom-Multi-Line-Plots--VmlldzozOTMwMjU) report.
  </Tab>
</Tabs>

### Model evaluation charts

These preset charts have built-in `wandb.plot()` methods that make it quick and easy to log charts directly from your script and see the exact information you're looking for in the UI.

<Tabs>
  <Tab title="Precision-recall curves">
    Create a [Precision-Recall curve](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.precision_recall_curve.html#sklearn.metrics.precision_recall_curve) in one line:

    ```python theme={null}
    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.

    <Frame>
      <img src="https://mintcdn.com/wb-21fd5541/_OEDykSS2PIumrEw/images/track/model_eval_charts_precision_recall.png?fit=max&auto=format&n=_OEDykSS2PIumrEw&q=85&s=c5accf7be884f7517b880425f127be82" alt="Precision-recall curve" width="657" height="431" data-path="images/track/model_eval_charts_precision_recall.png" />
    </Frame>

    For more information, see the [Plot Precision Recall Curves With W\&B](https://wandb.ai/wandb/plots/reports/Plot-Precision-Recall-Curves--VmlldzoyNjk1ODY) report.

    [Run the code](https://colab.research.google.com/drive/1mS8ogA3LcZWOXchfJoMrboW3opY1A8BY?usp=sharing)
  </Tab>

  <Tab title="ROC curves">
    Create an [ROC curve](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.roc_curve.html#sklearn.metrics.roc_curve) in one line:

    ```python theme={null}
    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.

    <Frame>
      <img src="https://mintcdn.com/wb-21fd5541/_OEDykSS2PIumrEw/images/track/demo_custom_chart_roc_curve.png?fit=max&auto=format&n=_OEDykSS2PIumrEw&q=85&s=1e23e67b4238b990c7b68a3fe5fcd245" alt="ROC curve" width="1338" height="788" data-path="images/track/demo_custom_chart_roc_curve.png" />
    </Frame>

    For more information, see the [Plot ROC Curves With W\&B](https://wandb.ai/wandb/plots/reports/Plot-ROC-Curves--VmlldzoyNjk3MDE) report.

    [Run the code](https://colab.research.google.com/github/wandb/examples/blob/master/colabs/wandb-log/Plot_ROC_Curves_with_W%26B.ipynb)
  </Tab>

  <Tab title="Confusion matrix">
    Create a multi-class [confusion matrix](https://scikit-learn.org/stable/auto_examples/model_selection/plot_confusion_matrix.html) in one line:

    ```python theme={null}
    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`.

    <Frame>
      <img src="https://mintcdn.com/wb-21fd5541/88iR80mZ8tuFCZUU/images/experiments/confusion_matrix.png?fit=max&auto=format&n=88iR80mZ8tuFCZUU&q=85&s=eb980135fce1c4b0960f03cef572420a" alt="Confusion matrix" width="1070" height="422" data-path="images/experiments/confusion_matrix.png" />
    </Frame>

    For more information, see the [Confusion Matrix: Usage and Examples](https://wandb.ai/wandb/plots/reports/Confusion-Matrix--VmlldzozMDg1NTM) report.

    [Run the code](https://colab.research.google.com/github/wandb/examples/blob/master/colabs/wandb-log/Log_a_Confusion_Matrix_with_W%26B.ipynb)
  </Tab>
</Tabs>

### Interactive custom charts

For full customization, tweak a built-in [Custom Chart preset](/models/app/features/custom-charts/walkthrough/) or create a new preset, then save the chart. Use the chart ID to log data to that custom preset directly from your script.

```python theme={null}
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](https://tiny.cc/custom-charts)

### Matplotlib and Plotly plots

Instead of using W\&B [Custom Charts](/models/app/features/custom-charts/walkthrough/) with `wandb.plot()`, you can log charts generated with [matplotlib](https://matplotlib.org/) and [Plotly](https://plotly.com/).

```python theme={null}
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})
```

Just pass a `matplotlib` plot or figure object to `wandb.Run.log()`. By default we'll convert the plot into a [Plotly](https://plot.ly/) plot. If you'd rather log the plot as an image, you can pass the plot into `wandb.Image`. We also accept Plotly charts directly.

<Note>
  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()`.
</Note>

### Log custom HTML to W\&B Tables

W\&B supports logging interactive charts from Plotly and Bokeh as HTML and adding them to Tables.

#### Log Plotly figures to Tables as HTML

You can log interactive Plotly charts to W\&B Tables by converting them to HTML.

```python theme={null}
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})
```

#### Log Bokeh figures to Tables as HTML

You can log interactive Bokeh charts to W\&B Tables by converting them to HTML.

```python theme={null}
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})
```
