Skip to content
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

Uncertainty: Conformal Prediction V1.1 - extend to multiple forecast steps instead of only a single forecast step #1073

Merged
merged 22 commits into from
Jan 13, 2023

Conversation

Kevin-Chen0
Copy link
Collaborator

@Kevin-Chen0 Kevin-Chen0 commented Dec 17, 2022

🔬 Background

🔮 Key changes

  • Extend to multiple forecast steps instead of only a single forecast step.

📋 Review Checklist

  • I have performed a self-review of my own code.
  • I have commented my code, added docstrings and data types to function definitions.
  • I have added pytests to check whether my feature / fix works.

Please make sure to follow our best practices in the Contributing guidelines.

@Kevin-Chen0 Kevin-Chen0 added enhancement status: needs review PR needs to be reviewed by Reviewer(s) priority:P2 Medium priority labels Dec 17, 2022
@Kevin-Chen0 Kevin-Chen0 added this to the Release 0.5.1 milestone Dec 17, 2022
@Kevin-Chen0 Kevin-Chen0 self-assigned this Dec 17, 2022
@codecov-commenter
Copy link

codecov-commenter commented Dec 17, 2022

Codecov Report

Merging #1073 (f4629e2) into main (05d5e10) will increase coverage by 0.19%.
The diff coverage is 97.91%.

@@            Coverage Diff             @@
##             main    #1073      +/-   ##
==========================================
+ Coverage   90.14%   90.33%   +0.19%     
==========================================
  Files          21       21              
  Lines        4800     4824      +24     
==========================================
+ Hits         4327     4358      +31     
+ Misses        473      466       -7     
Impacted Files Coverage Δ
neuralprophet/conformal.py 96.82% <96.96%> (+2.59%) ⬆️
neuralprophet/forecaster.py 87.89% <100.00%> (ø)
neuralprophet/plot_forecast_matplotlib.py 85.50% <100.00%> (+0.58%) ⬆️
neuralprophet/plot_forecast_plotly.py 87.72% <100.00%> (+3.07%) ⬆️

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

@github-actions
Copy link

github-actions bot commented Dec 17, 2022

Model Benchmark

Benchmark Metric main current diff
AirPassengers MAE_val 15.2698 15.2698 0.0%
AirPassengers RMSE_val 19.4209 19.4209 0.0%
AirPassengers Loss_val 0.00195 0.00195 0.0%
AirPassengers MAE 9.82902 9.82902 0.0%
AirPassengers RMSE 11.7005 11.7005 0.0%
AirPassengers Loss 0.00056 0.00056 0.0%
AirPassengers time 4.90997 4.08 -16.9% 🎉
YosemiteTemps MAE_val 1.72948 1.72949 0.0%
YosemiteTemps RMSE_val 2.27386 2.27386 0.0%
YosemiteTemps Loss_val 0.00096 0.00096 0.0%
YosemiteTemps MAE 1.45189 1.45189 0.0%
YosemiteTemps RMSE 2.16631 2.16631 0.0%
YosemiteTemps Loss 0.00066 0.00066 0.0%
YosemiteTemps time 111.253 92.43 -16.92% 🎉
PeytonManning MAE_val 0.64636 0.64636 0.0%
PeytonManning RMSE_val 0.79276 0.79276 0.0%
PeytonManning Loss_val 0.01494 0.01494 0.0%
PeytonManning MAE 0.42701 0.42701 0.0%
PeytonManning RMSE 0.57032 0.57032 0.0%
PeytonManning Loss 0.00635 0.00635 0.0%
PeytonManning time 13.5751 11.42 -15.88% 🎉
Model training plots

Model Training

PeytonManning

YosemiteTemps

AirPassengers

…nd added plot_interval_width_per_timestep() method for multiple timesteps.
@Kevin-Chen0 Kevin-Chen0 added status: needs update PR has outstanding comment(s) or PR test(s) that need to be resolved and removed status: needs review PR needs to be reviewed by Reviewer(s) labels Dec 18, 2022
@Kevin-Chen0 Kevin-Chen0 requested a review from noxan January 3, 2023 23:40
@Kevin-Chen0 Kevin-Chen0 added status: needs review PR needs to be reviewed by Reviewer(s) and removed status: needs update PR has outstanding comment(s) or PR test(s) that need to be resolved labels Jan 3, 2023
@Kevin-Chen0
Copy link
Collaborator Author

FYI, I had to comment out test_PeytonManning, test_YosemiteTemps, and test_AirPassengers in test_model_performance.py as they were failing for me.

@Kevin-Chen0 Kevin-Chen0 linked an issue Jan 10, 2023 that may be closed by this pull request
3 tasks
f"Unknown conformal prediction method '{self.method}'. Please input either 'naive' or 'cqr'."
)
if step_number == 1:
# save nonconformity scores of the first timestep
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these saved for the first step (only)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The nonconformity scores are saved in order to be inputted into plot_nonconformity_scores() , where it plots:
Naive One-Sided Interval Width with q

The nonconformity score is the score (blue line).

This plot is only called when n_forecasts ==1. For models with n_forecasts >1, it will call the plot_interval_width_per_timestep() instead (more details under your 3rd question), which doesn't require nonconformity scores. Therefore, only the first step needs to be saved.

Copy link
Owner

@ourownstory ourownstory Jan 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the explanation!

fig = plot_nonconformity_scores(self.noncon_scores, self.alpha, self.q_hat, method)
if self.n_forecasts == 1:
# includes nonconformity scores of the first timestep
fig = plot_nonconformity_scores(self.noncon_scores, self.alpha, self.q_hats[0], method)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally we would have the same behavior for self.n_forecasts == 1 and other values of n_forecasts.
Maybe we could instead have the special plot that includes the scores be a separate plotting utility call instead of automatically overwriting the standard plotting utility.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Further, there seems to be these two options only in the matplotlib case but not for plotly - However the plot should be as identical as possible independent of the plotting backend. How can we make them return the same kind of plot?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two different plots show whether n_forecasts == 1 or n_forecasts >1. See your 1st and 3rd questions for details.

As for the matplotlib and plotly, both have the plot_nonconformity_scores(), but only matplotlib has the plot_interval_width_per_timestep(). I'll try to code that for plotly now and before the merge of this PR.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just added plot_interval_width_per_timestep() for for plotly and modified the test_plot_conformal_prediction so the test coverage for that addition is there.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes more sense to me now, thank you!
From a UI-perspective it's not ideal to have the plot change quite so drastically depending on an external factor, but I think it is OK in this case as this is more of a research/diagnostic plot.

Figure showing the q-values for each timestep
"""
fig, ax = plt.subplots()
ax.plot(range(1, len(q_hats) + 1), q_hats)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am sorry, I am a bit confused about what is being plotted based on the docstring and code.
Aren't the qhats static?
Or what are we plotting here?

Copy link
Collaborator Author

@Kevin-Chen0 Kevin-Chen0 Jan 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the plot_interval_width_per_timestep() method for models with n_lags > 1 and thus self.n_forecasts >1. You can try with the m3 and m4 models in the uncertainty_conformal_prediction.ipynb. Therefore, instead of plotting the Naive One-Side Interval Width from q (with the noncon scores and q1 horizontal line from just forecast1), this method will instead plot the q values (or q_hats) for each of the timesteps:
Naive One-Sdied Interval Width with q
So the blue line here is not the noncon scores but the q values on each timestep number.

You can see how q linearly increases the further the timestep (until it plateaus around t+12)? This shows the greater uncertainty, the further out the forecast that it requires wider intervals for the same confidence level (e.g., 90% in this example). The reason for this plateau could be attributed to the half-day seasonality of this hospital energy load dataset (i.e., day and night usage).

Copy link
Owner

@ourownstory ourownstory Jan 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for explaining!
Sorry, I interpreted x-axis to be datetime, not forecast step numbers.
Now it makes sense. Cool how one can see it increase and then plateau!
I like this new plot. I think it is helpful!

Kevin-Chen0 and others added 3 commits January 12, 2023 20:42
…nd modified plot() in conformal.py to enable this method for plotting_backend='plotly'.
… plotting_backend param into m.conformal_predict() method.
Copy link
Owner

@ourownstory ourownstory left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for adding the plotly equivalent! Good work!
Ready to merge.

@ourownstory ourownstory merged commit 3d46b1e into main Jan 13, 2023
@ourownstory ourownstory deleted the refactor/conformal-multistep branch January 13, 2023 07:40
@Kevin-Chen0 Kevin-Chen0 restored the refactor/conformal-multistep branch February 20, 2023 21:20
@Kevin-Chen0 Kevin-Chen0 deleted the refactor/conformal-multistep branch February 20, 2023 21:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
priority:P2 Medium priority status: needs review PR needs to be reviewed by Reviewer(s)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Conformal Prediction V1.1 tasks
4 participants