Skip to content

check_fit_predict_without_exogenous

yohou.testing.forecaster.check_fit_predict_without_exogenous(forecaster, y, requires_exogenous=False, target_as_feature='transformed', forecasting_horizon=3)

Check forecaster behavior when X_actual=None at fit time.

Validates two clear-cut scenarios based on requires_exogenous tag and target_as_feature parameter:

  • requires_exogenous=False: fit(y, X_actual=None) succeeds and predict() returns valid output.
  • requires_exogenous=True + target_as_feature=None: fit(y, X_actual=None) raises ValueError.

When requires_exogenous=True and target_as_feature is not None, the check is skipped because behaviour depends on the specific forecaster (some compositions always require X_actual).

Parameters

Name Type Description Default
forecaster BaseForecaster

Fitted forecaster instance (will be cloned).

required
y DataFrame

Target time series with "time" column.

required
requires_exogenous bool

Value of the requires_exogenous forecaster tag.

False
target_as_feature str or None

Value of the target_as_feature forecaster parameter.

"transformed"
forecasting_horizon int

Forecasting horizon to use for fit/predict.

3

Source Code

Show/Hide source
def check_fit_predict_without_exogenous(
    forecaster,
    y: pl.DataFrame,
    requires_exogenous: bool = False,
    target_as_feature: str | None = "transformed",
    forecasting_horizon: int = 3,
) -> None:
    """Check forecaster behavior when X_actual=None at fit time.

    Validates two clear-cut scenarios based on ``requires_exogenous`` tag
    and ``target_as_feature`` parameter:

    * ``requires_exogenous=False``: fit(y, X_actual=None) succeeds and predict()
      returns valid output.
    * ``requires_exogenous=True`` + ``target_as_feature=None``:
      fit(y, X_actual=None) raises ``ValueError``.

    When ``requires_exogenous=True`` and ``target_as_feature`` is not
    ``None``, the check is skipped because behaviour depends on the
    specific forecaster (some compositions always require X_actual).

    Parameters
    ----------
    forecaster : BaseForecaster
        Fitted forecaster instance (will be cloned).
    y : pl.DataFrame
        Target time series with ``"time"`` column.
    requires_exogenous : bool, default=False
        Value of the ``requires_exogenous`` forecaster tag.
    target_as_feature : str or None, default="transformed"
        Value of the ``target_as_feature`` forecaster parameter.
    forecasting_horizon : int, default=3
        Forecasting horizon to use for fit/predict.

    """
    forecaster_clone = clone(forecaster)
    name = forecaster_clone.__class__.__name__

    if not requires_exogenous:
        # Forecasters that don't require exogenous must succeed with X_actual=None
        forecaster_clone.fit(y, X_actual=None, forecasting_horizon=forecasting_horizon)
        y_pred = forecaster_clone.predict(forecasting_horizon=forecasting_horizon)
        assert isinstance(y_pred, pl.DataFrame), (
            f"{name}.predict() must return pl.DataFrame after fit(y, X_actual=None), got {type(y_pred).__name__}"
        )
        assert "time" in y_pred.columns, (
            f"{name}.predict() output must contain 'time' column after fit(y, X_actual=None)"
        )
    elif target_as_feature is None:
        # target_as_feature=None and requires_exogenous=True → must raise
        try:
            forecaster_clone.fit(y, X_actual=None, forecasting_horizon=forecasting_horizon)
            raise AssertionError(
                f"{name}.fit(y, X_actual=None) must raise ValueError when target_as_feature=None and requires_exogenous=True"
            )
        except ValueError:
            pass  # Expected