-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
[ENH] prophet based piecewise linear trend forecaster
#5592
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
Conversation
…into pcw-linear-detrender
|
Hello core developers this is my first PR and I would be happy to get some feedback and improve the code if needed. |
fkiraly
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good on superficial look!
One issue - which the tests will also highlight - is that you are not adhering to sktime code formatting (linting). These are various small and - logic-wise - inconsequential things, but it is enforced.
Instructions on this, including how to set this up on your computer in an automated way, here:
https://www.sktime.net/en/stable/developer_guide/coding_standards.html
…into pcw-linear-detrender
Thanks @fkiraly for the comments. I ran |
fkiraly
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great!
There is a subtle issue, related to how sktime does testing.
In testing, we pass multiple data scenarios to fit/predict, this is with varying index and index type.
In get_test_params, you have specified changepoints that make sense for some indices, but not for others, but all data scenarios are run with these parameters, which can lead to the "changepoints outside range" issue.
An acceptable solution would be, imo, to specify changepoints only by number or relatively, without direct reference to the index range, and set up separate tests, in a test_pwl_trend or similar file, with changepoints matching index range.
fkiraly
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me.
I would recommend, let's add at least a second parameter set to get_test_params as well, covering different parameter settings.
Will not merge yet as this is still a draft, but looks done.
|
FYI @sbuse , @tpvasconcelos, @yarnabrina, this PR actually contains an example of a second descendant of Post-merge #5597, code that previously would not have failed, fails now. Reviews would be appreciated, from the perspective of the prophet adapter. |
…into pcw-linear-detrender
Okay, I will add |
|
@sbuse @fkiraly quick question on this one. Referencing the original example in #5197 , isn't this already possible with: pwl_trend_forecaster = Prophet(
daily_seasonality=False,
weekly_seasonality=False,
yearly_seasonality=False
)
forecaster = TransformedTargetForecaster(
[
("detrend", Detrender(forecaster=pwl_trend_forecaster)),
("forecast", ARIMA() )
]
) |
prophet based piecewise linear trend forecaster
|
Hi @tpvasconcelos, Hi @fkiraly import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sktime.forecasting.base import ForecastingHorizon
from sktime.forecasting.trend import ProphetPiecewiseLinearTrendForecaster
from sktime.forecasting.model_selection import temporal_train_test_split
from sktime.forecasting.fbprophet import Prophet
from sktime.performance_metrics.forecasting import MeanSquaredError
def Randomwalk1D(n):
y = 0
yposition = [0]
for i in range(n-1):
step = np.random.uniform(0,1)
if step < 0.5:
y += 1
if step > 0.5:
y += -1
yposition.append(y)
return yposition
n = 1000
np.random.seed(42)
mse = MeanSquaredError(square_root=True)
all_mse_current = []
all_mse_suggestion = []
for prior_scale in np.logspace(-3,-1/3,num=10): #values within 0.001 and 0.46
for i in range(500):
y = pd.Series(
data=Randomwalk1D(n),
index=pd.date_range('2016-01-01',periods=n, freq='15min')
)
y_train, y_test = temporal_train_test_split(y)
fh = ForecastingHorizon(y.index, is_relative=False)
current = ProphetPiecewiseLinearTrendForecaster(
changepoint_prior_scale=prior_scale
)
suggestion = Prophet(
daily_seasonality=False,
weekly_seasonality=False,
yearly_seasonality=False,
changepoint_prior_scale=prior_scale
)
y_pred_current = current.fit(y).predict(fh)
y_pred_suggestion = suggestion.fit(y).predict(fh)
mse_current = mse(y,y_pred_current)
mse_suggestion = mse(y,y_pred_suggestion)
all_mse_current.append(mse_current)
all_mse_suggestion.append(mse_suggestion)
total = len(np.array(all_mse_current))
current_wins = np.sum(np.array(all_mse_current)<np.array(all_mse_suggestion))
suggestion_wins = np.sum(np.array(all_mse_current)>np.array(all_mse_suggestion))
ties = np.sum(np.array(all_mse_current)==np.array(all_mse_suggestion))
print(f"Out of {total} runs: \nThe current implementation is more accurate in "+
f"{current_wins} ({np.round_(current_wins/total*100,1)}%) cases.\n"+
f"The suggested change is more accurate in {suggestion_wins}"+
f"({np.round_(suggestion_wins/total*100,1)}%) cases.\n"+
f"In {ties} ({np.round_(ties/total*100,1)}%) cases they return the same value.") |
|
probably will depend on the data - my intuition would tell me, if there are different sensible suggestions on how it should behave internally, just expose them to the user, i.e., the seasonality parameters, with default being current. |
…ecaster (#5834) <!-- Welcome to sktime, and thanks for contributing! Please have a look at our contribution guide: https://www.sktime.net/en/latest/get_involved/contributing.html --> The PR exposes the seasonal parameters of the ProphetPiecewiseLinearTrendForecaster. The PR is the result of the discussion in this (#5592). #### What does this implement/fix? Explain your changes. <!-- A clear and concise description of what you have implemented. --> This is a simple change to allow the user to define what the seasonality parameters should be. @tpvasconcelos suggested they should be ```python daily_seasonality=False, weekly_seasonality=False, yearly_seasonality=False ``` but as the discussion (#5592) showed it is not clear if this is the best setting.
Reference Issues/PRs
Discussion #5197
Depends on #5622 which should be merged first.
What does this implement/fix? Explain your changes.
This PR extracts the piece wise linear trend from the prophet algorithm. The algorithm is well suited to be used for trend forecasting in a pipeline and less useful alone.
Does your contribution introduce a new dependency? If yes, which one?
no new dependency, prophet was already implemented.
What should a reviewer concentrate their feedback on?
Since this is my first PR for sktime it would be good if the reviewer could check if i have done everything required and according to the conventions.
Did you add any tests for the change?
No I haven't added any test.
Any other comments?
PR checklist
For all contributions
How to: add yourself to the all-contributors file in the
sktimeroot directory (not theCONTRIBUTORS.md). Common badges:code- fixing a bug, or adding code logic.doc- writing or improving documentation or docstrings.bug- reporting or diagnosing a bug (get this pluscodeif you also fixed the bug in the PR).maintenance- CI, test framework, release.See here for full badge reference
See here for further details on the algorithm maintainer role.
For new estimators
docs/source/api_reference/taskname.rst, follow the pattern.Examplessection.python_dependenciestag and ensureddependency isolation, see the estimator dependencies guide.