-
Notifications
You must be signed in to change notification settings - Fork 487
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
Conversation
Codecov Report
@@ 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
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. |
Model Benchmark
|
…nd added plot_interval_width_per_timestep() method for multiple timesteps.
…n and changed the split frequencies from to because of the Peyton Manning dataset.
FYI, I had to comment out |
f"Unknown conformal prediction method '{self.method}'. Please input either 'naive' or 'cqr'." | ||
) | ||
if step_number == 1: | ||
# save nonconformity scores of the first timestep |
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.
Why are these saved for the first step (only)?
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.
The nonconformity scores are saved in order to be inputted into plot_nonconformity_scores()
, where it plots:
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.
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.
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) |
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.
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.
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.
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?
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.
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.
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.
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.
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.
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) |
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.
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?
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.
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:
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).
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.
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!
…nd modified plot() in conformal.py to enable this method for plotting_backend='plotly'.
… plotting_backend param into m.conformal_predict() method.
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.
Thank you for adding the plotly equivalent! Good work!
Ready to merge.
🔬 Background
🔮 Key changes
📋 Review Checklist
Please make sure to follow our best practices in the Contributing guidelines.