@@ -663,6 +663,40 @@ def kullback_leibler_divergence(y_true: np.ndarray, y_pred: np.ndarray) -> float
663663 return np .sum (kl_loss )
664664
665665
666+ def mean_absolute_percentage_error (
667+ y_true : np .ndarray , y_pred : np .ndarray , epsilon : float = 1e-15
668+ ) -> float :
669+ """
670+ Calculate the Mean Absolute Percentage Error (MAPE) between y_true and y_pred.
671+ MAPE is calculated by dividing the absolute error by the absolute value of
672+ the actual measurement and then averaging.
673+ SMAPE = (1/n) * Σ( |y_true - y_pred| / |y_true|)
674+ Reference:
675+ https://en.wikipedia.org/wiki/Mean_absolute_percentage_error
676+ Parameters:
677+ - y_true: The true values (ground truth)
678+ - y_pred: The predicted values
679+ - epsilon: Small constant to avoid division by zero
680+ >>> true_values = np.array([100, 200, 300, 400])
681+ >>> predicted_values = np.array([110, 190, 310, 420])
682+ >>> float(symmetric_mean_absolute_percentage_error(true_values, predicted_values))
683+ 0.058333333333333334
684+ >>> true_labels = np.array([100, 200, 300])
685+ >>> predicted_probs = np.array([110, 190, 310, 420])
686+ >>> symmetric_mean_absolute_percentage_error(true_labels, predicted_probs)
687+ Traceback (most recent call last):
688+ ...
689+ ValueError: Input arrays must have the same length.
690+ """
691+ if len (y_true ) != len (y_pred ):
692+ raise ValueError ("Input arrays must have the same length." )
693+
694+ denominator = np .where (np .abs (y_true ) == 0 , epsilon , np .abs (y_true ))
695+
696+ mape_loss = np .abs (y_true - y_pred ) / denominator
697+ return np .mean (mape_loss )
698+
699+
666700if __name__ == "__main__" :
667701 import doctest
668702
0 commit comments