.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/model_evaluation/plot_custom_metrics.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_model_evaluation_plot_custom_metrics.py: .. _example_custom_metrics: =========================================================== `EstimatorReport.metrics.add`: Adapt skore to your use-case =========================================================== By default, :meth:`~skore.EstimatorReport.metrics.summarize` reports a curated set of metrics for your ML task. In practice you often need domain-specific scores: a business cost function, a custom fairness measure, an F-beta with a particular beta, etc. This example walks through how to register such metrics with :meth:`~skore.EstimatorReport.metrics.add` so they are computed and displayed alongside the built-in ones. .. GENERATED FROM PYTHON SOURCE LINES 19-21 Setting up a classification problem =================================== .. GENERATED FROM PYTHON SOURCE LINES 23-29 .. code-block:: Python import skore from sklearn.datasets import load_breast_cancer from sklearn.linear_model import LogisticRegression X, y = load_breast_cancer(return_X_y=True) .. GENERATED FROM PYTHON SOURCE LINES 30-33 We create an :class:`~skore.EstimatorReport` through :func:`~skore.evaluate` using a simple train/test split. ``pos_label=1`` marks the *malignant* class as the positive class. .. GENERATED FROM PYTHON SOURCE LINES 35-39 .. code-block:: Python report = skore.evaluate( LogisticRegression(max_iter=10_000), X, y, pos_label=1, splitter=0.2 ) .. GENERATED FROM PYTHON SOURCE LINES 40-41 Let's look at the default metrics: .. GENERATED FROM PYTHON SOURCE LINES 41-43 .. code-block:: Python report.metrics.summarize().frame() .. raw:: html
LogisticRegression
Metric
Accuracy 0.947368
Precision 0.984127
Recall 0.925373
ROC AUC 0.993649
Log loss 0.110103
Brier score 0.036139
Fit time (s) 0.199774
Predict time (s) 0.000118


.. GENERATED FROM PYTHON SOURCE LINES 44-50 Adding a plain callable ======================= Any function with the signature ``(y_true, y_pred, **kwargs) -> float`` can be registered with :meth:`~skore.EstimatorReport.metrics.add`. The function name is used as the metric name by default. .. GENERATED FROM PYTHON SOURCE LINES 53-62 .. code-block:: Python def specificity(y_true, y_pred): """Proportion of true negatives among actual negatives.""" tn = ((y_true == 0) & (y_pred == 0)).sum() fp = ((y_true == 0) & (y_pred == 1)).sum() return tn / (tn + fp) report.metrics.add(specificity, greater_is_better=True) .. GENERATED FROM PYTHON SOURCE LINES 63-65 .. code-block:: Python report.metrics.summarize().frame() .. raw:: html
LogisticRegression
Metric
Accuracy 0.947368
Precision 0.984127
Recall 0.925373
ROC AUC 0.993649
Log loss 0.110103
Brier score 0.036139
Fit time (s) 0.199774
Predict time (s) 0.000118
Specificity 0.978723


.. GENERATED FROM PYTHON SOURCE LINES 66-67 ``specificity`` now appears alongside the built-in metrics. .. GENERATED FROM PYTHON SOURCE LINES 69-76 Passing extra keyword arguments ================================ If your metric needs extra data at scoring time (e.g. sample-level amounts, a cost matrix, ...), pass them as keyword arguments to :meth:`~skore.EstimatorReport.metrics.add`. They will be forwarded to the metric function when it is computed. .. GENERATED FROM PYTHON SOURCE LINES 78-96 .. code-block:: Python def misclassification_cost(y_true, y_pred, cost_fp, cost_fn): """Total cost of misclassifications, weighted by error type.""" fp = ((y_true == 0) & (y_pred == 1)).sum() fn = ((y_true == 1) & (y_pred == 0)).sum() return cost_fp * fp + cost_fn * fn report.metrics.add( misclassification_cost, greater_is_better=False, cost_fp=1.0, cost_fn=10.0, ) report.metrics.summarize().frame() .. raw:: html
LogisticRegression
Metric
Accuracy 0.947368
Precision 0.984127
Recall 0.925373
ROC AUC 0.993649
Log loss 0.110103
Brier score 0.036139
Fit time (s) 0.199774
Predict time (s) 0.000118
Specificity 0.978723
Misclassification Cost 51.000000


.. GENERATED FROM PYTHON SOURCE LINES 97-103 Adding an sklearn scorer ======================== If you already have a :func:`~sklearn.metrics.make_scorer` object, you can register it directly. The ``response_method`` and ``greater_is_better`` metadata are extracted from the scorer automatically. .. GENERATED FROM PYTHON SOURCE LINES 105-112 .. code-block:: Python from sklearn.metrics import fbeta_score, make_scorer f2_scorer = make_scorer(fbeta_score, beta=2, response_method="predict", pos_label=1) report.metrics.add(f2_scorer, name="f2") report.metrics.summarize().frame() .. raw:: html
LogisticRegression
Metric
Accuracy 0.947368
Precision 0.984127
Recall 0.925373
ROC AUC 0.993649
Log loss 0.110103
Brier score 0.036139
Fit time (s) 0.199774
Predict time (s) 0.000118
Specificity 0.978723
Misclassification Cost 51.000000
F2 0.936556


.. GENERATED FROM PYTHON SOURCE LINES 113-118 Cherry-picking metrics to display ================================== Once registered, custom metrics can be selected by name in :meth:`~skore.EstimatorReport.metrics.summarize`: .. GENERATED FROM PYTHON SOURCE LINES 120-124 .. code-block:: Python report.metrics.summarize( metric=["specificity", "f2", "misclassification_cost"], ).frame() .. raw:: html
LogisticRegression
Metric
Specificity 0.978723
F2 0.936556
Misclassification Cost 51.000000


.. GENERATED FROM PYTHON SOURCE LINES 125-126 Selecting ``data_source="both"`` lets you compare train vs. test in one call: .. GENERATED FROM PYTHON SOURCE LINES 128-130 .. code-block:: Python report.metrics.summarize(metric=["specificity", "f2"], data_source="both").frame() .. raw:: html
LogisticRegression (train) LogisticRegression (test)
Metric
Specificity 0.933333 0.978723
F2 0.975945 0.936556


.. GENERATED FROM PYTHON SOURCE LINES 131-136 Using a different response method ================================== By default, callables receive the output of ``estimator.predict(X)``. If your metric needs probabilities instead, set ``response_method="predict_proba"``. .. GENERATED FROM PYTHON SOURCE LINES 138-151 .. code-block:: Python import numpy as np def mean_confidence(y_true, y_proba): """Average predicted probability assigned to the true class.""" return np.where(y_true == 1, y_proba, 1 - y_proba).mean() report.metrics.add( mean_confidence, response_method="predict_proba", greater_is_better=True ) report.metrics.summarize(metric="mean_confidence").frame() .. raw:: html
LogisticRegression
Metric
Mean Confidence 0.931102


.. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.245 seconds) .. _sphx_glr_download_auto_examples_model_evaluation_plot_custom_metrics.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_custom_metrics.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_custom_metrics.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_custom_metrics.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_