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

Add initial support for pathfinder #464

Merged
merged 19 commits into from
May 21, 2024
Merged

Add initial support for pathfinder #464

merged 19 commits into from
May 21, 2024

Conversation

seabbs
Copy link
Collaborator

@seabbs seabbs commented May 16, 2024

Description

This PR adds initial support for Pathfinder. It appears to work fairly well for some models and less well for others (generally based on complexity). Definitely more to do here but I think having this functionality in now is useful.

Some likely contributors who may be interested to review @adrian-lison, @medewitt, @sbfnk.

Something this does not add is pathfinder initialisation for NUTs which I am waiting on support in cmdstanr for.

Try it out with:

library(epinowcast)

pobs <- enw_example("preprocessed")
latest_obs <- enw_example("observations")

path_nowcast <- epinowcast(pobs,
  expectation = enw_expectation(~1, data = pobs),
  fit = enw_fit_opts(enw_pathfinder, pp = TRUE, num_threads = 4, num_paths = 16),
  obs = enw_obs(family = "poisson", data = pobs)
)

plot(path_nowcast, latest_obs)

nuts_nowcast <- epinowcast(pobs,
  expectation = enw_expectation(~1, data = pobs),
  fit = enw_fit_opts(save_warmup = FALSE, pp = TRUE,
	chains = 2, iter_warmup = 1000, iter_sampling = 1000,
  ),
  obs = enw_obs(family = "poisson", data = pobs)
)

plot(nuts_nowcast, latest_obs)

@athowes we should check brms to see if Pathfinder is supported as for the same reasons as its useful here it might be handy to surface in epidist.

Checklist

  • My PR is based on a package issue and I have explicitly linked it.
  • I have included the target issue or issues in the PR title in the for Issue(s) issue-numbers: PR title
  • I have read the contribution guidelines.
  • I have tested my changes locally.
  • I have added or updated unit tests where necessary.
  • I have updated the documentation if required.
  • My code follows the established coding standards.
  • I have added a news item linked to this PR.
  • I have reviewed CI checks for this PR and addressed them as far as I am able.

Copy link
Contributor

This is how benchmark results would change (along with a 95% confidence interval in relative change) if e75618b is merged into main:

  • ✔️day_of_week_model: 20.5s -> 19.8s [-7.77%, +1.38%]
  • ✔️latent_renewal_model: 23s -> 24.8s [-8.31%, +24.15%]
  • ✔️missingness_model: 1.3m -> 1.31m [-2.22%, +3.77%]
  • ✔️multi_group_latent_renewal_model: 5.78s -> 6.11s [-12.81%, +24.08%]
  • ✔️preprocessing: 508ms -> 512ms [-4.98%, +6.75%]
  • ✔️simple_model: 4.54s -> 4.86s [-10.89%, +24.67%]
  • ✔️simple_negbin_model_with_pp: 5.09s -> 4.9s [-58.97%, +51.61%]
    These benchmarks are based on package examples which are available here. Further explanation regarding interpretation and methodology can be found in the documentation of touchstone.

Copy link
Collaborator

@medewitt medewitt left a comment

Choose a reason for hiding this comment

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

One typo, one philosophical. How do we detect the version of CmdStanR installed such that we can alert the user that pathfinder (and eventually laplace) isn't available? Or do we let CmdStan do it for us?

R/model-tools.R Outdated Show resolved Hide resolved
DESCRIPTION Show resolved Hide resolved
Copy link
Contributor

This is how benchmark results would change (along with a 95% confidence interval in relative change) if 96444ce is merged into main:

  • ✔️day_of_week_model: 19.7s -> 19.7s [-2.44%, +3.09%]
  • ✔️latent_renewal_model: 23.2s -> 24.7s [-4.86%, +18.2%]
  • ✔️missingness_model: 1.3m -> 1.32m [-4.61%, +7.69%]
  • ✔️multi_group_latent_renewal_model: 5.84s -> 5.74s [-14.69%, +11.13%]
  • 🚀preprocessing: 507ms -> 498ms [-3.18%, -0.36%]
  • ✔️simple_model: 4.78s -> 4.75s [-26.37%, +25.4%]
  • ✔️simple_negbin_model_with_pp: 3.75s -> 4.45s [-10.71%, +48.08%]
    These benchmarks are based on package examples which are available here. Further explanation regarding interpretation and methodology can be found in the documentation of touchstone.

Copy link
Contributor

This is how benchmark results would change (along with a 95% confidence interval in relative change) if dc6c75e is merged into main:

  • ✔️day_of_week_model: 19.5s -> 19.8s [-2.79%, +6.05%]
  • ✔️latent_renewal_model: 25.1s -> 23.6s [-22.19%, +10.42%]
  • ✔️missingness_model: 1.29m -> 1.3m [-2.86%, +3.97%]
  • ✔️multi_group_latent_renewal_model: 5.62s -> 5.72s [-8.83%, +12.47%]
  • ✔️preprocessing: 497ms -> 495ms [-1.58%, +0.66%]
  • ✔️simple_model: 4.44s -> 4.36s [-13.25%, +9.72%]
  • ✔️simple_negbin_model_with_pp: 3.86s -> 4.34s [-25.47%, +50.17%]
    These benchmarks are based on package examples which are available here. Further explanation regarding interpretation and methodology can be found in the documentation of touchstone.

Copy link

codecov bot commented May 19, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 97.46%. Comparing base (8d0da65) to head (0fa2690).
Report is 4 commits behind head on main.

Current head 0fa2690 differs from pull request most recent head e19e5f8

Please upload reports for the commit e19e5f8 to get more accurate results.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #464      +/-   ##
==========================================
+ Coverage   97.45%   97.46%   +0.01%     
==========================================
  Files          15       15              
  Lines        2160     2172      +12     
==========================================
+ Hits         2105     2117      +12     
  Misses         55       55              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

This is how benchmark results would change (along with a 95% confidence interval in relative change) if 0fa2690 is merged into main:

  • ✔️day_of_week_model: 19.7s -> 19.4s [-7.21%, +4.27%]
  • ✔️latent_renewal_model: 24.3s -> 23s [-12.39%, +1.54%]
  • ✔️missingness_model: 1.28m -> 1.29m [-1.54%, +4.05%]
  • ✔️multi_group_latent_renewal_model: 5.6s -> 5.49s [-13.54%, +9.6%]
  • ✔️preprocessing: 493ms -> 493ms [-1.41%, +1.54%]
  • ✔️simple_model: 4.55s -> 6.13s [-65.14%, +134.39%]
  • ✔️simple_negbin_model_with_pp: 3.81s -> 3.76s [-19.73%, +16.93%]
    These benchmarks are based on package examples which are available here. Further explanation regarding interpretation and methodology can be found in the documentation of touchstone.

Copy link
Collaborator

@medewitt medewitt left a comment

Choose a reason for hiding this comment

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

This looks good. I think the method detection is the only think I would recommend. Maybe a cli::cli_abort rather than cli::warn?

R/model-tools.R Show resolved Hide resolved
DESCRIPTION Show resolved Hide resolved
@seabbs seabbs requested a review from medewitt May 20, 2024 20:30
Copy link
Contributor

This is how benchmark results would change (along with a 95% confidence interval in relative change) if e19e5f8 is merged into main:

  • ✔️day_of_week_model: 19.5s -> 19.7s [-4.83%, +6.81%]
  • ✔️latent_renewal_model: 25.1s -> 23.4s [-33.16%, +19.4%]
  • ✔️missingness_model: 1.31m -> 1.31m [-4.5%, +4.53%]
  • 🚀multi_group_latent_renewal_model: 6.37s -> 6.01s [-10.45%, -0.83%]
  • ✔️preprocessing: 500ms -> 500ms [-1.19%, +1.24%]
  • ✔️simple_model: 4.99s -> 4.51s [-32%, +12.79%]
  • ✔️simple_negbin_model_with_pp: 4.78s -> 5.33s [-49.84%, +72.93%]
    These benchmarks are based on package examples which are available here. Further explanation regarding interpretation and methodology can be found in the documentation of touchstone.

Copy link
Collaborator

@medewitt medewitt left a comment

Choose a reason for hiding this comment

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

LGTM--can't wait to play with this!

@seabbs seabbs added this pull request to the merge queue May 21, 2024
Merged via the queue into main with commit 886b45c May 21, 2024
10 checks passed
@seabbs seabbs deleted the playing-with-pathfinder branch May 21, 2024 12:44
Copy link
Collaborator

@adrian-lison adrian-lison left a comment

Choose a reason for hiding this comment

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

Looking good! @seabbs, how much did you already play around with it? I just tested it on your example but with a daily random walk model and generation time, it wasn't too bad in terms of expectation, only the uncertainty quantification got worse (intervals very narrow).

When I tested pathfinder a while ago for EpiSewer, I wasn't impressed. It didn't seem to like the renewal model at all... Trends were often considerably off, and there was basically no uncertainty. Interestingly, this got worse when running more paths, results were best when running just one path with a limited number of iterations...

Would be great to get a better understanding of pathfinder's behaviour on time series models and possible tweaks, as this is obviously very useful.

@seabbs
Copy link
Collaborator Author

seabbs commented Jun 3, 2024

on your example but with a daily random walk model and generation time, it wasn't too bad in terms of expectation, only the uncertainty quantification got worse (intervals very narrow).

Yes, I also only did some limited exploration and found similar. I concluded that its likely useful for prototyping but I wouldn't trust it (on the examples I tested) for anything where I wanted to use the output.

@athowes is interested in potentially doing a more in depth look. I think your point about potential tweaks is a good one as it might be something simple that improves performance.

Interestingly, this got worse when running more paths, results were best when running just one path with a limited number of iterations...

I didn't see this and that is interesting. Suggests instability based on initialisation?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

None yet

3 participants