Skip to content

Metrics

Evaluation metrics for highFIS estimators.

This module provides a small, sklearn-style evaluation API for both regression and classification tasks.

Classification Metrics
  • accuracy: standard accuracy score
  • balanced_accuracy: average recall over classes
  • precision_macro: macro-averaged precision
  • recall_macro: macro-averaged recall
  • f1_macro: macro-averaged F1 score
  • precision_micro: micro-averaged precision
  • recall_micro: micro-averaged recall
  • f1_micro: micro-averaged F1 score
  • confusion_matrix: confusion matrix by class
  • classes: sorted union of true and predicted labels
Regression Metrics
  • mse: mean squared error
  • mae: mean absolute error
  • rmse: root mean squared error
  • r2: coefficient of determination
  • median_absolute_error: median absolute error
  • mean_bias_error: average prediction bias
  • max_error: maximum absolute error
  • std_error: standard deviation of residuals
  • explained_variance: explained variance score
  • mape: mean absolute percentage error
  • smape: symmetric mean absolute percentage error
  • msle: mean squared logarithmic error
  • pearson: Pearson correlation coefficient
Notes
  • The module exports compute_metrics and the helper classes ClassificationMetrics and RegressionMetrics.
  • compute_metrics validates metric names and returns only the requested subset.
  • All metrics accept raw array-like inputs and flatten non-1D arrays.

ClassificationMetrics

Standard classification metrics.

accuracy staticmethod

Return classification accuracy.

Source code in highfis/metrics.py
@staticmethod
def accuracy(y_true: Any, y_pred: Any, sample_weight: Any | None = None) -> float:
    """Return classification accuracy."""
    return float(accuracy_score(y_true, y_pred, sample_weight=sample_weight))

balanced_accuracy staticmethod

Return the balanced accuracy score.

Source code in highfis/metrics.py
@staticmethod
def balanced_accuracy(y_true: Any, y_pred: Any, sample_weight: Any | None = None) -> float:
    """Return the balanced accuracy score."""
    return float(balanced_accuracy_score(y_true, y_pred, sample_weight=sample_weight))

classes staticmethod

Return the sorted set of predicted and true classes.

Note

sample_weight is ignored.

Source code in highfis/metrics.py
@staticmethod
def classes(
    y_true: Any,
    y_pred: Any,
    sample_weight: Any | None = None,
) -> np.ndarray:
    """Return the sorted set of predicted and true classes.

    Note:
        ``sample_weight`` is ignored.
    """
    if sample_weight is not None:
        warnings.warn("sample_weight is ignored by classes", UserWarning, stacklevel=2)
    y_true_arr = _flatten_array(y_true)
    y_pred_arr = _flatten_array(y_pred)
    return np.unique(np.concatenate([y_true_arr, y_pred_arr]))

confusion_matrix staticmethod

Return the confusion matrix for the predictions.

Source code in highfis/metrics.py
@staticmethod
def confusion_matrix(
    y_true: Any,
    y_pred: Any,
    sample_weight: Any | None = None,
) -> np.ndarray:
    """Return the confusion matrix for the predictions."""
    y_true_arr = _flatten_array(y_true)
    y_pred_arr = _flatten_array(y_pred)
    return confusion_matrix(y_true_arr, y_pred_arr, sample_weight=sample_weight)

f1_macro staticmethod

Return macro-averaged F1 score.

Source code in highfis/metrics.py
@staticmethod
def f1_macro(y_true: Any, y_pred: Any, sample_weight: Any | None = None) -> float:
    """Return macro-averaged F1 score."""
    return float(f1_score(y_true, y_pred, average="macro", zero_division=0, sample_weight=sample_weight))

f1_micro staticmethod

Return micro-averaged F1 score.

Source code in highfis/metrics.py
@staticmethod
def f1_micro(y_true: Any, y_pred: Any, sample_weight: Any | None = None) -> float:
    """Return micro-averaged F1 score."""
    return float(f1_score(y_true, y_pred, average="micro", zero_division=0, sample_weight=sample_weight))

precision_macro staticmethod

Return macro-averaged precision.

Source code in highfis/metrics.py
@staticmethod
def precision_macro(y_true: Any, y_pred: Any, sample_weight: Any | None = None) -> float:
    """Return macro-averaged precision."""
    return float(precision_score(y_true, y_pred, average="macro", zero_division=0, sample_weight=sample_weight))

precision_micro staticmethod

Return micro-averaged precision.

Source code in highfis/metrics.py
@staticmethod
def precision_micro(y_true: Any, y_pred: Any, sample_weight: Any | None = None) -> float:
    """Return micro-averaged precision."""
    return float(precision_score(y_true, y_pred, average="micro", zero_division=0, sample_weight=sample_weight))

recall_macro staticmethod

Return macro-averaged recall.

Source code in highfis/metrics.py
@staticmethod
def recall_macro(y_true: Any, y_pred: Any, sample_weight: Any | None = None) -> float:
    """Return macro-averaged recall."""
    return float(recall_score(y_true, y_pred, average="macro", zero_division=0, sample_weight=sample_weight))

recall_micro staticmethod

Return micro-averaged recall.

Source code in highfis/metrics.py
@staticmethod
def recall_micro(y_true: Any, y_pred: Any, sample_weight: Any | None = None) -> float:
    """Return micro-averaged recall."""
    return float(recall_score(y_true, y_pred, average="micro", zero_division=0, sample_weight=sample_weight))

ClassificationMetricsPytorch

Standard classification metrics using PyTorch.

accuracy staticmethod

Return classification accuracy.

Source code in highfis/metrics.py
@staticmethod
def accuracy(y_true: torch.Tensor, y_pred: torch.Tensor, sample_weight: torch.Tensor | None = None) -> float:
    """Return classification accuracy."""
    if sample_weight is not None:
        return (torch.sum((y_true == y_pred).float() * sample_weight) / torch.sum(sample_weight)).item()
    return torch.mean((y_true == y_pred).float()).item()

balanced_accuracy staticmethod

Return the balanced accuracy score.

Source code in highfis/metrics.py
@staticmethod
def balanced_accuracy(
    y_true: torch.Tensor, y_pred: torch.Tensor, sample_weight: torch.Tensor | None = None
) -> float:
    """Return the balanced accuracy score."""
    classes = torch.unique(y_true)
    recalls = []
    for c in classes:
        true_c = y_true == c
        if sample_weight is not None:
            w_c = sample_weight[true_c]
            den = torch.sum(w_c)
            if den == 0:
                recalls.append(torch.tensor(0.0, device=y_true.device))
            else:
                recalls.append(torch.sum((y_pred[true_c] == c).float() * w_c) / den)
        else:
            recalls.append(torch.mean((y_pred[true_c] == c).float()))
    return torch.stack(recalls).mean().item() if recalls else 0.0

classes staticmethod

Return the sorted union of true and predicted labels.

Note

sample_weight is ignored.

Source code in highfis/metrics.py
@staticmethod
def classes(y_true: torch.Tensor, y_pred: torch.Tensor, sample_weight: torch.Tensor | None = None) -> np.ndarray:
    """Return the sorted union of true and predicted labels.

    Note:
        ``sample_weight`` is ignored.
    """
    if sample_weight is not None:
        warnings.warn("sample_weight is ignored by classes", UserWarning, stacklevel=2)
    return torch.unique(torch.cat([y_true, y_pred])).cpu().numpy()

confusion_matrix staticmethod

Return the confusion matrix.

Source code in highfis/metrics.py
@staticmethod
def confusion_matrix(
    y_true: torch.Tensor, y_pred: torch.Tensor, sample_weight: torch.Tensor | None = None
) -> np.ndarray:
    """Return the confusion matrix."""
    classes, inverse = torch.unique(torch.cat([y_true, y_pred]), return_inverse=True)
    n_classes = len(classes)

    y_true_idx = inverse[: len(y_true)]
    y_pred_idx = inverse[len(y_true) :]
    indices = y_true_idx * n_classes + y_pred_idx

    if sample_weight is not None:
        cm = torch.bincount(indices, weights=sample_weight, minlength=n_classes**2)
    else:
        cm = torch.bincount(indices, minlength=n_classes**2)

    return cm.reshape(n_classes, n_classes).cpu().numpy()

f1_macro staticmethod

Return macro-averaged F1 score.

Source code in highfis/metrics.py
@staticmethod
def f1_macro(y_true: torch.Tensor, y_pred: torch.Tensor, sample_weight: torch.Tensor | None = None) -> float:
    """Return macro-averaged F1 score."""
    _, _, f1 = ClassificationMetricsPytorch._precision_recall_f1_macro(y_true, y_pred, sample_weight)
    return f1.item()

f1_micro staticmethod

Return micro-averaged F1 score.

Source code in highfis/metrics.py
@staticmethod
def f1_micro(y_true: torch.Tensor, y_pred: torch.Tensor, sample_weight: torch.Tensor | None = None) -> float:
    """Return micro-averaged F1 score."""
    _, _, f1 = ClassificationMetricsPytorch._precision_recall_f1_micro(y_true, y_pred, sample_weight)
    return f1.item()

precision_macro staticmethod

Return macro-averaged precision.

Source code in highfis/metrics.py
@staticmethod
def precision_macro(y_true: torch.Tensor, y_pred: torch.Tensor, sample_weight: torch.Tensor | None = None) -> float:
    """Return macro-averaged precision."""
    prec, _, _ = ClassificationMetricsPytorch._precision_recall_f1_macro(y_true, y_pred, sample_weight)
    return prec.item()

precision_micro staticmethod

Return micro-averaged precision.

Source code in highfis/metrics.py
@staticmethod
def precision_micro(y_true: torch.Tensor, y_pred: torch.Tensor, sample_weight: torch.Tensor | None = None) -> float:
    """Return micro-averaged precision."""
    prec, _, _ = ClassificationMetricsPytorch._precision_recall_f1_micro(y_true, y_pred, sample_weight)
    return prec.item()

recall_macro staticmethod

Return macro-averaged recall.

Source code in highfis/metrics.py
@staticmethod
def recall_macro(y_true: torch.Tensor, y_pred: torch.Tensor, sample_weight: torch.Tensor | None = None) -> float:
    """Return macro-averaged recall."""
    _, rec, _ = ClassificationMetricsPytorch._precision_recall_f1_macro(y_true, y_pred, sample_weight)
    return rec.item()

recall_micro staticmethod

Return micro-averaged recall.

Source code in highfis/metrics.py
@staticmethod
def recall_micro(y_true: torch.Tensor, y_pred: torch.Tensor, sample_weight: torch.Tensor | None = None) -> float:
    """Return micro-averaged recall."""
    _, rec, _ = ClassificationMetricsPytorch._precision_recall_f1_micro(y_true, y_pred, sample_weight)
    return rec.item()

RegressionMetrics

Standard regression metrics.

explained_variance staticmethod

Return explained variance.

Source code in highfis/metrics.py
@staticmethod
def explained_variance(y_true: Any, y_pred: Any, sample_weight: Any | None = None) -> float:
    """Return explained variance."""
    return float(explained_variance_score(y_true, y_pred, sample_weight=sample_weight))

mae staticmethod

Return mean absolute error.

Source code in highfis/metrics.py
@staticmethod
def mae(y_true: Any, y_pred: Any, sample_weight: Any | None = None) -> float:
    """Return mean absolute error."""
    return float(mean_absolute_error(y_true, y_pred, sample_weight=sample_weight))

mape staticmethod

Return mean absolute percentage error.

Source code in highfis/metrics.py
@staticmethod
def mape(y_true: Any, y_pred: Any, sample_weight: Any | None = None) -> float:
    """Return mean absolute percentage error."""
    return float(mean_absolute_percentage_error(y_true, y_pred, sample_weight=sample_weight))

max_error staticmethod

Return maximum absolute error.

Note

sample_weight is ignored.

Source code in highfis/metrics.py
@staticmethod
def max_error(y_true: Any, y_pred: Any, sample_weight: Any | None = None) -> float:
    """Return maximum absolute error.

    Note:
        ``sample_weight`` is ignored.
    """
    if sample_weight is not None:
        warnings.warn("sample_weight is ignored by max_error", UserWarning, stacklevel=2)
    return float(max_error(y_true, y_pred))

mean_bias_error staticmethod

Return mean bias error (prediction minus truth).

Source code in highfis/metrics.py
@staticmethod
def mean_bias_error(y_true: Any, y_pred: Any, sample_weight: Any | None = None) -> float:
    """Return mean bias error (prediction minus truth)."""
    y_true_arr = _flatten_array(y_true)
    y_pred_arr = _flatten_array(y_pred)
    if sample_weight is not None:
        return float(np.average(y_pred_arr - y_true_arr, weights=sample_weight))
    return float(np.mean(y_pred_arr - y_true_arr))

median_absolute_error staticmethod

Return median absolute error.

Source code in highfis/metrics.py
@staticmethod
def median_absolute_error(y_true: Any, y_pred: Any, sample_weight: Any | None = None) -> float:
    """Return median absolute error."""
    return float(median_absolute_error(y_true, y_pred, sample_weight=sample_weight))

mse staticmethod

Return mean squared error.

Source code in highfis/metrics.py
@staticmethod
def mse(y_true: Any, y_pred: Any, sample_weight: Any | None = None) -> float:
    """Return mean squared error."""
    return float(mean_squared_error(y_true, y_pred, sample_weight=sample_weight))

msle staticmethod

Return mean squared logarithmic error.

Source code in highfis/metrics.py
@staticmethod
def msle(y_true: Any, y_pred: Any, sample_weight: Any | None = None) -> float:
    """Return mean squared logarithmic error."""
    try:
        return float(mean_squared_log_error(y_true, y_pred, sample_weight=sample_weight))
    except ValueError:
        return float(np.nan)

pearson staticmethod

Return Pearson correlation coefficient.

Note

sample_weight is ignored.

Source code in highfis/metrics.py
@staticmethod
def pearson(y_true: Any, y_pred: Any, sample_weight: Any | None = None) -> float:
    """Return Pearson correlation coefficient.

    Note:
        ``sample_weight`` is ignored.
    """
    if sample_weight is not None:
        warnings.warn("sample_weight is ignored by pearson", UserWarning, stacklevel=2)
    y_true_arr = _flatten_array(y_true)
    y_pred_arr = _flatten_array(y_pred)
    if y_true_arr.size < 2 or np.std(y_true_arr) == 0 or np.std(y_pred_arr) == 0:
        return float(np.nan)
    with np.errstate(invalid="ignore", divide="ignore"):
        return float(np.corrcoef(y_true_arr, y_pred_arr)[0, 1])

r2 staticmethod

Return coefficient of determination (R²).

Source code in highfis/metrics.py
@staticmethod
def r2(y_true: Any, y_pred: Any, sample_weight: Any | None = None) -> float:
    """Return coefficient of determination (R²)."""
    return float(r2_score(y_true, y_pred, sample_weight=sample_weight))

rmse staticmethod

Return root mean squared error.

Source code in highfis/metrics.py
@staticmethod
def rmse(y_true: Any, y_pred: Any, sample_weight: Any | None = None) -> float:
    """Return root mean squared error."""
    return float(np.sqrt(mean_squared_error(y_true, y_pred, sample_weight=sample_weight)))

smape staticmethod

Return symmetric mean absolute percentage error.

Source code in highfis/metrics.py
@staticmethod
def smape(y_true: Any, y_pred: Any, sample_weight: Any | None = None) -> float:
    """Return symmetric mean absolute percentage error."""
    y_true_arr = _flatten_array(y_true)
    y_pred_arr = _flatten_array(y_pred)
    numerator = np.abs(y_pred_arr - y_true_arr) * 2.0
    denominator = np.abs(y_true_arr) + np.abs(y_pred_arr)
    with np.errstate(divide="ignore", invalid="ignore"):
        ratio = np.where(denominator == 0.0, 0.0, numerator / denominator)
    if sample_weight is not None:
        return float(np.average(ratio, weights=sample_weight))
    return float(np.mean(ratio))

std_error staticmethod

Return the standard deviation of the errors.

Note

sample_weight is ignored.

Source code in highfis/metrics.py
@staticmethod
def std_error(y_true: Any, y_pred: Any, sample_weight: Any | None = None) -> float:
    """Return the standard deviation of the errors.

    Note:
        ``sample_weight`` is ignored.
    """
    if sample_weight is not None:
        warnings.warn("sample_weight is ignored by std_error", UserWarning, stacklevel=2)
    y_true_arr = _flatten_array(y_true)
    y_pred_arr = _flatten_array(y_pred)
    if y_true_arr.size < 2:
        return 0.0
    return float(np.std(y_pred_arr - y_true_arr, ddof=1))

RegressionMetricsPytorch

Standard regression metrics using PyTorch.

explained_variance staticmethod

Return explained variance.

Note

Uses biased variance (unbiased=False) to match scikit-learn's explained_variance_score implementation.

Source code in highfis/metrics.py
@staticmethod
def explained_variance(
    y_true: torch.Tensor, y_pred: torch.Tensor, sample_weight: torch.Tensor | None = None
) -> float:
    """Return explained variance.

    Note:
        Uses biased variance (unbiased=False) to match scikit-learn's
        explained_variance_score implementation.
    """
    y_true = y_true.float()
    y_pred = y_pred.float()
    if sample_weight is not None:
        sample_weight = sample_weight.float()
        mean_diff = torch.sum((y_true - y_pred) * sample_weight) / torch.sum(sample_weight)
        var_diff = torch.sum(((y_true - y_pred - mean_diff) ** 2) * sample_weight) / torch.sum(sample_weight)
        mean_y = torch.sum(y_true * sample_weight) / torch.sum(sample_weight)
        var_y = torch.sum(((y_true - mean_y) ** 2) * sample_weight) / torch.sum(sample_weight)
    else:
        var_diff = torch.var(y_true - y_pred, unbiased=False)
        var_y = torch.var(y_true, unbiased=False)
    return (1.0 - var_diff / var_y).item() if var_y > 0 else 0.0

mae staticmethod

Return mean absolute error.

Source code in highfis/metrics.py
@staticmethod
def mae(y_true: torch.Tensor, y_pred: torch.Tensor, sample_weight: torch.Tensor | None = None) -> float:
    """Return mean absolute error."""
    y_true = y_true.float()
    y_pred = y_pred.float()
    if sample_weight is not None:
        sample_weight = sample_weight.float()
        return (torch.sum(torch.abs(y_true - y_pred) * sample_weight) / torch.sum(sample_weight)).item()
    return torch.mean(torch.abs(y_true - y_pred)).item()

mape staticmethod

Return mean absolute percentage error.

Source code in highfis/metrics.py
@staticmethod
def mape(y_true: torch.Tensor, y_pred: torch.Tensor, sample_weight: torch.Tensor | None = None) -> float:
    """Return mean absolute percentage error."""
    y_true = y_true.float()
    y_pred = y_pred.float()
    eps = torch.finfo(y_true.dtype).eps
    ratio = torch.abs(y_true - y_pred) / torch.clamp(torch.abs(y_true), min=eps)
    if sample_weight is not None:
        sample_weight = sample_weight.float()
        return (torch.sum(ratio * sample_weight) / torch.sum(sample_weight)).item()
    return torch.mean(ratio).item()

max_error staticmethod

Return maximum absolute error.

Note

sample_weight is ignored.

Source code in highfis/metrics.py
@staticmethod
def max_error(y_true: torch.Tensor, y_pred: torch.Tensor, sample_weight: torch.Tensor | None = None) -> float:
    """Return maximum absolute error.

    Note:
        ``sample_weight`` is ignored.
    """
    y_true = y_true.float()
    y_pred = y_pred.float()
    if sample_weight is not None:
        sample_weight = sample_weight.float()
        warnings.warn("sample_weight is ignored by max_error", UserWarning, stacklevel=2)
    return torch.max(torch.abs(y_true - y_pred)).item()

mean_bias_error staticmethod

Return mean bias error (prediction minus truth).

Source code in highfis/metrics.py
@staticmethod
def mean_bias_error(y_true: torch.Tensor, y_pred: torch.Tensor, sample_weight: torch.Tensor | None = None) -> float:
    """Return mean bias error (prediction minus truth)."""
    y_true = y_true.float()
    y_pred = y_pred.float()
    diff = y_pred - y_true
    if sample_weight is not None:
        sample_weight = sample_weight.float()
        return (torch.sum(diff * sample_weight) / torch.sum(sample_weight)).item()
    return torch.mean(diff).item()

median_absolute_error staticmethod

Return median absolute error.

Source code in highfis/metrics.py
@staticmethod
def median_absolute_error(
    y_true: torch.Tensor, y_pred: torch.Tensor, sample_weight: torch.Tensor | None = None
) -> float:
    """Return median absolute error."""
    y_true = y_true.float()
    y_pred = y_pred.float()
    errors = torch.abs(y_true - y_pred)
    if sample_weight is not None:
        sample_weight = sample_weight.float()
        # Weighted median matching scikit-learn
        sorted_indices = torch.argsort(errors)
        sorted_errors = errors[sorted_indices]
        sorted_weights = sample_weight[sorted_indices]
        cum_weights = torch.cumsum(sorted_weights, dim=0)
        total_weight = cum_weights[-1]
        half_weight = total_weight / 2.0
        idx = torch.searchsorted(cum_weights, half_weight)
        idx = torch.clamp(idx, max=max(0, len(sorted_errors) - 1))
        if idx < len(sorted_errors) - 1 and cum_weights[idx] == half_weight:
            return ((sorted_errors[idx] + sorted_errors[idx + 1]) / 2.0).item()
        return sorted_errors[idx].item()
    return torch.quantile(errors, 0.5).item()

mse staticmethod

Return mean squared error.

Source code in highfis/metrics.py
@staticmethod
def mse(y_true: torch.Tensor, y_pred: torch.Tensor, sample_weight: torch.Tensor | None = None) -> float:
    """Return mean squared error."""
    y_true = y_true.float()
    y_pred = y_pred.float()
    if sample_weight is not None:
        sample_weight = sample_weight.float()
        return (torch.sum(((y_true - y_pred) ** 2) * sample_weight) / torch.sum(sample_weight)).item()
    return torch.mean((y_true - y_pred) ** 2).item()

msle staticmethod

Return mean squared logarithmic error.

Source code in highfis/metrics.py
@staticmethod
def msle(y_true: torch.Tensor, y_pred: torch.Tensor, sample_weight: torch.Tensor | None = None) -> float:
    """Return mean squared logarithmic error."""
    y_true = y_true.float()
    y_pred = y_pred.float()
    if torch.any(y_true < 0) or torch.any(y_pred < 0):
        return float("nan")
    log_diff = torch.log1p(y_true) - torch.log1p(y_pred)
    if sample_weight is not None:
        sample_weight = sample_weight.float()
        return (torch.sum((log_diff**2) * sample_weight) / torch.sum(sample_weight)).item()
    return torch.mean(log_diff**2).item()

pearson staticmethod

Return Pearson correlation coefficient.

Note

sample_weight is ignored.

Source code in highfis/metrics.py
@staticmethod
def pearson(y_true: torch.Tensor, y_pred: torch.Tensor, sample_weight: torch.Tensor | None = None) -> float:
    """Return Pearson correlation coefficient.

    Note:
        ``sample_weight`` is ignored.
    """
    y_true = y_true.float()
    y_pred = y_pred.float()
    if sample_weight is not None:
        sample_weight = sample_weight.float()
        warnings.warn("sample_weight is ignored by pearson", UserWarning, stacklevel=2)
    if y_true.numel() < 2:
        return float("nan")
    vx = y_true - torch.mean(y_true)
    vy = y_pred - torch.mean(y_pred)
    corr = torch.sum(vx * vy) / (torch.sqrt(torch.sum(vx**2) * torch.sum(vy**2)))
    if torch.isnan(corr) or torch.isinf(corr):
        return float("nan")
    return corr.item()

r2 staticmethod

Return coefficient of determination (R²).

Source code in highfis/metrics.py
@staticmethod
def r2(y_true: torch.Tensor, y_pred: torch.Tensor, sample_weight: torch.Tensor | None = None) -> float:
    """Return coefficient of determination (R²)."""
    y_true = y_true.float()
    y_pred = y_pred.float()
    if sample_weight is not None:
        sample_weight = sample_weight.float()
        mean_y = torch.sum(y_true * sample_weight) / torch.sum(sample_weight)
        ss_res = torch.sum(((y_true - y_pred) ** 2) * sample_weight)
        ss_tot = torch.sum(((y_true - mean_y) ** 2) * sample_weight)
    else:
        mean_y = torch.mean(y_true)
        ss_res = torch.sum((y_true - y_pred) ** 2)
        ss_tot = torch.sum((y_true - mean_y) ** 2)
    if ss_tot == 0:
        return 1.0 if ss_res == 0 else 0.0
    return (1.0 - ss_res / ss_tot).item()

rmse staticmethod

Return root mean squared error.

Source code in highfis/metrics.py
@staticmethod
def rmse(y_true: torch.Tensor, y_pred: torch.Tensor, sample_weight: torch.Tensor | None = None) -> float:
    """Return root mean squared error."""
    y_true = y_true.float()
    y_pred = y_pred.float()
    if sample_weight is not None:
        sample_weight = sample_weight.float()
        return torch.sqrt(torch.sum(((y_true - y_pred) ** 2) * sample_weight) / torch.sum(sample_weight)).item()
    return torch.sqrt(torch.mean((y_true - y_pred) ** 2)).item()

smape staticmethod

Return symmetric mean absolute percentage error.

Source code in highfis/metrics.py
@staticmethod
def smape(y_true: torch.Tensor, y_pred: torch.Tensor, sample_weight: torch.Tensor | None = None) -> float:
    """Return symmetric mean absolute percentage error."""
    y_true = y_true.float()
    y_pred = y_pred.float()
    numerator = torch.abs(y_pred - y_true) * 2.0
    denominator = torch.abs(y_true) + torch.abs(y_pred)
    ratio = torch.where(denominator == 0.0, torch.zeros_like(numerator), numerator / denominator)
    if sample_weight is not None:
        sample_weight = sample_weight.float()
        return (torch.sum(ratio * sample_weight) / torch.sum(sample_weight)).item()
    return torch.mean(ratio).item()

std_error staticmethod

Return the standard deviation of the errors.

Note

sample_weight is ignored.

Source code in highfis/metrics.py
@staticmethod
def std_error(y_true: torch.Tensor, y_pred: torch.Tensor, sample_weight: torch.Tensor | None = None) -> float:
    """Return the standard deviation of the errors.

    Note:
        ``sample_weight`` is ignored.
    """
    y_true = y_true.float()
    y_pred = y_pred.float()
    if sample_weight is not None:
        sample_weight = sample_weight.float()
        warnings.warn("sample_weight is ignored by std_error", UserWarning, stacklevel=2)
    if y_true.numel() < 2:
        return 0.0
    return torch.std(y_pred - y_true, unbiased=True).item()

compute_metrics

Compute a set of named evaluation metrics.

Parameters:

Name Type Description Default
task Task

"classification" or "regression".

required
y_true Any

Ground-truth labels or targets.

required
y_pred Any

Predicted labels or values.

required
sample_weight Any | None

Optional sample weights.

None
metrics Sequence[str] | None

Optional list of metric names to compute.

None

Returns:

Type Description
dict[str, Any]

Dictionary mapping metric names to scalar float results.

Source code in highfis/metrics.py
def compute_metrics(
    task: Task,
    y_true: Any,
    y_pred: Any,
    sample_weight: Any | None = None,
    metrics: Sequence[str] | None = None,
) -> dict[str, Any]:
    """Compute a set of named evaluation metrics.

    Args:
        task: ``"classification"`` or ``"regression"``.
        y_true: Ground-truth labels or targets.
        y_pred: Predicted labels or values.
        sample_weight: Optional sample weights.
        metrics: Optional list of metric names to compute.

    Returns:
        Dictionary mapping metric names to scalar float results.
    """
    if isinstance(y_true, torch.Tensor) and isinstance(y_pred, torch.Tensor):
        if sample_weight is not None and not isinstance(sample_weight, torch.Tensor):
            sample_weight = torch.as_tensor(sample_weight, device=y_true.device, dtype=y_true.dtype)
        return compute_metrics_pytorch(task, y_true, y_pred, sample_weight, metrics)

    if task == "classification":
        return _compute_classification_numpy(y_true, y_pred, sample_weight, metrics)
    if task == "regression":
        return _compute_regression_numpy(y_true, y_pred, sample_weight, metrics)
    raise ValueError("task must be 'classification' or 'regression'")

compute_metrics_pytorch

Compute a set of named evaluation metrics using PyTorch.

Source code in highfis/metrics.py
def compute_metrics_pytorch(
    task: Task,
    y_true: torch.Tensor,
    y_pred: torch.Tensor,
    sample_weight: torch.Tensor | None = None,
    metrics: Sequence[str] | None = None,
) -> dict[str, Any]:
    """Compute a set of named evaluation metrics using PyTorch."""
    if y_true.ndim != 1:
        y_true = y_true.ravel()
    if y_pred.ndim != 1:
        y_pred = y_pred.ravel()
    if sample_weight is not None and sample_weight.ndim != 1:
        sample_weight = sample_weight.ravel()

    if y_true.numel() != y_pred.numel():
        raise ValueError(
            f"Found input variables with inconsistent numbers of samples: [{y_true.numel()}, {y_pred.numel()}]"
        )

    if task == "classification":
        return _compute_classification_pytorch(y_true, y_pred, sample_weight, metrics)
    if task == "regression":
        return _compute_regression_pytorch(y_true, y_pred, sample_weight, metrics)
    raise ValueError("task must be 'classification' or 'regression'")