Source code for discotime.metrics.ipa

from typing import Optional
import numpy as np
import numpy.typing as npt
from discotime.metrics import BrierScore


[docs]class IPA: """Index of prediction accuracy (IPA) for right-censored survival models. In the context of survival analysis, the IPA is also known as the Brier skill score (BSS). """ def __init__( self, timepoints: npt.NDArray[np.float_], causes: Optional[list[int]] = None, integrate: bool = True, ) -> None: """ Args: timepoints: sequence of `t` timepoints to evaluate. causes: causes for which the brier score is calculated. integrate: should the time-dependent IPA be integrated? (default: True) """ self.timepoints = np.asanyarray(timepoints) self.brier_score = BrierScore(self.timepoints, causes) self.integrate = integrate def __call__( self, estimates: npt.NDArray[np.floating], time: npt.NDArray[np.floating], event: npt.NDArray[np.integer], ) -> np.float_: """Calculate the index of prediction accuracy. Args: estimates: array[batch, timepoints, cause] model estimates of cause probabilities. time: observed follow-up. event: event indicator at time with 0 as censoring. If there are multiple timepoints to consider, then the IPA is numerically integrated using the trapezoidal method. """ bs = self.brier_score(estimates, time, event) with np.errstate(divide="ignore"): ipa = 1 - (bs.model / bs.null) ipa = np.nan_to_num(ipa, neginf=0, posinf=0) if len(self.timepoints) > 1 and self.integrate: scaling = 1 / (max(self.timepoints) - min(self.timepoints)) ipa = np.trapz(ipa, self.timepoints, axis=0) * scaling return ipa