Skip to content

Custom eval metric

mljar-supervised supports custom evaluation metrics.

You can pass your own Python function directly as the eval_metric argument in AutoML.

Basic usage

The function should have this interface:

def my_custom_metric(y_true, y_predicted, sample_weight=None):
    # compute score
    return score

Then use it directly:

from supervised import AutoML

automl = AutoML(
    results_path="AutoML_custom_metric",
    eval_metric=my_custom_metric,
)
automl.fit(X, y)

Important rule: the metric must be minimized

Custom metrics in mljar-supervised are always treated as metrics to minimize.

This means:

  • if lower is better, return the value directly
  • if higher is better, return its negative value

For example:

  • MSE can be returned directly
  • precision, F1, or AUC should usually return -value

Regression example

import numpy as np
from supervised import AutoML

def custom_mse(y_true, y_predicted, sample_weight=None):
    y_true = np.asarray(y_true)
    y_predicted = np.asarray(y_predicted)
    return np.mean((y_true - y_predicted) ** 2)

automl = AutoML(
    results_path="AutoML_regression_custom_metric",
    eval_metric=custom_mse,
)
automl.fit(X, y)

Classification example

For classification, y_predicted can contain probabilities, so you may need to apply thresholding or argmax inside your metric.

import numpy as np
from sklearn.metrics import precision_score
from supervised import AutoML

def positive_class_precision(y_true, y_predicted, sample_weight=None):
    y_true = np.asarray(y_true)
    y_predicted = np.asarray(y_predicted)

    if y_predicted.ndim == 2 and y_predicted.shape[1] == 1:
        y_predicted = y_predicted.ravel()

    if y_predicted.ndim == 1:
        y_predicted = (y_predicted > 0.5).astype(int)
    else:
        y_predicted = np.argmax(y_predicted, axis=1)

    value = precision_score(y_true, y_predicted, sample_weight=sample_weight)

    # higher precision is better, so return negative value
    return -value

automl = AutoML(
    results_path="AutoML_classification_custom_metric",
    eval_metric=positive_class_precision,
)
automl.fit(X, y)

Notes

  • the metric function must return a single numeric value
  • the metric should handle sample_weight=None
  • the metric will be used for early stopping and model selection
  • the metric should be deterministic and reasonably fast

FAQ

Can I pass a function directly?

Yes. This is the supported public interface:

automl = AutoML(eval_metric=my_custom_metric)

Should I pass eval_metric="user_defined_metric"?

No. That name is used internally. In user code, pass the function itself.

Can I maximize my metric directly?

No. Convert it to a minimization target, usually by returning -value.

Why do I need thresholding for some classification metrics?

Because many classification metrics such as precision or F1 expect class labels, while model predictions during evaluation can be probabilities.