Skip to content

feat: support forecast_limit_lower_bound and forecast_limit_upper_bou… #1305

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 29 commits into from
May 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
831499a
feat: support forecast_limit_lower_bound and forecast_limit_upper_bou…
rey-esp Jan 21, 2025
e5693fb
update doc string
rey-esp Jan 21, 2025
b96e942
Merge branch 'main' of github.com:googleapis/python-bigquery-datafram…
rey-esp Jan 22, 2025
d5a752e
Merge branch 'main' into b384509112-forecast-limit-bounds
rey-esp Jan 29, 2025
78ec488
Merge branch 'main' into b384509112-forecast-limit-bounds
rey-esp Jan 29, 2025
70e4cc4
Merge branch 'main' into b384509112-forecast-limit-bounds
rey-esp Jan 29, 2025
05f39de
Merge branch 'main' into b384509112-forecast-limit-bounds
rey-esp Jan 30, 2025
2370c1a
Merge branch 'main' into b384509112-forecast-limit-bounds
rey-esp Feb 6, 2025
1bee7b5
Merge branch 'main' into b384509112-forecast-limit-bounds
rey-esp Feb 10, 2025
5d4e7b7
Merge branch 'main' into b384509112-forecast-limit-bounds
rey-esp Mar 5, 2025
1aabb2a
Merge branch 'main' into b384509112-forecast-limit-bounds
rey-esp Mar 5, 2025
2f6adfd
Merge branch 'main' into b384509112-forecast-limit-bounds
rey-esp Mar 10, 2025
8238733
Merge branch 'main' into b384509112-forecast-limit-bounds
rey-esp Mar 12, 2025
d64b774
Merge branch 'main' into b384509112-forecast-limit-bounds
rey-esp Mar 12, 2025
9d2b1be
Merge branch 'b384509112-forecast-limit-bounds' of github.com:googlea…
rey-esp Mar 13, 2025
864b7e2
Merge branch 'main' into b384509112-forecast-limit-bounds
rey-esp Mar 17, 2025
bbc0a48
Update test_forecasting.py - remove upper bound
rey-esp Mar 18, 2025
eadf2d5
Merge branch 'main' into b384509112-forecast-limit-bounds
rey-esp Mar 18, 2025
5da1c08
Merge branch 'main' into b384509112-forecast-limit-bounds
rey-esp Mar 18, 2025
0fcf034
Merge branch 'main' into b384509112-forecast-limit-bounds
rey-esp Mar 25, 2025
a7b22e0
add TODO
rey-esp Mar 25, 2025
c506ea3
Merge branch 'b384509112-forecast-limit-bounds' of github.com:googlea…
rey-esp Mar 25, 2025
3d3265d
Merge branch 'main' into b384509112-forecast-limit-bounds
rey-esp Mar 25, 2025
3a2b8eb
Merge branch 'main' into b384509112-forecast-limit-bounds
rey-esp Apr 3, 2025
ca8c6b8
Merge branch 'main' into b384509112-forecast-limit-bounds
rey-esp Apr 9, 2025
2682734
Merge branch 'main' into b384509112-forecast-limit-bounds
rey-esp Apr 9, 2025
7f9382b
Apply suggestions from code review
tswast May 7, 2025
a890e58
Merge branch 'main' into b384509112-forecast-limit-bounds
tswast May 7, 2025
3661e3d
🦉 Updates from OwlBot post-processor
gcf-owl-bot[bot] May 7, 2025
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,5 @@ coverage.xml
system_tests/local_test_setup

# Make sure a generated file isn't accidentally committed.
demo.ipynb
pylintrc
pylintrc.test
21 changes: 21 additions & 0 deletions bigframes/ml/forecasting.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
"holiday_region": "holidayRegion",
"clean_spikes_and_dips": "cleanSpikesAndDips",
"adjust_step_changes": "adjustStepChanges",
"forecast_limit_upper_bound": "forecastLimitUpperBound",
"forecast_limit_lower_bound": "forecastLimitLowerBound",
"time_series_length_fraction": "timeSeriesLengthFraction",
"min_time_series_length": "minTimeSeriesLength",
"max_time_series_length": "maxTimeSeriesLength",
Expand Down Expand Up @@ -78,6 +80,17 @@ class ARIMAPlus(base.SupervisedTrainableWithIdColPredictor):
adjust_step_changes (bool, default True):
Determines whether or not to perform automatic step change detection and adjustment in the model training pipeline.

forecast_limit_upper_bound (float or None, default None):
The upper bound of the forecasting values. When you specify the ``forecast_limit_upper_bound`` option, all of the forecast values must be less than the specified value.
For example, if you set ``forecast_limit_upper_bound`` to 100, then all of the forecast values are less than 100.
Also, all values greater than or equal to the ``forecast_limit_upper_bound`` value are excluded from modelling.
The forecasting limit ensures that forecasts stay within limits.

forecast_limit_lower_bound (float or None, default None):
The lower bound of the forecasting values where the minimum value allowed is 0. When you specify the ``forecast_limit_lower_bound`` option, all of the forecast values must be greater than the specified value.
For example, if you set ``forecast_limit_lower_bound`` to 0, then all of the forecast values are larger than 0. Also, all values less than or equal to the ``forecast_limit_lower_bound`` value are excluded from modelling.
The forecasting limit ensures that forecasts stay within limits.

time_series_length_fraction (float or None, default None):
The fraction of the interpolated length of the time series that's used to model the time series trend component. All of the time points of the time series are used to model the non-trend component.

Expand Down Expand Up @@ -106,6 +119,8 @@ def __init__(
holiday_region: Optional[str] = None,
clean_spikes_and_dips: bool = True,
adjust_step_changes: bool = True,
forecast_limit_lower_bound: Optional[float] = None,
forecast_limit_upper_bound: Optional[float] = None,
time_series_length_fraction: Optional[float] = None,
min_time_series_length: Optional[int] = None,
max_time_series_length: Optional[int] = None,
Expand All @@ -121,6 +136,8 @@ def __init__(
self.holiday_region = holiday_region
self.clean_spikes_and_dips = clean_spikes_and_dips
self.adjust_step_changes = adjust_step_changes
self.forecast_limit_upper_bound = forecast_limit_upper_bound
self.forecast_limit_lower_bound = forecast_limit_lower_bound
self.time_series_length_fraction = time_series_length_fraction
self.min_time_series_length = min_time_series_length
self.max_time_series_length = max_time_series_length
Expand Down Expand Up @@ -175,6 +192,10 @@ def _bqml_options(self) -> dict:

if self.include_drift:
options["include_drift"] = True
if self.forecast_limit_upper_bound is not None:
options["forecast_limit_upper_bound"] = self.forecast_limit_upper_bound
if self.forecast_limit_lower_bound is not None:
options["forecast_limit_lower_bound"] = self.forecast_limit_lower_bound

return options

Expand Down
3 changes: 3 additions & 0 deletions tests/system/large/ml/test_forecasting.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ def test_arima_plus_model_fit_params(
holiday_region="US",
clean_spikes_and_dips=False,
adjust_step_changes=False,
forecast_limit_lower_bound=0.0,
time_series_length_fraction=0.5,
min_time_series_length=10,
trend_smoothing_window_size=5,
Expand Down Expand Up @@ -183,6 +184,8 @@ def test_arima_plus_model_fit_params(
assert reloaded_model.holiday_region == "US"
assert reloaded_model.clean_spikes_and_dips is False
assert reloaded_model.adjust_step_changes is False
# TODO(b/391399223): API must return forecastLimitLowerBound for the following assertion
# assert reloaded_model.forecast_limit_lower_bound == 0.0
assert reloaded_model.time_series_length_fraction == 0.5
assert reloaded_model.min_time_series_length == 10
assert reloaded_model.trend_smoothing_window_size == 5
Expand Down