Skip to content

Commit

Permalink
rename f1 score (#731)
Browse files Browse the repository at this point in the history
* f1_score
* F1Score

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Jirka Borovec <[email protected]>
Co-authored-by: Jirka <[email protected]>
Co-authored-by: Daniel Stancl <[email protected]>
  • Loading branch information
5 people authored Jan 9, 2022
1 parent 459b01e commit c20860a
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 21 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* `PearsonCorrcoef` -> `PearsonCorrCoef`
* `SpearmanCorrcoef` -> `SpearmanCorrCoef`


- Renamed audio SDR metrics: ([#711](https://github.com/PyTorchLightning/metrics/pull/711))
* `functional.sdr` -> `functional.signal_distortion_ratio`
* `functional.si_sdr` -> `functional.scale_invariant_signal_distortion_ratio`
Expand All @@ -77,6 +76,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* `SNR` -> `SignalNoiseRatio`
* `SI_SNR` -> `ScaleInvariantSignalNoiseRatio`

- Renamed F-score metrics: ([#731](https://github.com/PyTorchLightning/metrics/pull/731))
* `torchmetrics.functional.f1` -> `torchmetrics.functional.f1_score`
* `torchmetrics.F1` -> `torchmetrics.F1Score`

### Removed

Expand Down
2 changes: 1 addition & 1 deletion docs/source/references/functional.rst
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ dice_score [func]
f1 [func]
~~~~~~~~~~~~~~~

.. autofunction:: torchmetrics.functional.f1
.. autofunction:: torchmetrics.functional.f1_score
:noindex:


Expand Down
6 changes: 3 additions & 3 deletions docs/source/references/modules.rst
Original file line number Diff line number Diff line change
Expand Up @@ -280,10 +280,10 @@ ConfusionMatrix
.. autoclass:: torchmetrics.ConfusionMatrix
:noindex:

F1
~~
F1Score
~~~~~~~

.. autoclass:: torchmetrics.F1
.. autoclass:: torchmetrics.F1Score
:noindex:

FBeta
Expand Down
31 changes: 22 additions & 9 deletions tests/classification/test_f_beta.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@
from tests.classification.inputs import _input_multilabel_prob as _input_mlb_prob
from tests.helpers import seed_all
from tests.helpers.testers import NUM_BATCHES, NUM_CLASSES, THRESHOLD, MetricTester
from torchmetrics import F1, FBeta, Metric
from torchmetrics.functional import f1, fbeta
from torchmetrics import F1Score, FBeta, Metric
from torchmetrics.functional import f1_score as f1_score_pl
from torchmetrics.functional import fbeta
from torchmetrics.utilities.checks import _input_format_classification
from torchmetrics.utilities.enums import AverageMethod

Expand Down Expand Up @@ -93,7 +94,7 @@ def _sk_fbeta_f1_multidim_multiclass(
"metric_class, metric_fn",
[
(partial(FBeta, beta=2.0), partial(fbeta, beta=2.0)),
(F1, f1),
(F1Score, f1_score_pl),
],
)
@pytest.mark.parametrize(
Expand Down Expand Up @@ -129,7 +130,7 @@ def test_wrong_params(metric_class, metric_fn, average, mdmc_average, num_classe
"metric_class, metric_fn",
[
(partial(FBeta, beta=2.0), partial(fbeta, beta=2.0)),
(F1, f1),
(F1Score, f1_score_pl),
],
)
def test_zero_division(metric_class, metric_fn):
Expand All @@ -151,7 +152,7 @@ def test_zero_division(metric_class, metric_fn):
"metric_class, metric_fn",
[
(partial(FBeta, beta=2.0), partial(fbeta, beta=2.0)),
(F1, f1),
(F1Score, f1_score_pl),
],
)
def test_no_support(metric_class, metric_fn):
Expand All @@ -178,7 +179,13 @@ def test_no_support(metric_class, metric_fn):
assert result_cl == result_fn == 0


@pytest.mark.parametrize("metric_class, metric_fn", [(partial(FBeta, beta=2.0), partial(fbeta, beta=2.0)), (F1, f1)])
@pytest.mark.parametrize(
"metric_class, metric_fn",
[
(partial(FBeta, beta=2.0), partial(fbeta, beta=2.0)),
(F1Score, f1_score_pl),
],
)
@pytest.mark.parametrize(
"ignore_index, expected", [(None, torch.tensor([1.0, np.nan])), (0, torch.tensor([np.nan, np.nan]))]
)
Expand All @@ -202,7 +209,10 @@ def test_class_not_present(metric_class, metric_fn, ignore_index, expected):

@pytest.mark.parametrize(
"metric_class, metric_fn, sk_fn",
[(partial(FBeta, beta=2.0), partial(fbeta, beta=2.0), partial(fbeta_score, beta=2.0)), (F1, f1, f1_score)],
[
(partial(FBeta, beta=2.0), partial(fbeta, beta=2.0), partial(fbeta_score, beta=2.0)),
(F1Score, f1_score_pl, f1_score),
],
)
@pytest.mark.parametrize("average", ["micro", "macro", None, "weighted", "samples"])
@pytest.mark.parametrize("ignore_index", [None, 0])
Expand Down Expand Up @@ -388,7 +398,7 @@ def test_fbeta_f1_differentiability(
"metric_class, metric_fn",
[
(partial(FBeta, beta=2.0), partial(fbeta, beta=2.0)),
(F1, fbeta),
(F1Score, fbeta),
],
)
@pytest.mark.parametrize(
Expand Down Expand Up @@ -430,7 +440,10 @@ def test_top_k(
@pytest.mark.parametrize("average", ["micro", "macro", "weighted"])
@pytest.mark.parametrize(
"metric_class, metric_functional, sk_fn",
[(partial(FBeta, beta=2.0), partial(fbeta, beta=2.0), partial(fbeta_score, beta=2.0)), (F1, f1, f1_score)],
[
(partial(FBeta, beta=2.0), partial(fbeta, beta=2.0), partial(fbeta_score, beta=2.0)),
(F1Score, f1_score_pl, f1_score),
],
)
def test_same_input(metric_class, metric_functional, sk_fn, average, ignore_index):
preds = _input_miss_class.preds
Expand Down
2 changes: 2 additions & 0 deletions torchmetrics/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
CalibrationError,
CohenKappa,
ConfusionMatrix,
F1Score,
FBeta,
HammingDistance,
Hinge,
Expand Down Expand Up @@ -114,6 +115,7 @@
"TweedieDevianceScore",
"ExplainedVariance",
"F1",
"F1Score",
"FBeta",
"HammingDistance",
"Hinge",
Expand Down
2 changes: 1 addition & 1 deletion torchmetrics/classification/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from torchmetrics.classification.calibration_error import CalibrationError # noqa: F401
from torchmetrics.classification.cohen_kappa import CohenKappa # noqa: F401
from torchmetrics.classification.confusion_matrix import ConfusionMatrix # noqa: F401
from torchmetrics.classification.f_beta import F1, FBeta # noqa: F401
from torchmetrics.classification.f_beta import F1, F1Score, FBeta # noqa: F401
from torchmetrics.classification.hamming_distance import HammingDistance # noqa: F401
from torchmetrics.classification.hinge import Hinge # noqa: F401
from torchmetrics.classification.iou import IoU # noqa: F401
Expand Down
53 changes: 51 additions & 2 deletions torchmetrics/classification/f_beta.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from typing import Any, Callable, Optional
from warnings import warn

import torch
from torch import Tensor
Expand Down Expand Up @@ -174,7 +175,7 @@ def compute(self) -> Tensor:
return _fbeta_compute(tp, fp, tn, fn, self.beta, self.ignore_index, self.average, self.mdmc_reduce)


class F1(FBeta):
class F1Score(FBeta):
"""Computes F1 metric. F1 metrics correspond to a harmonic mean of the precision and recall scores.
Works with binary, multiclass, and multilabel data. Accepts logits or probabilities from a model
Expand Down Expand Up @@ -260,6 +261,54 @@ class F1(FBeta):
will be used to perform the allgather.
Example:
>>> from torchmetrics import F1Score
>>> target = torch.tensor([0, 1, 2, 0, 1, 2])
>>> preds = torch.tensor([0, 2, 1, 0, 0, 1])
>>> f1 = F1Score(num_classes=3)
>>> f1(preds, target)
tensor(0.3333)
"""

is_differentiable = False
higher_is_better = True

def __init__(
self,
num_classes: Optional[int] = None,
threshold: float = 0.5,
average: str = "micro",
mdmc_average: Optional[str] = None,
ignore_index: Optional[int] = None,
top_k: Optional[int] = None,
multiclass: Optional[bool] = None,
compute_on_step: bool = True,
dist_sync_on_step: bool = False,
process_group: Optional[Any] = None,
dist_sync_fn: Callable = None,
) -> None:
super().__init__(
num_classes=num_classes,
beta=1.0,
threshold=threshold,
average=average,
mdmc_average=mdmc_average,
ignore_index=ignore_index,
top_k=top_k,
multiclass=multiclass,
compute_on_step=compute_on_step,
dist_sync_on_step=dist_sync_on_step,
process_group=process_group,
dist_sync_fn=dist_sync_fn,
)


class F1(F1Score):
"""Computes F1 metric. F1 metrics correspond to a harmonic mean of the precision and recall scores.
.. deprecated:: v0.7
Use :class:`torchmetrics.F1Score`. Will be removed in v0.8.
Example:
>>> from torchmetrics import F1
>>> target = torch.tensor([0, 1, 2, 0, 1, 2])
Expand All @@ -286,9 +335,9 @@ def __init__(
process_group: Optional[Any] = None,
dist_sync_fn: Callable = None,
) -> None:
warn("`F1` was renamed to `F1Score` in v0.7 and it will be removed in v0.8", DeprecationWarning)
super().__init__(
num_classes=num_classes,
beta=1.0,
threshold=threshold,
average=average,
mdmc_average=mdmc_average,
Expand Down
3 changes: 2 additions & 1 deletion torchmetrics/functional/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from torchmetrics.functional.classification.cohen_kappa import cohen_kappa
from torchmetrics.functional.classification.confusion_matrix import confusion_matrix
from torchmetrics.functional.classification.dice import dice_score
from torchmetrics.functional.classification.f_beta import f1, fbeta
from torchmetrics.functional.classification.f_beta import f1, f1_score, fbeta
from torchmetrics.functional.classification.hamming_distance import hamming_distance
from torchmetrics.functional.classification.hinge import hinge
from torchmetrics.functional.classification.iou import iou # noqa: F401
Expand Down Expand Up @@ -93,6 +93,7 @@
"dice_score",
"explained_variance",
"f1",
"f1_score",
"fbeta",
"hamming_distance",
"hinge",
Expand Down
2 changes: 1 addition & 1 deletion torchmetrics/functional/classification/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from torchmetrics.functional.classification.cohen_kappa import cohen_kappa # noqa: F401
from torchmetrics.functional.classification.confusion_matrix import confusion_matrix # noqa: F401
from torchmetrics.functional.classification.dice import dice_score # noqa: F401
from torchmetrics.functional.classification.f_beta import f1, fbeta # noqa: F401
from torchmetrics.functional.classification.f_beta import f1, f1_score, fbeta # noqa: F401
from torchmetrics.functional.classification.hamming_distance import hamming_distance # noqa: F401
from torchmetrics.functional.classification.hinge import hinge # noqa: F401
from torchmetrics.functional.classification.jaccard import jaccard_index # noqa: F401
Expand Down
33 changes: 31 additions & 2 deletions torchmetrics/functional/classification/f_beta.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from typing import Optional
from warnings import warn

import torch
from torch import Tensor
Expand Down Expand Up @@ -243,7 +244,7 @@ def fbeta(
return _fbeta_compute(tp, fp, tn, fn, beta, ignore_index, average, mdmc_average)


def f1(
def f1_score(
preds: Tensor,
target: Tensor,
beta: float = 1.0,
Expand Down Expand Up @@ -341,11 +342,39 @@ def f1(
- If ``average in ['none', None]``, the shape will be ``(C,)``, where ``C`` stands for the number
of classes
Example:
>>> from torchmetrics.functional import f1_score
>>> target = torch.tensor([0, 1, 2, 0, 1, 2])
>>> preds = torch.tensor([0, 2, 1, 0, 0, 1])
>>> f1_score(preds, target, num_classes=3)
tensor(0.3333)
"""
return fbeta(preds, target, 1.0, average, mdmc_average, ignore_index, num_classes, threshold, top_k, multiclass)


def f1(
preds: Tensor,
target: Tensor,
beta: float = 1.0,
average: str = "micro",
mdmc_average: Optional[str] = None,
ignore_index: Optional[int] = None,
num_classes: Optional[int] = None,
threshold: float = 0.5,
top_k: Optional[int] = None,
multiclass: Optional[bool] = None,
) -> Tensor:
"""Computes F1 metric. F1 metrics correspond to a equally weighted average of the precision and recall scores.
.. deprecated:: v0.7
Use :class:`torchmetrics.functional.f1_score`. Will be removed in v0.8.
Example:
>>> from torchmetrics.functional import f1
>>> target = torch.tensor([0, 1, 2, 0, 1, 2])
>>> preds = torch.tensor([0, 2, 1, 0, 0, 1])
>>> f1(preds, target, num_classes=3)
tensor(0.3333)
"""
return fbeta(preds, target, 1.0, average, mdmc_average, ignore_index, num_classes, threshold, top_k, multiclass)
warn("`f1` was renamed to `f1_score` in v0.7 and it will be removed in v0.8", DeprecationWarning)
return f1_score(preds, target, 1.0, average, mdmc_average, ignore_index, num_classes, threshold, top_k, multiclass)

0 comments on commit c20860a

Please sign in to comment.