symmetric_mape.py 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. # Copyright The Lightning team.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. from typing import Union
  15. import torch
  16. from torch import Tensor
  17. from torchmetrics.utilities.checks import _check_same_shape
  18. def _symmetric_mean_absolute_percentage_error_update(
  19. preds: Tensor,
  20. target: Tensor,
  21. epsilon: float = 1.17e-06,
  22. ) -> tuple[Tensor, int]:
  23. """Update and returns variables required to compute Symmetric Mean Absolute Percentage Error.
  24. Check for same shape of input tensors.
  25. Args:
  26. preds: Predicted tensor
  27. target: Ground truth tensor
  28. epsilon: Avoids ``ZeroDivisionError``.
  29. """
  30. _check_same_shape(preds, target)
  31. abs_diff = torch.abs(preds - target)
  32. abs_per_error = abs_diff / torch.clamp(torch.abs(target) + torch.abs(preds), min=epsilon)
  33. sum_abs_per_error = 2 * torch.sum(abs_per_error)
  34. num_obs = target.numel()
  35. return sum_abs_per_error, num_obs
  36. def _symmetric_mean_absolute_percentage_error_compute(sum_abs_per_error: Tensor, num_obs: Union[int, Tensor]) -> Tensor:
  37. """Compute Symmetric Mean Absolute Percentage Error.
  38. Args:
  39. sum_abs_per_error: Sum of values of symmetric absolute percentage errors over all observations
  40. ``(symmetric absolute percentage error = 2 * |target - prediction| / (target + prediction))``
  41. num_obs: Number of predictions or observations
  42. Example:
  43. >>> target = torch.tensor([1, 10, 1e6])
  44. >>> preds = torch.tensor([0.9, 15, 1.2e6])
  45. >>> sum_abs_per_error, num_obs = _symmetric_mean_absolute_percentage_error_update(preds, target)
  46. >>> _symmetric_mean_absolute_percentage_error_compute(sum_abs_per_error, num_obs)
  47. tensor(0.2290)
  48. """
  49. return sum_abs_per_error / num_obs
  50. def symmetric_mean_absolute_percentage_error(preds: Tensor, target: Tensor) -> Tensor:
  51. r"""Compute symmetric mean absolute percentage error (SMAPE_).
  52. .. math:: \text{SMAPE} = \frac{2}{n}\sum_1^n\frac{| y_i - \hat{y_i} |}{max(| y_i | + | \hat{y_i} |, \epsilon)}
  53. Where :math:`y` is a tensor of target values, and :math:`\hat{y}` is a tensor of predictions.
  54. Args:
  55. preds: estimated labels
  56. target: ground truth labels
  57. Return:
  58. Tensor with SMAPE.
  59. Example:
  60. >>> from torchmetrics.functional.regression import symmetric_mean_absolute_percentage_error
  61. >>> target = torch.tensor([1, 10, 1e6])
  62. >>> preds = torch.tensor([0.9, 15, 1.2e6])
  63. >>> symmetric_mean_absolute_percentage_error(preds, target)
  64. tensor(0.2290)
  65. """
  66. sum_abs_per_error, num_obs = _symmetric_mean_absolute_percentage_error_update(
  67. preds,
  68. target,
  69. )
  70. return _symmetric_mean_absolute_percentage_error_compute(
  71. sum_abs_per_error,
  72. num_obs,
  73. )