---
title: Metric Tracker
description: >-
  A wrapper class that can help keeping track of a metric or metric collection
  over time.
canonical: 'https://lightning.ai/docs/torchmetrics/stable/wrappers/metric_tracker'
---
# Metric Tracker {#metric-tracker}

## Module Interface {#module-interface}

### `class torchmetrics.wrappers.MetricTracker(metric, maximize=None)` {#torchmetrics.wrappers.MetricTracker}

[\[source\]](https://github.com/Lightning-AI/torchmetrics/blob/v1.9.0/src/torchmetrics/wrappers/tracker.py#L33-L364)

A wrapper class that can help keeping track of a metric or metric collection over time.

The wrapper implements the standard `.update()`, `.compute()`, `.reset()` methods that just calls corresponding method of the currently tracked metric. However, the following additional methods are provided:

> \-`MetricTracker.n_steps`: number of metrics being tracked -`MetricTracker.increment()`: initialize a new metric for being tracked -`MetricTracker.compute_all()`: get the metric value for all steps -`MetricTracker.best_metric()`: returns the best value

Out of the box, this wrapper class fully supports that the base metric being tracked is a single Metric, a MetricCollection or another MetricWrapper wrapped around a metric. However, multiple layers of nesting, such as using a Metric inside a MetricWrapper inside a MetricCollection is not fully supported, especially the .best\_metric method that cannot auto compute the best metric and index for such nested structures.

Parameters:

*   **metric** (`Union`\[[`Metric`](/docs/torchmetrics/1.9.0/api-reference/metric.md#torchmetrics.Metric "torchmetrics.metric.Metric"), [`MetricCollection`](/docs/torchmetrics/1.9.0/user-guide/overview.md#torchmetrics.MetricCollection "torchmetrics.collections.MetricCollection")\]) – instance of a `torchmetrics.Metric` or `torchmetrics.MetricCollection` to keep track of at each timestep.
    
*   **maximize** (`Union`\[[`bool`](https://docs.python.org/3/builtins/functions.html#bool "(in Python v3.15)"), [`list`](https://docs.python.org/3/builtins/stdtypes.html#list "(in Python v3.15)")\[[`bool`](https://docs.python.org/3/builtins/functions.html#bool "(in Python v3.15)")\], [`None`](https://docs.python.org/3/builtins/constants.html#None "(in Python v3.15)")\]) – either single bool or list of bool indicating if higher metric values are better (`True`) or lower is better (`False`).
    

Example (single metric):

```python
>>> from torch import randint
>>> from torchmetrics.wrappers import MetricTracker
>>> from torchmetrics.classification import MulticlassAccuracy
>>> tracker = MetricTracker(MulticlassAccuracy(num_classes=10, average='micro'))
>>> for epoch in range(5):
...     tracker.increment()
...     for batch_idx in range(5):
...         tracker.update(randint(10, (100,)), randint(10, (100,)))
...     print(f"current acc={tracker.compute()}")
current acc=0.1120000034570694
current acc=0.08799999952316284
current acc=0.12600000202655792
current acc=0.07999999821186066
current acc=0.10199999809265137
>>> best_acc, which_epoch = tracker.best_metric(return_step=True)
>>> best_acc  
0.1260...
>>> which_epoch
2
>>> tracker.compute_all()
tensor([0.1120, 0.0880, 0.1260, 0.0800, 0.1020])
```

Example (multiple metrics using MetricCollection):

```python
>>> from torch import randn
>>> from torchmetrics.wrappers import MetricTracker
>>> from torchmetrics import MetricCollection
>>> from torchmetrics.regression import MeanSquaredError, ExplainedVariance
>>> tracker = MetricTracker(MetricCollection([MeanSquaredError(), ExplainedVariance()]), maximize=[False, True])
>>> for epoch in range(5):
...     tracker.increment()
...     for batch_idx in range(5):
...         tracker.update(randn(100), randn(100))
...     print(f"current stats={tracker.compute()}")  
current stats={'MeanSquaredError': tensor(2.3292), 'ExplainedVariance': tensor(-0.9516)}
current stats={'MeanSquaredError': tensor(2.1370), 'ExplainedVariance': tensor(-1.0775)}
current stats={'MeanSquaredError': tensor(2.1695), 'ExplainedVariance': tensor(-0.9945)}
current stats={'MeanSquaredError': tensor(2.1072), 'ExplainedVariance': tensor(-1.1878)}
current stats={'MeanSquaredError': tensor(2.0562), 'ExplainedVariance': tensor(-1.0754)}
>>> from pprint import pprint
>>> best_res, which_epoch = tracker.best_metric(return_step=True)
>>> pprint(best_res)  
{'ExplainedVariance': -0.951...,
 'MeanSquaredError': 2.056...}
>>> which_epoch
{'MeanSquaredError': 4, 'ExplainedVariance': 0}
>>> pprint(tracker.compute_all())
{'ExplainedVariance': tensor([-0.9516, -1.0775, -0.9945, -1.1878, -1.0754]),
 'MeanSquaredError': tensor([2.3292, 2.1370, 2.1695, 2.1072, 2.0562])}
```

#### `best_metric(return_step=False)` {#torchmetrics.wrappers.MetricTracker.best_metric}

[\[source\]](https://github.com/Lightning-AI/torchmetrics/blob/v1.9.0/src/torchmetrics/wrappers/tracker.py#L238-L319)

Return the highest metric out of all tracked.

Parameters:

**return\_step** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool "(in Python v3.15)")) – If `True` will also return the step with the highest metric value.

Return type:

`Union`\[[`None`](https://docs.python.org/3/builtins/constants.html#None "(in Python v3.15)"), [`float`](https://docs.python.org/3/builtins/functions.html#float "(in Python v3.15)"), [`Tensor`](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor "(in PyTorch v2.15)"), [`tuple`](https://docs.python.org/3/builtins/stdtypes.html#tuple "(in Python v3.15)")\[`Union`\[[`int`](https://docs.python.org/3/builtins/functions.html#int "(in Python v3.15)"), [`float`](https://docs.python.org/3/builtins/functions.html#float "(in Python v3.15)"), [`Tensor`](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor "(in PyTorch v2.15)")\], `Union`\[[`int`](https://docs.python.org/3/builtins/functions.html#int "(in Python v3.15)"), [`float`](https://docs.python.org/3/builtins/functions.html#float "(in Python v3.15)"), [`Tensor`](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor "(in PyTorch v2.15)")\]\], [`tuple`](https://docs.python.org/3/builtins/stdtypes.html#tuple "(in Python v3.15)")\[[`None`](https://docs.python.org/3/builtins/constants.html#None "(in Python v3.15)"), [`None`](https://docs.python.org/3/builtins/constants.html#None "(in Python v3.15)")\], [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict "(in Python v3.15)")\[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str "(in Python v3.15)"), [`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional "(in Python v3.15)")\[[`float`](https://docs.python.org/3/builtins/functions.html#float "(in Python v3.15)")\]\], [`tuple`](https://docs.python.org/3/builtins/stdtypes.html#tuple "(in Python v3.15)")\[[`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict "(in Python v3.15)")\[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str "(in Python v3.15)"), [`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional "(in Python v3.15)")\[[`float`](https://docs.python.org/3/builtins/functions.html#float "(in Python v3.15)")\]\], [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict "(in Python v3.15)")\[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str "(in Python v3.15)"), [`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional "(in Python v3.15)")\[[`int`](https://docs.python.org/3/builtins/functions.html#int "(in Python v3.15)")\]\]\]\]

Returns:

Either a single value or a tuple, depends on the value of `return_step` and the object being tracked.

*   If a single metric is being tracked and `return_step=False` then a single tensor will be returned
    
*   If a single metric is being tracked and `return_step=True` then a 2-element tuple will be returned, where the first value is optimal value and second value is the corresponding optimal step
    
*   If a metric collection is being tracked and `return_step=False` then a single dict will be returned, where keys correspond to the different values of the collection and the values are the optimal metric value
    
*   If a metric collection is being bracked and `return_step=True` then a 2-element tuple will be returned where each is a dict, with keys corresponding to the different values of th collection and the values of the first dict being the optimal values and the values of the second dict being the optimal step
    

In addition the value in all cases may be `None` if the underlying metric does have a proper defined way of being optimal or in the case where a nested structure of metrics are being tracked.

#### `compute_all()` {#torchmetrics.wrappers.MetricTracker.compute_all}

[\[source\]](https://github.com/Lightning-AI/torchmetrics/blob/v1.9.0/src/torchmetrics/wrappers/tracker.py#L188-L223)

Compute the metric value for all tracked metrics.

Return type:

[`Any`](https://docs.python.org/3/library/typing.html#typing.Any "(in Python v3.15)")

Returns:

By default will try stacking the results from all increments into a single tensor if the tracked base object is a single metric. If a metric collection is provided a dict of stacked tensors will be returned. If the stacking process fails a list of the computed results will be returned.

Raises:

[**ValueError**](https://docs.python.org/3/builtins/exceptions.html#ValueError "(in Python v3.15)") – If self.increment have not been called before this method is called.

#### `forward(*args, **kwargs)` {#torchmetrics.wrappers.MetricTracker.forward}

[\[source\]](https://github.com/Lightning-AI/torchmetrics/blob/v1.9.0/src/torchmetrics/wrappers/tracker.py#L167-L172)

Call forward of the current metric being tracked.

Return type:

[`None`](https://docs.python.org/3/builtins/constants.html#None "(in Python v3.15)")

#### `increment()` {#torchmetrics.wrappers.MetricTracker.increment}

[\[source\]](https://github.com/Lightning-AI/torchmetrics/blob/v1.9.0/src/torchmetrics/wrappers/tracker.py#L162-L165)

Create a new instance of the input metric that will be updated next.

Return type:

[`None`](https://docs.python.org/3/builtins/constants.html#None "(in Python v3.15)")

#### `plot(val=None, ax=None)` {#torchmetrics.wrappers.MetricTracker.plot}

[\[source\]](https://github.com/Lightning-AI/torchmetrics/blob/v1.9.0/src/torchmetrics/wrappers/tracker.py#L326-L364)

Plot a single or multiple values from the metric.

Parameters:

*   **val** (`Union`\[[`Tensor`](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor "(in PyTorch v2.15)"), [`Sequence`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Sequence "(in Python v3.15)")\[[`Tensor`](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor "(in PyTorch v2.15)")\], [`None`](https://docs.python.org/3/builtins/constants.html#None "(in Python v3.15)")\]) – Either a single result from calling metric.forward or metric.compute or a list of these results. If no value is provided, will automatically call metric.compute and plot that result.
    
*   **ax** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional "(in Python v3.15)")\[[`Axes`](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.html#matplotlib.axes.Axes "(in Matplotlib v3.11.2)")\]) – An matplotlib axis object. If provided will add plot to that axis
    

Return type:

[`tuple`](https://docs.python.org/3/builtins/stdtypes.html#tuple "(in Python v3.15)")\[[`Figure`](https://matplotlib.org/stable/api/_as_gen/matplotlib.figure.Figure.html#matplotlib.figure.Figure "(in Matplotlib v3.11.2)"), `Union`\[[`Axes`](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.html#matplotlib.axes.Axes "(in Matplotlib v3.11.2)"), [`ndarray`](https://numpy.org/doc/stable/reference/generated/numpy.ndarray.html#numpy.ndarray "(in NumPy v2.5)")\]\]

Returns:

Figure and Axes object

Raises:

[**ModuleNotFoundError**](https://docs.python.org/3/builtins/exceptions.html#ModuleNotFoundError "(in Python v3.15)") – If matplotlib is not installed

```python
>>> # Example plotting a single value
>>> import torch
>>> from torchmetrics.wrappers import MetricTracker
>>> from torchmetrics.classification import BinaryAccuracy
>>> tracker = MetricTracker(BinaryAccuracy(), maximize=True)
>>> for epoch in range(5):
...     tracker.increment()
...     for batch_idx in range(5):
...         tracker.update(torch.randint(2, (10,)), torch.randint(2, (10,)))
>>> fig_, ax_ = tracker.plot()  # plot all epochs
```

[![../../\_images/metric\_tracker-1.png](/docs/torchmetrics/1.9.0/static/_images/metric_tracker-1.png)](/docs/torchmetrics/1.9.0/static/_images/metric_tracker-1.png)

#### `reset()` {#torchmetrics.wrappers.MetricTracker.reset}

[\[source\]](https://github.com/Lightning-AI/torchmetrics/blob/v1.9.0/src/torchmetrics/wrappers/tracker.py#L225-L229)

Reset the current metric being tracked.

Return type:

[`None`](https://docs.python.org/3/builtins/constants.html#None "(in Python v3.15)")

#### `reset_all()` {#torchmetrics.wrappers.MetricTracker.reset_all}

[\[source\]](https://github.com/Lightning-AI/torchmetrics/blob/v1.9.0/src/torchmetrics/wrappers/tracker.py#L231-L236)

Reset all metrics being tracked.

Return type:

[`None`](https://docs.python.org/3/builtins/constants.html#None "(in Python v3.15)")

#### `property n_steps: int` {#torchmetrics.wrappers.MetricTracker.n_steps}

[\[source\]](https://github.com/Lightning-AI/torchmetrics/blob/torchmetrics/wrappers.py)

Returns the number of times the tracker has been incremented.

---

**Navigation**

- Parent: [Wrappers](/docs/torchmetrics/1.9.0/wrappers.md)
