Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ but cannot always guarantee backwards compatibility. Changes that may **break co
**Improved**

**Fixed**
- Added parameter `verbose` to `ForecastingModel.fit()` that allows to control the verbosity for model fitting. Ignored if the underlying model does not support it. [#2805](https://github.com/unit8co/darts/pull/2805) by [Timon Erhart](https://github.com/turbotimon).
- Fixed a bug in `historical_forecast` where the `verbose` parameter was not propagated to the the model's `fit()` method. [#2805](https://github.com/unit8co/darts/pull/2805) by [Timon Erhart](https://github.com/turbotimon).
2805) by [Timon Erhart](https://github.com/turbotimon).

**Dependencies**

Expand Down
10 changes: 6 additions & 4 deletions darts/models/forecasting/baselines.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def __init__(self):
def supports_multivariate(self) -> bool:
return True

def fit(self, series: TimeSeries):
def fit(self, series: TimeSeries, verbose: bool = False):
super().fit(series)

self.mean_val = np.mean(series.values(copy=False), axis=0)
Expand Down Expand Up @@ -112,7 +112,7 @@ def supports_multivariate(self) -> bool:
def min_train_series_length(self):
return max(self.K, 3)

def fit(self, series: TimeSeries):
def fit(self, series: TimeSeries, verbose: bool = False):
super().fit(series)

raise_if_not(
Expand Down Expand Up @@ -167,7 +167,7 @@ def __init__(self):
def supports_multivariate(self) -> bool:
return True

def fit(self, series: TimeSeries):
def fit(self, series: TimeSeries, verbose: bool = False):
super().fit(series)
assert series.n_samples == 1, "This model expects deterministic time series"

Expand Down Expand Up @@ -235,7 +235,7 @@ def min_train_series_length(self):
def __str__(self):
return f"NaiveMovingAverage({self.input_chunk_length})"

def fit(self, series: TimeSeries):
def fit(self, series: TimeSeries, verbose: bool = False):
super().fit(series)
raise_if_not(
series.is_deterministic,
Expand Down Expand Up @@ -332,6 +332,7 @@ def fit(
past_covariates: Optional[Union[TimeSeries, Sequence[TimeSeries]]] = None,
future_covariates: Optional[Union[TimeSeries, Sequence[TimeSeries]]] = None,
sample_weight: Optional[Union[TimeSeries, Sequence[TimeSeries], str]] = None,
verbose: bool = False,
):
super().fit(
series=series,
Expand All @@ -351,6 +352,7 @@ def fit(
sample_weight=sample_weight
if model.supports_sample_weight
else None,
verbose=verbose,
)
return self

Expand Down
1 change: 1 addition & 0 deletions darts/models/forecasting/ensemble_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ def fit(
series: Union[TimeSeries, Sequence[TimeSeries]],
past_covariates: Optional[Union[TimeSeries, Sequence[TimeSeries]]] = None,
future_covariates: Optional[Union[TimeSeries, Sequence[TimeSeries]]] = None,
verbose: bool = False,
):
"""
Fits the model on the provided series.
Expand Down
2 changes: 1 addition & 1 deletion darts/models/forecasting/exponential_smoothing.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ def __init__(
self.fit_kwargs = fit_kwargs
self.model = None

def fit(self, series: TimeSeries):
def fit(self, series: TimeSeries, verbose: bool = False):
super().fit(series)
self._assert_univariate(series)
series = self.training_series
Expand Down
2 changes: 1 addition & 1 deletion darts/models/forecasting/fft.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ def _null_trend(self, x) -> Callable:
"""Helper function, used to make FFT model pickable."""
return 0

def fit(self, series: TimeSeries):
def fit(self, series: TimeSeries, verbose: bool = False):
series = fill_missing_values(series)
super().fit(series)
self._assert_univariate(series)
Expand Down
19 changes: 16 additions & 3 deletions darts/models/forecasting/forecasting_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,13 +169,15 @@ def __init__(self, *args, **kwargs):
self.encoders = self.initialize_encoders(default=True)

@abstractmethod
def fit(self, series: TimeSeries) -> "ForecastingModel":
def fit(self, series: TimeSeries, verbose=False) -> "ForecastingModel":
"""Fit/train the model on the provided series.

Parameters
----------
series
A target time series. The model will be trained to forecast this time series.
verbose
Optionally, set the fit verbosity. Not effective for all models.

Returns
-------
Expand Down Expand Up @@ -1188,6 +1190,7 @@ def retrain_func(
past_covariates=past_covariates_,
future_covariates=future_covariates_,
sample_weight=sample_weight_,
verbose=verbose,
**fit_kwargs,
)
else:
Expand Down Expand Up @@ -2950,7 +2953,7 @@ def _model_encoder_settings(
return None, None, False, False, None, None

@abstractmethod
def fit(self, series: TimeSeries) -> "LocalForecastingModel":
def fit(self, series: TimeSeries, verbose: bool = False) -> "LocalForecastingModel":
super().fit(series)
series._assert_deterministic()

Expand Down Expand Up @@ -3011,6 +3014,7 @@ def fit(
series: Union[TimeSeries, Sequence[TimeSeries]],
past_covariates: Optional[Union[TimeSeries, Sequence[TimeSeries]]] = None,
future_covariates: Optional[Union[TimeSeries, Sequence[TimeSeries]]] = None,
verbose: bool = False,
) -> "GlobalForecastingModel":
"""Fit/train the model on (potentially multiple) series.

Expand All @@ -3033,6 +3037,8 @@ def fit(
be used by some models as an input. The covariate(s) may or may not be multivariate, but if multiple
covariates are provided they must have the same number of components. If `future_covariates` is provided,
it must contain the same number of series as `series`.
verbose
Optionally, set the fit verbosity. Not effective for all models.

Returns
-------
Expand Down Expand Up @@ -3237,7 +3243,12 @@ class FutureCovariatesLocalForecastingModel(LocalForecastingModel, ABC):
All implementations must implement the :func:`_fit()` and :func:`_predict()` methods.
"""

def fit(self, series: TimeSeries, future_covariates: Optional[TimeSeries] = None):
def fit(
self,
series: TimeSeries,
future_covariates: Optional[TimeSeries] = None,
verbose: bool = False,
):
"""Fit/train the model on the (single) provided series.

Optionally, a future covariates series can be provided as well.
Expand All @@ -3250,6 +3261,8 @@ def fit(self, series: TimeSeries, future_covariates: Optional[TimeSeries] = None
A time series of future-known covariates. This time series will not be forecasted, but can be used by
some models as an input. It must contain at least the same time steps/indices as the target `series`.
If it is longer than necessary, it will be automatically trimmed.
verbose
Optionally, set the fit verbosity. Not effective for all models.

Returns
-------
Expand Down
5 changes: 5 additions & 0 deletions darts/models/forecasting/lgbm.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ def fit(
val_sample_weight: Optional[
Union[TimeSeries, Sequence[TimeSeries], str]
] = None,
verbose: bool = False,
**kwargs,
):
"""
Expand Down Expand Up @@ -300,6 +301,8 @@ def fit(
are extracted from the end of the global weights. This gives a common time weighting across all series.
val_sample_weight
Same as for `sample_weight` but for the evaluation dataset.
verbose
Optionally, set the fit verbosity. Not effective for all models.
**kwargs
Additional kwargs passed to `lightgbm.LGBRegressor.fit()`
"""
Expand All @@ -321,6 +324,7 @@ def fit(
n_jobs_multioutput_wrapper=n_jobs_multioutput_wrapper,
sample_weight=sample_weight,
val_sample_weight=val_sample_weight,
verbose=verbose,
**kwargs,
)
# store the trained model in the container as it might have been wrapped by MultiOutputRegressor
Expand All @@ -338,6 +342,7 @@ def fit(
n_jobs_multioutput_wrapper=n_jobs_multioutput_wrapper,
sample_weight=sample_weight,
val_sample_weight=val_sample_weight,
verbose=verbose,
**kwargs,
)
return self
Expand Down
3 changes: 3 additions & 0 deletions darts/models/forecasting/linear_regression_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ def fit(
max_samples_per_ts: Optional[int] = None,
n_jobs_multioutput_wrapper: Optional[int] = None,
sample_weight: Optional[Union[TimeSeries, Sequence[TimeSeries], str]] = None,
verbose: bool = False,
**kwargs,
):
likelihood = self.likelihood
Expand Down Expand Up @@ -244,6 +245,7 @@ def fit(
max_samples_per_ts=max_samples_per_ts,
n_jobs_multioutput_wrapper=n_jobs_multioutput_wrapper,
sample_weight=sample_weight,
verbose=verbose,
**kwargs,
)
# store the trained model in the container as it might have been wrapped by MultiOutputRegressor
Expand All @@ -262,6 +264,7 @@ def fit(
max_samples_per_ts=max_samples_per_ts,
n_jobs_multioutput_wrapper=n_jobs_multioutput_wrapper,
sample_weight=sample_weight,
verbose=verbose,
**kwargs,
)

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 @@ -283,6 +283,7 @@ def fit(
past_covariates: Optional[Union[TimeSeries, Sequence[TimeSeries]]] = None,
future_covariates: Optional[Union[TimeSeries, Sequence[TimeSeries]]] = None,
sample_weight: Optional[Union[TimeSeries, Sequence[TimeSeries], str]] = None,
verbose: bool = False,
):
"""
Fits the forecasting models with the entire series except the last `regression_train_n_points` values, which
Expand Down Expand Up @@ -311,6 +312,8 @@ def fit(
`"linear"` or `"exponential"` decay - the further in the past, the lower the weight. The weights are
computed globally based on the length of the longest series in `series`. Then for each series, the weights
are extracted from the end of the global weights. This gives a common time weighting across all series.
verbose
Optionally, set the fit verbosity. Not effective for all models.
"""
super().fit(
series, past_covariates=past_covariates, future_covariates=future_covariates
Expand Down Expand Up @@ -395,6 +398,7 @@ def fit(
sample_weight=sample_weight
if model.supports_sample_weight
else None,
verbose=verbose,
)

# we can call direct prediction in any case. Even if we overwrite with historical
Expand Down Expand Up @@ -442,6 +446,7 @@ def fit(
sample_weight=sample_weight
if model.supports_sample_weight
else None,
verbose=verbose,
)
return self

Expand Down
18 changes: 17 additions & 1 deletion darts/models/forecasting/sklearn_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
<https://unit8co.github.io/darts/examples/24-SKLearnClassifierModel-examples.html>`_
"""

import inspect
from abc import ABC, abstractmethod
from collections import OrderedDict
from collections.abc import Sequence
Expand Down Expand Up @@ -847,6 +848,7 @@ def _fit_model(
val_past_covariates: Optional[Sequence[TimeSeries]] = None,
val_future_covariates: Optional[Sequence[TimeSeries]] = None,
val_sample_weight: Optional[Union[Sequence[TimeSeries], str]] = None,
verbose: bool = False,
**kwargs,
):
"""
Expand Down Expand Up @@ -884,8 +886,16 @@ def _fit_model(
"`sample_weight` was ignored since underlying regression model's "
"`fit()` method does not support it."
)

# only pass "verbose" to the underlying model if it supports it
if "verbose" in inspect.signature(self.model.fit).parameters:
kwargs["verbose"] = verbose

self.model.fit(
training_samples, training_labels, **sample_weight_kwargs, **kwargs
training_samples,
training_labels,
**sample_weight_kwargs,
**kwargs,
)

# generate and store the lagged components names (for feature importance analysis)
Expand All @@ -912,6 +922,7 @@ def fit(
n_jobs_multioutput_wrapper: Optional[int] = None,
sample_weight: Optional[Union[TimeSeries, Sequence[TimeSeries], str]] = None,
stride: int = 1,
verbose: bool = False,
**kwargs,
):
"""
Expand Down Expand Up @@ -949,6 +960,8 @@ def fit(
The number of time steps between consecutive samples, applied starting from the end of the series. The same
stride will be applied to both the training and evaluation set (if supplied and supported). This should be
used with caution as it might introduce bias in the forecasts.
verbose
Optionally, set the fit verbosity. Not effective for all models.
**kwargs
Additional keyword arguments passed to the `fit` method of the model.
"""
Expand Down Expand Up @@ -1116,6 +1129,7 @@ def fit(
val_sample_weight=val_sample_weight,
max_samples_per_ts=max_samples_per_ts,
stride=stride,
verbose=verbose,
**kwargs,
)

Expand Down Expand Up @@ -1864,6 +1878,7 @@ def _fit_model(
future_covariates,
max_samples_per_ts,
sample_weight,
verbose: bool = False,
**kwargs,
):
"""
Expand Down Expand Up @@ -1893,6 +1908,7 @@ def _fit_model(
future_covariates=future_covariates,
max_samples_per_ts=max_samples_per_ts,
sample_weight=sample_weight,
verbose=verbose,
**kwargs,
)

Expand Down
4 changes: 2 additions & 2 deletions darts/models/forecasting/theta.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def __init__(
if self.theta == 0:
raise_log(ValueError("The parameter theta cannot be equal to 0."), logger)

def fit(self, series: TimeSeries):
def fit(self, series: TimeSeries, verbose: bool = False):
super().fit(series)
self._assert_univariate(series)
ts = self.training_series
Expand Down Expand Up @@ -308,7 +308,7 @@ def __init__(
logger,
)

def fit(self, series):
def fit(self, series, verbose: bool = False):
super().fit(series)

self.length = len(series)
Expand Down
7 changes: 6 additions & 1 deletion darts/models/forecasting/varima.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,12 @@ def _differentiate_series(self, series: TimeSeries) -> TimeSeries:
)
return series

def fit(self, series: TimeSeries, future_covariates: Optional[TimeSeries] = None):
def fit(
self,
series: TimeSeries,
future_covariates: Optional[TimeSeries] = None,
verbose: bool = False,
):
# for VARIMA we need to process target `series` before calling
# TransferableFutureCovariatesLocalForecastingModel's fit() method
self._last_values = (
Expand Down
5 changes: 5 additions & 0 deletions darts/models/forecasting/xgboost.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ def fit(
val_sample_weight: Optional[
Union[TimeSeries, Sequence[TimeSeries], str]
] = None,
verbose: bool = False,
**kwargs,
):
"""
Expand Down Expand Up @@ -303,6 +304,8 @@ def fit(
are extracted from the end of the global weights. This gives a common time weighting across all series.
val_sample_weight
Same as for `sample_weight` but for the evaluation dataset.
verbose
Optionally, set the fit verbosity. Not effective for all models.
**kwargs
Additional kwargs passed to `xgb.XGBRegressor.fit()`
"""
Expand All @@ -326,6 +329,7 @@ def fit(
n_jobs_multioutput_wrapper=n_jobs_multioutput_wrapper,
sample_weight=sample_weight,
val_sample_weight=val_sample_weight,
verbose=verbose,
**kwargs,
)
# store the trained model in the container as it might have been wrapped by MultiOutputRegressor
Expand All @@ -343,6 +347,7 @@ def fit(
n_jobs_multioutput_wrapper=n_jobs_multioutput_wrapper,
sample_weight=sample_weight,
val_sample_weight=val_sample_weight,
verbose=verbose,
**kwargs,
)
return self
Expand Down
Loading
Loading