\[ \newcommand{\F}{\mathbb{F}} \newcommand{\R}{\mathbb{R}} \newcommand{\v}{\mathbf{v}} \newcommand{\a}{\mathbf{a}} \newcommand{\b}{\mathbf{b}} \newcommand{\c}{\mathbf{c}} \newcommand{\x}{\mathbf{x}} \newcommand{\y}{\mathbf{y}} \newcommand{\yhat}{\mathbf{\hat{y}}} \newcommand{\0}{\mathbf{0}} \newcommand{\1}{\mathbf{1}} \]

Mean Absolute Percentage Error#

This is a metric that measures the relative error and hence an intuitive metric.

Definition (Mean Absolute Percentage Error)#

Given a dataset of \(n\) samples indexed by the tuple pair \((x_i, y_i)\), the mean absolute percentage error (MAPE) is defined as:

\[ \textbf{MAPE} = \dfrac{1}{n} \dfrac{\sum_{i=1}^n |\hat{y}_i - y_i|}{\max(\epsilon, |y_i|)} \]

where \(\epsilon\) is an arbitarily small and positive number in case the ground truth \(y_i\) is \(0\).

Implementation of MAPE#

import numpy as np

def mean_absolute_percentage_error_(
    y_true: np.ndarray, y_pred: np.ndarray, epsilon: float = 1e-5
) -> float:
    """Mean absolute percentage error (MAPE) regression loss.

    Note:
        Loss can be extremely high when `y_true` is near 0 since the denominator
        will be epislon, and np.abs(y_true - y_pred) / epislon will be very large.

    Args:
        y_true (np.ndarray): Ground truth (correct) target values.
        y_pred (np.ndarray): Estimated target values.
        epsilon (float, optional): An arbitrarily small positive number for numerical stability
                                   in case y_true is 0 or near 0. Defaults to 1e-5.

    Shape:
        y_true: (n_samples, )
        y_pred: (n_samples, )

    Returns:
        loss (float): The mean absolute percentage error.

    Examples:
        >>> y_true = [3, -0.5, 2, 7]
        >>> y_pred = [2.5, 0.0, 2, 8]
        >>> mean_absolute_percentage_error_(y_true, y_pred)
        0.3273...
    """

    y_true = np.asarray(y_true).flatten()
    y_pred = np.asarray(y_pred).flatten()
    print(np.maximum.outer(y_true, epsilon))
    loss = np.mean(
        np.abs((y_true - y_pred) / np.maximum.outer(np.abs(y_true), epsilon))
    )
    return loss
>>> y_true = [3, -0.5, 2, 7]
>>> y_pred = [2.5, 0.0, 2, 8]
>>> mean_absolute_percentage_error_(y_true, y_pred)
[3.e+00 1.e-05 2.e+00 7.e+00]
0.3273809523809524