Skip to content

Add True Negative Rate (TNR) #541

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

Merged
merged 1 commit into from
Dec 19, 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
3 changes: 3 additions & 0 deletions cyclops/evaluate/metrics/experimental/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@
)
from cyclops.evaluate.metrics.experimental.specificity import (
BinarySpecificity,
BinaryTNR,
MulticlassSpecificity,
MulticlassTNR,
MultilabelSpecificity,
MultilabelTNR,
)
3 changes: 3 additions & 0 deletions cyclops/evaluate/metrics/experimental/functional/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
)
from cyclops.evaluate.metrics.experimental.functional.specificity import (
binary_specificity,
binary_tnr,
multiclass_specificity,
multiclass_tnr,
multilabel_specificity,
multilabel_tnr,
)
Original file line number Diff line number Diff line change
Expand Up @@ -441,3 +441,9 @@ def multilabel_specificity(
tn=tn,
fn=fn,
)


# Aliases
binary_tnr = binary_specificity
multiclass_tnr = multiclass_specificity
multilabel_tnr = multilabel_specificity
141 changes: 141 additions & 0 deletions cyclops/evaluate/metrics/experimental/specificity.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,3 +184,144 @@ def _compute_metric(self) -> Array:
tn=tn,
fn=fn,
)


# Aliases
class BinaryTNR(BinarySpecificity, registry_key="binary_tnr"):
"""The proportion of actual negatives that are correctly identified.

Parameters
----------
threshold : float, default=0.5
Threshold for converting probabilities into binary values.
ignore_index : int, optional
Values in the target array to ignore when computing the metric.
**kwargs
Additional keyword arguments common to all metrics.

Examples
--------
>>> from cyclops.evaluate.metrics.experimental import BinaryTNR
>>> import numpy.array_api as anp
>>> target = anp.asarray([0, 1, 0, 1])
>>> preds = anp.asarray([0, 1, 1, 1])
>>> metric = BinaryTNR()
>>> metric(target, preds)
Array(0.5, dtype=float32)
>>> metric.reset()
>>> target = [[0, 1, 0, 1], [1, 0, 1, 0]]
>>> preds = [[0, 1, 1, 1], [1, 0, 1, 0]]
>>> for t, p in zip(target, preds):
... metric.update(anp.asarray(t), anp.asarray(p))
>>> metric.compute()
Array(0.75, dtype=float32)

"""

name: str = "True Negative Rate"


class MulticlassTNR(MulticlassSpecificity, registry_key="multiclass_tnr"):
"""The proportion of actual negatives that are correctly identified.

Parameters
----------
num_classes : int
The number of classes in the classification task.
top_k : int, default=1
The number of highest probability or logit score predictions to consider
when computing the true negative rate. By default, only the top prediction is
considered. This parameter is ignored if `preds` contains integer values.
average : {'micro', 'macro', 'weighted', 'none'}, optional, default='micro'
Specifies the type of averaging to apply to the true negative rates. Should
be one of the following:
- `'micro'`: Compute the true negative rate globally by considering all
predictions and all targets.
- `'macro'`: Compute the true negative rate for each class individually and
then take the unweighted mean of the true negative rates.
- `'weighted'`: Compute the true negative rate for each class individually
and then take the mean of the true negative rates weighted by the support
(the number of true positives + the number of false negatives) for
each class.
- `'none'` or `None`: Compute the true negative rate for each class individually
and return the scores as an array.
ignore_index : int or tuple of int, optional, default=None
Specifies a target class that is ignored when computing the true negative rate.
Ignoring a target class means that the corresponding predictions do not
contribute to the true negative rate.

Examples
--------
>>> from cyclops.evaluate.metrics.experimental import MulticlassTNR
>>> import numpy.array_api as anp
>>> target = anp.asarray([0, 1, 2, 2, 2])
>>> preds = anp.asarray([0, 0, 2, 2, 1])
>>> metric = MulticlassTNR(num_classes=3)
>>> metric(target, preds)
Array(0.8, dtype=float32)
>>> metric.reset()
>>> target = [[0, 1, 2], [2, 1, 0]]
>>> preds = [[[0.05, 0.95, 0], [0.1, 0.8, 0.1], [0.2, 0.6, 0.2]],
... [[0.1, 0.8, 0.1], [0.05, 0.95, 0], [0.2, 0.6, 0.2]]]
>>> for t, p in zip(target, preds):
... metric.update(anp.asarray(t), anp.asarray(p))
>>> metric.compute()
Array(0.6666667, dtype=float32)

"""

name: str = "True Negative Rate"


class MultilabelTNR(MultilabelSpecificity, registry_key="multilabel_tnr"):
"""The proportion of actual negatives that are correctly identified.

Parameters
----------
num_labels : int
The number of labels in the classification task.
threshold : float, optional, default=0.5
The threshold used to convert probabilities to binary values.
top_k : int, optional, default=1
The number of highest probability predictions to assign the value `1`
(all other predictions are assigned the value `0`). By default, only the
highest probability prediction is considered. This parameter is ignored
if `preds` does not contain floating point values.
average : {'micro', 'macro', 'weighted', 'none'}, optional, default='macro'
Specifies the type of averaging to apply to the true negative rates. Should
be one of the following:
- `'micro'`: Compute the true negative rate globally by considering all
predictions and all targets.
- `'macro'`: Compute the true negative rate for each label individually and
then take the unweighted mean of the true negative rates.
- `'weighted'`: Compute the true negative rate for each label individually
and then take the mean of the true negative rates weighted by the support
(the number of true positives + the number of false negatives) for each
label.
- `'none'` or `None`: Compute the true negative rate for each label individually
and return the scores as an array.
ignore_index : int, optional, default=None
Specifies a value in the target array(s) that is ignored when computing
the true negative rate.

Examples
--------
>>> from cyclops.evaluate.metrics.experimental import MultilabelTNR
>>> import numpy.array_api as anp
>>> target = anp.asarray([[0, 1, 1], [1, 0, 0]])
>>> preds = anp.asarray([[0, 1, 0], [1, 0, 1]])
>>> metric = MultilabelTNR(num_labels=3)
>>> metric(target, preds)
Array(0.6666667, dtype=float32)
>>> metric.reset()
>>> target = [[[0, 1, 1], [1, 0, 0]], [[1, 0, 0], [0, 1, 1]]]
>>> preds = [[[0.05, 0.95, 0], [0.1, 0.8, 0.1]],
... [[0.1, 0.8, 0.1], [0.05, 0.95, 0]]]
>>> for t, p in zip(target, preds):
... metric.update(anp.asarray(t), anp.asarray(p))
>>> metric.compute()
Array(0.6666667, dtype=float32)

"""

name: str = "True Negative Rate"