Skip to content

Commit

Permalink
Fix/RegressionEnsemble with single model regressor and coef access in…
Browse files Browse the repository at this point in the history
… LinearRegressionModel (#2205)

* fix: overwrite the self.model attribute with the model container

* fix: prevent creation of RegressionEnsemble with a regression model created with multi_models=False

* update changelog

* Update darts/models/forecasting/regression_ensemble_model.py

Co-authored-by: Dennis Bader <dennis.bader@gmx.ch>

* rephrasing changelog

* fix: enforce multi_models=True when ocl=1

---------

Co-authored-by: Dennis Bader <dennis.bader@gmx.ch>
  • Loading branch information
madtoinou and dennisbader authored Feb 5, 2024
1 parent 1d7d854 commit 5b05d2b
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ but cannot always guarantee backwards compatibility. Changes that may **break co
- Added option to exclude some `group_cols` from being added as static covariates when using `TimeSeries.from_group_dataframe()` with parameter `drop_group_cols`.

**Fixed**
- Fixed a bug in probabilistic `LinearRegressionModel.fit()`, where the `model` attribute was not pointing to all underlying estimators. [#2205](https://github.com/unit8co/darts/pull/2205) by [Antoine Madrona](https://github.com/madtoinou).
- Raise an error in `RegressionEsembleModel` when the `regression_model` was created with `multi_models=False` (not supported). [#2205](https://github.com/unit8co/darts/pull/2205) by [Antoine Madrona](https://github.com/madtoinou).
- Fixed a bug in `coefficient_of_variaton()` with `intersect=True`, where the coefficient was not computed on the intersection. [#2202](https://github.com/unit8co/darts/pull/2202) by [Antoine Madrona](https://github.com/madtoinou).

### For developers of the library:
Expand Down
4 changes: 4 additions & 0 deletions darts/models/forecasting/linear_regression_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ def fit(

for quantile in self.quantiles:
self.kwargs["quantile"] = quantile
# assign the Quantile regressor to self.model to leverage existing logic
self.model = QuantileRegressor(**self.kwargs)
super().fit(
series=series,
Expand All @@ -256,6 +257,9 @@ def fit(

self._model_container[quantile] = self.model

# replace the last trained QuantileRegressor with the dictionnary of Regressors.
self.model = self._model_container

return self

else:
Expand Down
5 changes: 5 additions & 0 deletions darts/models/forecasting/regression_ensemble_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ def __init__(
lags=None, lags_future_covariates=[0], fit_intercept=False
)
elif isinstance(regression_model, RegressionModel):
raise_if_not(
regression_model.multi_models,
"Cannot use `regression_model` that was created with `multi_models = False`.",
logger,
)
regression_model = regression_model
else:
# scikit-learn like model
Expand Down
2 changes: 1 addition & 1 deletion darts/models/forecasting/regression_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ def encode_year(idx):
self.lags: Dict[str, List[int]] = {}
self.component_lags: Dict[str, Dict[str, List[int]]] = {}
self.input_dim = None
self.multi_models = multi_models
self.multi_models = True if multi_models or output_chunk_length == 1 else False
self._considers_static_covariates = use_static_covariates
self._static_covariates_shape: Optional[Tuple[int, int]] = None
self._lagged_feature_names: Optional[List[str]] = None
Expand Down
25 changes: 25 additions & 0 deletions darts/tests/models/forecasting/test_regression_ensemble_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -884,6 +884,31 @@ def test_predict_likelihood_parameters_multivariate_regression_ensemble(self):
pred_ens["linear_q0.05"].values() < pred_ens["linear_q0.50"].values()
) and all(pred_ens["linear_q0.50"].values() < pred_ens["linear_q0.95"].values())

def test_wrong_model_creation_params(self):
"""Since `multi_models=False` requires to shift the regression model lags in the past (outside of the forecasting
model predictions), it is not supported."""
forcasting_models = [
self.get_deterministic_global_model(2),
self.get_deterministic_global_model([-5, -7]),
]
RegressionEnsembleModel(
forecasting_models=forcasting_models,
regression_train_n_points=10,
regression_model=LinearRegressionModel(
lags_future_covariates=[0], output_chunk_length=2, multi_models=True
),
)
with pytest.raises(ValueError):
RegressionEnsembleModel(
forecasting_models=forcasting_models,
regression_train_n_points=10,
regression_model=LinearRegressionModel(
lags_future_covariates=[0],
output_chunk_length=2,
multi_models=False,
),
)

@staticmethod
def get_probabilistic_global_model(
lags: Union[int, List[int]],
Expand Down

0 comments on commit 5b05d2b

Please sign in to comment.