Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix specificity calculation for CBPE #334

Merged
merged 6 commits into from
Nov 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Author: Niels Nuyttens <niels@nannyml.com>
#
# License: Apache Software License 2.0
import warnings
from typing import Any, Dict, List, Optional, Tuple, Union

import numpy as np
import pandas as pd
from sklearn.metrics import confusion_matrix, f1_score, precision_score, recall_score, roc_auc_score
import warnings

from nannyml._typing import ProblemType
from nannyml.base import _list_missing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,25 @@
# License: Apache Software License 2.0

"""Module containing metric utilities and implementations."""
import warnings
from typing import Dict, List, Optional, Tuple, Union # noqa: TYP001

import numpy as np
import pandas as pd
import warnings
from sklearn.metrics import (
accuracy_score,
confusion_matrix,
f1_score,
multilabel_confusion_matrix,
precision_score,
recall_score,
roc_auc_score,
confusion_matrix,
)
from sklearn.preprocessing import LabelBinarizer, label_binarize

from nannyml._typing import ProblemType, class_labels, model_output_column_names
from nannyml.base import _list_missing
from nannyml.chunk import Chunker
from nannyml.exceptions import InvalidArgumentsException
from nannyml.performance_calculation.metrics.base import Metric, MetricFactory, _common_data_cleaning
from nannyml.sampling_error.multiclass_classification import (
Expand All @@ -44,7 +45,6 @@
multiclass_confusion_matrix_sampling_error_components,
)
from nannyml.thresholds import Threshold, calculate_threshold_values
from nannyml.chunk import Chunker


@MetricFactory.register(metric='roc_auc', use_case=ProblemType.CLASSIFICATION_MULTICLASS)
Expand Down Expand Up @@ -636,7 +636,7 @@
alert_thresholds = {}

if self.classes is None:
raise ValueError("classes must be set before calling this method")

Check warning on line 639 in nannyml/performance_calculation/metrics/multiclass_classification.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_calculation/metrics/multiclass_classification.py#L639

Added line #L639 was not covered by tests

num_classes = len(self.classes)

Expand Down Expand Up @@ -674,7 +674,10 @@
for true_class in classes:
for pred_class in classes:
components.append(
(f"true class: '{true_class}', predicted class: '{pred_class}'", f'true_{true_class}_pred_{pred_class}')
(
f"true class: '{true_class}', predicted class: '{pred_class}'",
f'true_{true_class}_pred_{pred_class}',
)
)

return components
Expand All @@ -686,12 +689,12 @@
y_pred = data[self.y_pred]

if y_pred.isna().all().any():
raise InvalidArgumentsException(

Check warning on line 692 in nannyml/performance_calculation/metrics/multiclass_classification.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_calculation/metrics/multiclass_classification.py#L692

Added line #L692 was not covered by tests
f"could not calculate metric {self.display_name}: prediction column contains no data"
)

if (y_true.nunique() <= 1) or (y_pred.nunique() <= 1):
return np.nan

Check warning on line 697 in nannyml/performance_calculation/metrics/multiclass_classification.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_calculation/metrics/multiclass_classification.py#L697

Added line #L697 was not covered by tests
else:
cm = confusion_matrix(y_true, y_pred, labels=self.classes, normalize=self.normalize_confusion_matrix)
return cm
Expand All @@ -699,13 +702,13 @@
def get_chunk_record(self, chunk_data: pd.DataFrame) -> Dict[str, Union[float, bool]]:

if self.classes is None:
raise ValueError("classes must be set before calling this method")

Check warning on line 705 in nannyml/performance_calculation/metrics/multiclass_classification.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_calculation/metrics/multiclass_classification.py#L705

Added line #L705 was not covered by tests

sampling_errors = multiclass_confusion_matrix_sampling_error(self.sampling_error_components, chunk_data)
realized_cm = self._calculate(chunk_data)

if isinstance(realized_cm, float):
realized_cm = np.full((len(self.classes), len(self.classes)), np.nan)

Check warning on line 711 in nannyml/performance_calculation/metrics/multiclass_classification.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_calculation/metrics/multiclass_classification.py#L711

Added line #L711 was not covered by tests

chunk_record = {}

Expand Down
164 changes: 160 additions & 4 deletions nannyml/performance_estimation/confidence_based/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import abc
import logging
import warnings
from typing import Any, Callable, Dict, List, Optional, Tuple, Type, Union

import numpy as np
Expand Down Expand Up @@ -402,6 +403,11 @@
y_pred_proba, _, y_true = self._common_cleaning(data, y_pred_proba_column_name=self.uncalibrated_y_pred_proba)

if y_true is None:
warnings.warn("No 'y_true' values given for chunk, returning NaN as realized ROC-AUC.")
return np.NaN

if y_true.nunique() <= 1:
warnings.warn("Too few unique values present in 'y_true', returning NaN as realized ROC-AUC.")

Check warning on line 410 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L410

Added line #L410 was not covered by tests
return np.NaN

return roc_auc_score(y_true, y_pred_proba)
Expand Down Expand Up @@ -494,6 +500,15 @@
_, y_pred, y_true = self._common_cleaning(data, y_pred_proba_column_name=self.uncalibrated_y_pred_proba)

if y_true is None:
warnings.warn("No 'y_true' values given for chunk, returning NaN as realized F1 score.")
return np.NaN

if y_true.nunique() <= 1:
warnings.warn("Too few unique values present in 'y_true', returning NaN as realized F1 score.")
return np.NaN

Check warning on line 508 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L507-L508

Added lines #L507 - L508 were not covered by tests

if y_pred.nunique() <= 1:
warnings.warn("Too few unique values present in 'y_pred', returning NaN as realized F1 score.")

Check warning on line 511 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L511

Added line #L511 was not covered by tests
return np.NaN

return f1_score(y_true=y_true, y_pred=y_pred)
Expand Down Expand Up @@ -570,6 +585,15 @@
_, y_pred, y_true = self._common_cleaning(data, y_pred_proba_column_name=self.uncalibrated_y_pred_proba)

if y_true is None:
warnings.warn("No 'y_true' values given for chunk, returning NaN as realized precision.")
return np.NaN

if y_true.nunique() <= 1:
warnings.warn("Too few unique values present in 'y_true', returning NaN as realized precision.")
return np.NaN

Check warning on line 593 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L592-L593

Added lines #L592 - L593 were not covered by tests

if y_pred.nunique() <= 1:
warnings.warn("Too few unique values present in 'y_pred', returning NaN as realized precision.")

Check warning on line 596 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L596

Added line #L596 was not covered by tests
return np.NaN

return precision_score(y_true=y_true, y_pred=y_pred)
Expand Down Expand Up @@ -644,6 +668,15 @@
_, y_pred, y_true = self._common_cleaning(data, y_pred_proba_column_name=self.uncalibrated_y_pred_proba)

if y_true is None:
warnings.warn("No 'y_true' values given for chunk, returning NaN as realized recall.")
return np.NaN

if y_true.nunique() <= 1:
warnings.warn("Too few unique values present in 'y_true', returning NaN as recall precision.")
return np.NaN

Check warning on line 676 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L675-L676

Added lines #L675 - L676 were not covered by tests

if y_pred.nunique() <= 1:
warnings.warn("Too few unique values present in 'y_pred', returning NaN as recall precision.")

Check warning on line 679 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L679

Added line #L679 was not covered by tests
return np.NaN

return recall_score(y_true=y_true, y_pred=y_pred)
Expand Down Expand Up @@ -718,10 +751,19 @@
_, y_pred, y_true = self._common_cleaning(data, y_pred_proba_column_name=self.uncalibrated_y_pred_proba)

if y_true is None:
warnings.warn("No 'y_true' values given for chunk, returning NaN as realized specificity.")
return np.NaN

if y_true.nunique() <= 1:
warnings.warn("Too few unique values present in 'y_true', returning NaN as realized specificity.")

Check warning on line 758 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L758

Added line #L758 was not covered by tests
return np.NaN

if y_pred.nunique() <= 1:
warnings.warn("Too few unique values present in 'y_pred', returning NaN as realized specificity.")
return np.NaN

Check warning on line 763 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L762-L763

Added lines #L762 - L763 were not covered by tests

conf_matrix = confusion_matrix(y_true=y_true, y_pred=y_pred)
return conf_matrix[1, 1] / (conf_matrix[1, 0] + conf_matrix[1, 1])
tn, fp, fn, tp = confusion_matrix(y_true, y_pred).ravel()
return tn / (tn + fp)


def estimate_specificity(y_pred: pd.DataFrame, y_pred_proba: pd.DataFrame) -> float:
Expand Down Expand Up @@ -797,6 +839,15 @@
_, y_pred, y_true = self._common_cleaning(data, y_pred_proba_column_name=self.uncalibrated_y_pred_proba)

if y_true is None:
warnings.warn("No 'y_true' values given for chunk, returning NaN as realized accuracy.")
return np.NaN

if y_true.nunique() <= 1:
warnings.warn("Too few unique values present in 'y_true', returning NaN as realized accuracy.")
return np.NaN

Check warning on line 847 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L846-L847

Added lines #L846 - L847 were not covered by tests

if y_pred.nunique() <= 1:
warnings.warn("Too few unique values present in 'y_pred', returning NaN as realized accuracy.")

Check warning on line 850 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L850

Added line #L850 was not covered by tests
return np.NaN

return accuracy_score(y_true=y_true, y_pred=y_pred)
Expand Down Expand Up @@ -961,6 +1012,15 @@
_, y_pred, y_true = self._common_cleaning(data, y_pred_proba_column_name=self.uncalibrated_y_pred_proba)

if y_true is None:
warnings.warn("No 'y_true' values given for chunk, returning NaN as realized confusion matrix.")
return np.NaN

if y_true.nunique() <= 1:
warnings.warn("Too few unique values present in 'y_true', returning NaN as realized confusion matrix.")
return np.NaN

Check warning on line 1020 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L1019-L1020

Added lines #L1019 - L1020 were not covered by tests

if y_pred.nunique() <= 1:
warnings.warn("Too few unique values present in 'y_pred', returning NaN as realized confusion matrix.")

Check warning on line 1023 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L1023

Added line #L1023 was not covered by tests
return np.NaN

num_tp = np.sum(np.logical_and(y_pred, y_true))
Expand All @@ -980,6 +1040,7 @@
_, y_pred, y_true = self._common_cleaning(data, y_pred_proba_column_name=self.uncalibrated_y_pred_proba)

if y_true is None:
warnings.warn("No 'y_true' values given for chunk, returning NaN as realized confusion matrix.")
return np.NaN

num_tn = np.sum(np.logical_and(np.logical_not(y_pred), np.logical_not(y_true)))
Expand All @@ -999,6 +1060,15 @@
_, y_pred, y_true = self._common_cleaning(data, y_pred_proba_column_name=self.uncalibrated_y_pred_proba)

if y_true is None:
warnings.warn("No 'y_true' values given for chunk, returning NaN as realized confusion matrix.")
return np.NaN

if y_true.nunique() <= 1:
warnings.warn("Too few unique values present in 'y_true', returning NaN as realized confusion matrix.")
return np.NaN

Check warning on line 1068 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L1067-L1068

Added lines #L1067 - L1068 were not covered by tests

if y_pred.nunique() <= 1:
warnings.warn("Too few unique values present in 'y_pred', returning NaN as realized confusion matrix.")

Check warning on line 1071 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L1071

Added line #L1071 was not covered by tests
return np.NaN

num_tp = np.sum(np.logical_and(y_pred, y_true))
Expand All @@ -1018,6 +1088,15 @@
_, y_pred, y_true = self._common_cleaning(data, y_pred_proba_column_name=self.uncalibrated_y_pred_proba)

if y_true is None:
warnings.warn("No 'y_true' values given for chunk, returning NaN as realized confusion matrix.")
return np.NaN

if y_true.nunique() <= 1:
warnings.warn("Too few unique values present in 'y_true', returning NaN as realized confusion matrix.")
return np.NaN

Check warning on line 1096 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L1095-L1096

Added lines #L1095 - L1096 were not covered by tests

if y_pred.nunique() <= 1:
warnings.warn("Too few unique values present in 'y_pred', returning NaN as realized confusion matrix.")

Check warning on line 1099 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L1099

Added line #L1099 was not covered by tests
return np.NaN

num_tp = np.sum(np.logical_and(y_pred, y_true))
Expand Down Expand Up @@ -1500,6 +1579,15 @@
_, y_pred, y_true = self._common_cleaning(data, y_pred_proba_column_name=self.uncalibrated_y_pred_proba)

if y_true is None:
warnings.warn("No 'y_true' values given for chunk, returning NaN as realized business value.")
return np.NaN

if y_true.nunique() <= 1:
warnings.warn("Too few unique values present in 'y_true', returning NaN as realized business value.")
return np.NaN

Check warning on line 1587 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L1586-L1587

Added lines #L1586 - L1587 were not covered by tests

if y_pred.nunique() <= 1:
warnings.warn("Too few unique values present in 'y_pred', returning NaN as realized business value.")

Check warning on line 1590 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L1590

Added line #L1590 was not covered by tests
return np.NaN

tp_value = self.business_value_matrix[1, 1]
Expand Down Expand Up @@ -1677,7 +1765,13 @@

def _realized_performance(self, data: pd.DataFrame) -> float:
data = self._ensure_targets(data)

if data is None:
warnings.warn("No 'y_true' values given for chunk, returning NaN as realized ROC-AUC.")
return np.NaN

if data[self.y_true].nunique() <= 1:
warnings.warn("Too few unique values present in 'y_true', returning NaN as realized ROC-AUC.")

Check warning on line 1774 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L1774

Added line #L1774 was not covered by tests
return np.NaN

_, y_pred_probas, labels = _get_multiclass_uncalibrated_predictions(data, self.y_pred, self.y_pred_proba)
Expand Down Expand Up @@ -1734,7 +1828,17 @@

def _realized_performance(self, data: pd.DataFrame) -> float:
data = self._ensure_targets(data)

if data is None:
warnings.warn("No 'y_true' values given for chunk, returning NaN as realized F1 score.")
return np.NaN

if data[self.y_true].nunique() <= 1:
warnings.warn("Too few unique values present in 'y_true', returning NaN as realized F1 score.")
return np.NaN

Check warning on line 1838 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L1837-L1838

Added lines #L1837 - L1838 were not covered by tests

if data[self.y_pred].nunique() <= 1:
warnings.warn("Too few unique values present in 'y_pred', returning NaN as realized F1 score.")

Check warning on line 1841 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L1841

Added line #L1841 was not covered by tests
return np.NaN

y_pred, _, labels = _get_multiclass_uncalibrated_predictions(data, self.y_pred, self.y_pred_proba)
Expand Down Expand Up @@ -1791,7 +1895,17 @@

def _realized_performance(self, data: pd.DataFrame) -> float:
data = self._ensure_targets(data)

if data is None:
warnings.warn("No 'y_true' values given for chunk, returning NaN as realized precision.")
return np.NaN

if data[self.y_true].nunique() <= 1:
warnings.warn("Too few unique values present in 'y_true', returning NaN as realized precision.")
return np.NaN

Check warning on line 1905 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L1904-L1905

Added lines #L1904 - L1905 were not covered by tests

if data[self.y_pred].nunique() <= 1:
warnings.warn("Too few unique values present in 'y_pred', returning NaN as realized precision.")

Check warning on line 1908 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L1908

Added line #L1908 was not covered by tests
return np.NaN

y_pred, _, labels = _get_multiclass_uncalibrated_predictions(data, self.y_pred, self.y_pred_proba)
Expand Down Expand Up @@ -1848,7 +1962,17 @@

def _realized_performance(self, data: pd.DataFrame) -> float:
data = self._ensure_targets(data)

if data is None:
warnings.warn("No 'y_true' values given for chunk, returning NaN as realized recall.")
return np.NaN

if data[self.y_true].nunique() <= 1:
warnings.warn("Too few unique values present in 'y_true', returning NaN as realized recall.")
return np.NaN

Check warning on line 1972 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L1971-L1972

Added lines #L1971 - L1972 were not covered by tests

if data[self.y_pred].nunique() <= 1:
warnings.warn("Too few unique values present in 'y_pred', returning NaN as realized recall.")

Check warning on line 1975 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L1975

Added line #L1975 was not covered by tests
return np.NaN

y_pred, _, labels = _get_multiclass_uncalibrated_predictions(data, self.y_pred, self.y_pred_proba)
Expand Down Expand Up @@ -1905,7 +2029,17 @@

def _realized_performance(self, data: pd.DataFrame) -> float:
data = self._ensure_targets(data)

if data is None:
warnings.warn("No 'y_true' values given for chunk, returning NaN as realized specificity.")
return np.NaN

if data[self.y_true].nunique() <= 1:
warnings.warn("Too few unique values present in 'y_true', returning NaN as realized specificity.")
return np.NaN

Check warning on line 2039 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L2038-L2039

Added lines #L2038 - L2039 were not covered by tests

if data[self.y_pred].nunique() <= 1:
warnings.warn("Too few unique values present in 'y_pred', returning NaN as realized specificity.")

Check warning on line 2042 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L2042

Added line #L2042 was not covered by tests
return np.NaN

y_pred, _, labels = _get_multiclass_uncalibrated_predictions(data, self.y_pred, self.y_pred_proba)
Expand Down Expand Up @@ -1964,8 +2098,19 @@

def _realized_performance(self, data: pd.DataFrame) -> float:
data = self._ensure_targets(data)

if data is None:
warnings.warn("No 'y_true' values given for chunk, returning NaN as realized accuracy.")
return np.NaN

if data[self.y_true].nunique() <= 1:
warnings.warn("Too few unique values present in 'y_true', returning NaN as realized accuracy.")
return np.NaN

Check warning on line 2108 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L2107-L2108

Added lines #L2107 - L2108 were not covered by tests

if data[self.y_pred].nunique() <= 1:
warnings.warn("Too few unique values present in 'y_pred', returning NaN as realized accuracy.")
return np.NaN

Check warning on line 2112 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L2111-L2112

Added lines #L2111 - L2112 were not covered by tests

y_pred, _, _ = _get_multiclass_uncalibrated_predictions(data, self.y_pred, self.y_pred_proba)
return accuracy_score(data[self.y_true], y_pred)

Expand All @@ -1985,7 +2130,7 @@
):

if isinstance(y_pred_proba, str):
raise ValueError(

Check warning on line 2133 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L2133

Added line #L2133 was not covered by tests
"y_pred_proba must be a dictionary with class labels as keys and pred_proba column names as values"
)

Expand All @@ -2011,7 +2156,10 @@
for true_class in classes:
for pred_class in classes:
components.append(
(f"true class: '{true_class}', predicted class: '{pred_class}'", f'true_{true_class}_pred_{pred_class}')
(
f"true class: '{true_class}', predicted class: '{pred_class}'",
f'true_{true_class}_pred_{pred_class}',
)
)

return components
Expand Down Expand Up @@ -2074,9 +2222,17 @@
return alert_thresholds

def _multi_class_confusion_matrix_realized_performance(self, data: pd.DataFrame) -> Union[np.ndarray, float]:
if data is None or self.y_true not in data.columns:
warnings.warn("No 'y_true' values given for chunk, returning NaN as realized precision.")
return np.NaN

if data[self.y_true].nunique() <= 1:
warnings.warn("Too few unique values present in 'y_true', returning NaN as realized precision.")
return np.NaN

Check warning on line 2231 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L2230-L2231

Added lines #L2230 - L2231 were not covered by tests

if self.y_true not in data.columns or data[self.y_true].isna().all():
if data[self.y_pred].nunique() <= 1:
warnings.warn("Too few unique values present in 'y_pred', returning NaN as realized precision.")
return np.NaN

Check warning on line 2235 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L2234-L2235

Added lines #L2234 - L2235 were not covered by tests

cm = confusion_matrix(
data[self.y_true], data[self.y_pred], labels=self.classes, normalize=self.normalize_confusion_matrix
Expand Down Expand Up @@ -2105,7 +2261,7 @@
def _get_multiclass_confusion_matrix_estimate(self, chunk_data: pd.DataFrame) -> np.ndarray:

if isinstance(self.y_pred_proba, str):
raise ValueError(

Check warning on line 2264 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L2264

Added line #L2264 was not covered by tests
"y_pred_proba must be a dictionary with class labels as keys and pred_proba column names as values"
)

Expand Down Expand Up @@ -2138,7 +2294,7 @@
elif self.normalize_confusion_matrix == 'all':
normalized_est_confusion_matrix = est_confusion_matrix / np.sum(est_confusion_matrix)
else:
raise ValueError(

Check warning on line 2297 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L2297

Added line #L2297 was not covered by tests
f'normalize_confusion_matrix should be one of None, "true", \
"pred", or "all", but got {self.normalize_confusion_matrix}'
)
Expand Down Expand Up @@ -2232,10 +2388,10 @@
return chunk_record

def _estimate(self, data: pd.DataFrame):
pass

Check warning on line 2391 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L2391

Added line #L2391 was not covered by tests

def _sampling_error(self, data: pd.DataFrame) -> float:
return 0.0

Check warning on line 2394 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L2394

Added line #L2394 was not covered by tests

def _realized_performance(self, data: pd.DataFrame) -> float:
return 0.0

Check warning on line 2397 in nannyml/performance_estimation/confidence_based/metrics.py

View check run for this annotation

Codecov / codecov/patch

nannyml/performance_estimation/confidence_based/metrics.py#L2397

Added line #L2397 was not covered by tests
Loading
Loading