Source code for bayesflow.diagnostics.metrics.accuracy
from typing import Any
from collections.abc import Sequence
import numpy as np
from ...utils.classification import confusion_matrix
[docs]
def accuracy(
predictions: np.ndarray,
true_models: np.ndarray,
model_names: Sequence[str] | None = None,
per_model: bool = True,
) -> dict[str, Any]:
"""
Compute classification accuracy for model comparison networks.
Parameters
----------
predictions : np.ndarray of shape (N, M)
Predicted (log) probabilities. The argmax is used as the predicted label.
true_models : np.ndarray of shape (N, M)
One-hot encoded true model indices.
model_names : Sequence[str], optional (default = None)
Optional model names to show in the output. Only used when ``per_model``
is True. By default, models are called "M_" + model index.
per_model : bool, optional (default = True)
If True, returns the per-model accuracy, i.e., the diagonal entries of
the confusion matrix normalized over the true (row) labels. This is
equivalent to the recall / true-positive-rate of each model. If False,
returns the overall (aggregate) accuracy as a single float.
Returns
-------
dict[str, any] or float
If ``per_model`` is True, a dictionary containing:
- "values" : np.ndarray
The per-model accuracy (diagonal of the row-normalized confusion
matrix).
- "metric_name" : str
The name of the metric ("Accuracy").
- "model_names" : list[str]
The (inferred) model names.
If ``per_model`` is False, the fraction of datasets for which the
predicted model matches the true model (a single float).
Examples
--------
>>> import numpy as np
>>> from bayesflow.diagnostics.metrics import accuracy
>>> probs = np.array([[0.8, 0.1, 0.1], [0.1, 0.9, 0.0]])
>>> one_hot = np.array([[1, 0, 0], [0, 1, 0]])
>>> accuracy(probs, one_hot, per_model=False)
1.0
"""
num_models = true_models.shape[-1]
true_labels = true_models.argmax(axis=-1)
predicted_labels = predictions.argmax(axis=-1)
if not per_model:
return np.mean(predicted_labels == true_labels)
if model_names is None:
model_names = ["M_" + str(i) for i in range(1, num_models + 1)]
cm = confusion_matrix(true_labels, predicted_labels, labels=np.arange(num_models), normalize="true")
values = np.diag(cm)
return dict(values=values, metric_name="Accuracy", model_names=list(model_names))