Shortcuts

Source code for torcheval.metrics.regression.r2_score

# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

# pyre-ignore-all-errors[16]: Undefined attribute of metric states.

from typing import Iterable, Optional, TypeVar

import torch

from torcheval.metrics.functional.regression.r2_score import (
    _r2_score_compute,
    _r2_score_param_check,
    _r2_score_update,
)
from torcheval.metrics.metric import Metric

TR2Score = TypeVar("TR2Score")


[docs]class R2Score(Metric[torch.Tensor]): """ Compute R-squared score, which is the proportion of variance in the dependent variable that can be explained by the independent variable. Its functional version is :func:`torcheval.metrics.functional.r2_score`. Args: multioutput (str, Optional): - ``'uniform_average'`` [default]: Return scores of all outputs are averaged with uniform weight. - ``'raw_values'``: Return a full set of scores. - ``variance_weighted``: Return scores of all outputs are averaged with weighted by the variances of each individual output. num_regressors (int, Optional): Number of independent variables used, applied to adjusted R-squared score. Defaults to zero (standard R-squared score). Raises: ValueError: - If value of multioutput does not exist in (``raw_values``, ``uniform_average``, ``variance_weighted``). - If value of num_regressors is not an ``integer`` in the range of [0, n_samples - 1]. Examples:: >>> import torch >>> from torcheval.metrics import R2Score >>> metric = R2Score() >>> input = torch.tensor([0, 2, 1, 3]) >>> target = torch.tensor([0, 1, 2, 3]) >>> metric.update(input, target) >>> metric.compute() tensor(0.6) >>> metric = R2Score() >>> input = torch.tensor([[0, 2], [1, 6]]) >>> target = torch.tensor([[0, 1], [2, 5]]) >>> metric.update(input, target) >>> metric.compute() tensor(0.6250) >>> metric = R2Score(multioutput="raw_values") >>> input = torch.tensor([[0, 2], [1, 6]]) >>> target = torch.tensor([[0, 1], [2, 5]]) >>> metric.update(input, target) >>> metric.compute() tensor([0.5000, 0.7500]) >>> metric = R2Score(multioutput="variance_weighted") >>> input = torch.tensor([[0, 2], [1, 6]]) >>> target = torch.tensor([[0, 1], [2, 5]]) >>> metric.update(input, target) >>> metric.compute() tensor(0.7000) >>> metric = R2Score(multioutput="raw_values", num_regressors=2) >>> input = torch.tensor([1.2, 2.5, 3.6, 4.5, 6]) >>> target = torch.tensor([1, 2, 3, 4, 5]) >>> metric.update(input, target) >>> metric.compute() tensor(0.6200) """
[docs] def __init__( self: TR2Score, *, multioutput: str = "uniform_average", num_regressors: int = 0, device: Optional[torch.device] = None, ) -> None: super().__init__(device=device) _r2_score_param_check(multioutput, num_regressors) self.multioutput = multioutput self.num_regressors = num_regressors self._add_state("sum_squared_obs", torch.tensor(0.0, device=self.device)) self._add_state("sum_obs", torch.tensor(0.0, device=self.device)) self._add_state( "sum_squared_residual", torch.tensor(0.0, device=self.device), ) self._add_state("num_obs", torch.tensor(0.0, device=self.device))
@torch.inference_mode() # pyre-ignore[14]: inconsistent override on *_:Any, **__:Any def update( self: TR2Score, input: torch.Tensor, target: torch.Tensor, ) -> TR2Score: """ Update states with the ground truth values and predictions. Args: input (Tensor): Tensor of predicted values with shape of (n_sample, n_output). target (Tensor): Tensor of ground truth values with shape of (n_sample, n_output). """ ( sum_squared_obs, sum_obs, sum_squared_residual, num_obs, ) = _r2_score_update(input, target) if self.sum_squared_obs.ndim == 0 and sum_squared_obs.ndim == 1: self.sum_squared_obs = sum_squared_obs self.sum_obs = sum_obs self.sum_squared_residual = sum_squared_residual else: self.sum_squared_obs += sum_squared_obs self.sum_obs += sum_obs self.sum_squared_residual += sum_squared_residual self.num_obs += num_obs return self @torch.inference_mode() def compute(self: TR2Score) -> torch.Tensor: """ Return the R-squared score. NaN is returned if no calls to ``update()`` are made before ``compute()`` is called. """ return _r2_score_compute( self.sum_squared_obs, self.sum_obs, self.sum_squared_residual, self.num_obs, self.multioutput, self.num_regressors, ) @torch.inference_mode() def merge_state(self: TR2Score, metrics: Iterable[TR2Score]) -> TR2Score: for metric in metrics: if self.sum_squared_obs.ndim == 0 and metric.sum_squared_obs.ndim == 1: self.sum_squared_obs = metric.sum_squared_obs.to(self.device) self.sum_obs = metric.sum_obs.to(self.device) self.sum_squared_residual = metric.sum_squared_residual.to(self.device) else: self.sum_squared_obs += metric.sum_squared_obs.to(self.device) self.sum_obs += metric.sum_obs.to(self.device) self.sum_squared_residual += metric.sum_squared_residual.to(self.device) self.num_obs += metric.num_obs.to(self.device) return self

Docs

Access comprehensive developer documentation for PyTorch

View Docs

Tutorials

Get in-depth tutorials for beginners and advanced developers

View Tutorials

Resources

Find development resources and get your questions answered

View Resources