Skip to content

MeanAbsoluteError

yohou.metrics.point.MeanAbsoluteError

Bases: BasePointScorer

Mean Absolute Error metric for point forecasts.

Computes the average of absolute differences between predictions and actual values. This metric is robust to outliers and provides intuitive interpretation in the original units of the target variable.

The MAE is defined as:

\[\text{MAE} = \frac{1}{n}\\sum_{i=1}^{n}|y_i - \\hat{y}_i|\]

where \(y_i\) is the actual value, \(\\hat{y}_i\) is the predicted value, and \(n\) is the number of observations.

Parameters

Name Type Description Default
aggregation_method list of str or str

Dimensions to aggregate over. Options: - "stepwise": Aggregate across forecasting steps. - "vintagewise": Aggregate across vintages (observed times). - "componentwise": Aggregate across components, return per-timestep DataFrame - "groupwise": Aggregate across panel groups (panel data only) - "all": Aggregate across all dimensions (returns scalar). Same as ["stepwise", "vintagewise", "componentwise", "groupwise"]. Example outputs: - ["stepwise", "vintagewise"]: Per-component (and per-group) DataFrame. - "componentwise" or ["componentwise"]: Per-timestep (and per-group) DataFrame. - "groupwise" or ["groupwise"]: Per-component per-timestep DataFrame (panel aggregated). - ["stepwise", "vintagewise", "componentwise"]: Scalar (global) or per-group DataFrame (panel). - "all": Scalar float (hierarchically aggregated for panel data).

"all"
groups list of str, dict of str to float, or None

Panel group filter (list) or filter with weights (dict).

None
components list of str, dict of str to float, or None

Component filter (list) or filter with weights (dict).

None

Attributes

Name Type Description
lower_is_better bool

Always True for MAE.

Examples

>>> import polars as pl
>>> from datetime import datetime
>>> from yohou.metrics import MeanAbsoluteError
>>> y_true = pl.DataFrame({
...     "time": [datetime(2020, 1, 1), datetime(2020, 1, 2), datetime(2020, 1, 3)],
...     "value": [10.0, 20.0, 30.0],
... })
>>> y_pred = pl.DataFrame({
...     "vintage_time": [datetime(2019, 12, 31)] * 3,
...     "time": [datetime(2020, 1, 1), datetime(2020, 1, 2), datetime(2020, 1, 3)],
...     "value": [12.0, 19.0, 28.0],
... })
>>> mae = MeanAbsoluteError()
>>> _ = mae.fit(y_true)
>>> mae.score(y_true, y_pred)
1.666...

Notes

  • MAE treats all errors equally regardless of direction (over or under prediction)
  • Less sensitive to outliers compared to MSE/RMSE
  • Interpretable in the same units as the target variable
  • Suitable for most forecasting tasks where outliers should not dominate

See Also

Source Code

Show/Hide source
class MeanAbsoluteError(BasePointScorer):
    r"""Mean Absolute Error metric for point forecasts.

    Computes the average of absolute differences between predictions and actual values.
    This metric is robust to outliers and provides intuitive interpretation in the
    original units of the target variable.

    The MAE is defined as:

    $$\text{MAE} = \frac{1}{n}\\sum_{i=1}^{n}|y_i - \\hat{y}_i|$$

    where $y_i$ is the actual value, $\\hat{y}_i$ is the predicted value, and
    $n$ is the number of observations.

    Parameters
    ----------
    aggregation_method : list of str or str, default="all"
        Dimensions to aggregate over. Options:
        - "stepwise": Aggregate across forecasting steps.
        - "vintagewise": Aggregate across vintages (observed times).
        - "componentwise": Aggregate across components, return per-timestep DataFrame
        - "groupwise": Aggregate across panel groups (panel data only)
        - "all": Aggregate across all dimensions (returns scalar). Same as
          ["stepwise", "vintagewise", "componentwise", "groupwise"].
        Example outputs:
        - ["stepwise", "vintagewise"]: Per-component (and per-group) DataFrame.
        - "componentwise" or ["componentwise"]: Per-timestep (and per-group) DataFrame.
        - "groupwise" or ["groupwise"]: Per-component per-timestep DataFrame (panel aggregated).
        - ["stepwise", "vintagewise", "componentwise"]: Scalar (global) or per-group DataFrame (panel).
        - "all": Scalar float (hierarchically aggregated for panel data).
    groups : list of str, dict of str to float, or None, default=None
        Panel group filter (list) or filter with weights (dict).
    components : list of str, dict of str to float, or None, default=None
        Component filter (list) or filter with weights (dict).

    Attributes
    ----------
    lower_is_better : bool
        Always True for MAE.

    Examples
    --------
    >>> import polars as pl
    >>> from datetime import datetime
    >>> from yohou.metrics import MeanAbsoluteError
    >>> y_true = pl.DataFrame({
    ...     "time": [datetime(2020, 1, 1), datetime(2020, 1, 2), datetime(2020, 1, 3)],
    ...     "value": [10.0, 20.0, 30.0],
    ... })
    >>> y_pred = pl.DataFrame({
    ...     "vintage_time": [datetime(2019, 12, 31)] * 3,
    ...     "time": [datetime(2020, 1, 1), datetime(2020, 1, 2), datetime(2020, 1, 3)],
    ...     "value": [12.0, 19.0, 28.0],
    ... })
    >>> mae = MeanAbsoluteError()
    >>> _ = mae.fit(y_true)
    >>> mae.score(y_true, y_pred)  # doctest: +ELLIPSIS
    1.666...

    Notes
    -----
    - MAE treats all errors equally regardless of direction (over or under prediction)
    - Less sensitive to outliers compared to MSE/RMSE
    - Interpretable in the same units as the target variable
    - Suitable for most forecasting tasks where outliers should not dominate

    See Also
    --------
    - [`MeanSquaredError`][yohou.metrics.point.MeanSquaredError] : Mean Squared Error, more sensitive to large errors
    - [`RootMeanSquaredError`][yohou.metrics.point.RootMeanSquaredError] : Root Mean Squared Error, MeanSquaredError in original units
    - [`RootMeanSquaredScaledError`][yohou.metrics.point.RootMeanSquaredScaledError] : Root Mean Squared Scaled Error, scale-independent version
    - [`MeanAbsolutePercentageError`][yohou.metrics.point.MeanAbsolutePercentageError] : Mean Absolute Percentage Error, scale-independent

    """

    _parameter_constraints: dict = {
        **BasePointScorer._parameter_constraints,
    }

    _metric_name = "mae"

    def __init__(
        self,
        aggregation_method: list[str] | str = "all",
        groups: list[str] | dict[str, float] | None = None,
        components: list[str] | dict[str, float] | None = None,
    ) -> None:
        super().__init__(
            aggregation_method=aggregation_method,
            groups=groups,
            components=components,
        )

    def _compute_raw_errors(self, y_truth: pl.DataFrame, y_pred: pl.DataFrame) -> pl.DataFrame:
        """Compute per-row absolute errors."""
        return (y_truth - y_pred).select(pl.all().abs())

Tutorials

The following example notebooks use this component:

  • How to Tune Fourier Seasonality Terms


    Data-Features

    Explore how Fourier harmonic count affects seasonal fit quality, compare Fourier vs Pattern seasonality, and tune harmonics jointly with GridSearchCV.

    View · Open in marimo

  • How to Aggregate Scorer Results


    Evaluation-Search

    Demonstrate all scorer aggregation strategies (stepwise, vintagewise, componentwise, groupwise, coveragewise, all) on panel data with weighted group aggregation.

    View · Open in marimo

  • How to Forecast with CatBoost


    Forecasting-Models

    Plug CatBoostRegressor into PointReductionForecaster as a drop-in sklearn estimator, compare gradient-boosted versus Ridge linear baseline, and demonstrate the direct reduction strategy with tree-based models.

    View · Open in marimo

  • How to Choose a Decomposition Strategy


    Forecasting-Models

    Build 2- and 3-component DecompositionPipeline forecasters chaining trend, seasonality, and residual models with target pre-transformation.

    View · Open in marimo

  • How to Use Lagged Forecasts as Features


    Forecasting-Models

    Compare ForecastedFeatureForecaster strategies (actual, predicted, rewind) and split ratio tuning for chaining feature and target forecasters.

    View · Open in marimo

  • How to Choose a Forecasting Method


    Getting-Started

    Interactive decision guide progressing from SeasonalNaive baseline through linear reduction, stationarity transforms, feature enrichment, nonlinear models, decomposition, and prediction intervals.

    View · Open in marimo

  • How to Create a Custom Estimator


    Getting-Started

    Implement a LastValueForecaster from scratch, validate it with the check generator, and use it in a forecast pipeline.

    View · Open in marimo

  • Panel Data Forecasting


    Getting-Started

    Forecast multiple related time series simultaneously using the __ naming convention, LocalPanelForecaster, and per-group scoring.

    View · Open in marimo

  • How to Run Panel Cross-Validation


    Panel-Data

    Time series cross-validation on panel data with GridSearchCV, selective group observation, rewind operations, and groupwise performance comparison.

    View · Open in marimo