Files
2026-07-13 12:35:17 +08:00

74 lines
2.8 KiB
Python

import torch
import torchmetrics
from torch import Tensor
class RawCurveAccuracy(torchmetrics.Metric):
def __init__(self, *, tolerance, **kwargs):
super().__init__(**kwargs)
self.tolerance = tolerance
self.add_state('close', default=torch.tensor(0, dtype=torch.int), dist_reduce_fx='sum')
self.add_state('total', default=torch.tensor(0, dtype=torch.int), dist_reduce_fx='sum')
def update(self, pred: Tensor, target: Tensor, mask=None) -> None:
"""
:param pred: predicted curve
:param target: reference curve
:param mask: valid or non-padding mask
"""
if mask is None:
assert pred.shape == target.shape, f'shapes of pred and target mismatch: {pred.shape}, {target.shape}'
else:
assert pred.shape == target.shape == mask.shape, \
f'shapes of pred, target and mask mismatch: {pred.shape}, {target.shape}, {mask.shape}'
close = torch.abs(pred - target) <= self.tolerance
if mask is not None:
close &= mask
self.close += close.sum()
self.total += pred.numel() if mask is None else mask.sum()
def compute(self) -> Tensor:
return self.close / self.total
class RawCurveR2Score(torchmetrics.Metric):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.add_state('sum_squared_error', default=torch.tensor(0.0), dist_reduce_fx='sum')
self.add_state('sum_error', default=torch.tensor(0.0), dist_reduce_fx='sum')
self.add_state('residual', default=torch.tensor(0.0), dist_reduce_fx='sum')
self.add_state('total', default=torch.tensor(0), dist_reduce_fx='sum')
def update(self, pred: Tensor, target: Tensor, mask=None) -> None:
"""
:param pred: predicted curve
:param target: reference curve
:param mask: valid or non-padding mask
"""
if mask is None:
assert pred.shape == target.shape, f'shapes of pred and target mismatch: {pred.shape}, {target.shape}'
else:
assert pred.shape == target.shape == mask.shape, \
f'shapes of pred, target and mask mismatch: {pred.shape}, {target.shape}, {mask.shape}'
pred = pred[mask]
target = target[mask]
pred = pred.flatten()
target = target.flatten()
sum_error = torch.sum(target)
sum_squared_error = torch.sum(target * target)
residual = target - pred
rss = torch.sum(residual * residual)
total = target.numel() if mask is None else mask.sum()
self.sum_squared_error += sum_squared_error
self.sum_error += sum_error
self.residual += rss
self.total += total
def compute(self) -> Tensor:
return 1 - self.residual / (self.sum_squared_error - self.sum_error ** 2 / self.total)