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

Test speed advantage of using ulpdf instead of lpdf #1017

Closed
avehtari opened this issue Oct 15, 2020 · 15 comments
Closed

Test speed advantage of using ulpdf instead of lpdf #1017

avehtari opened this issue Oct 15, 2020 · 15 comments

Comments

@avehtari
Copy link
Contributor

brms uses always target += instead of ~. The tilde version uses log unnormalized pdf to avoid computation of constants that don't affect sampling. brms uses target += with *_lpdf that are log normalized pdfs to support marginal likelihood computations, but then computes the constants also when not needed. The new Stan release 2.25 has support for *_lupdf that provide the log unnormalized pdf, so it would be possible to provide an option switch normalization off. It would be useful to make some speed tests with models that have expensive normalization terms and especially with for loops so that the normalization terms are computed many times. Unlikely of order of magnitude speed-ups but can be significant speed-ups for some models.

@wds15
Copy link
Contributor

wds15 commented Oct 15, 2020

Test poisson and you should see a difference (and also dropping those ccdf calls should help) in speed.

@andrjohns
Copy link
Contributor

Correct me if I'm wrong, but doesn't brms need to keep the _lpdf construction for compatibility with bridgesampling post-processing? Since that needs the normalising constants?

@andrjohns
Copy link
Contributor

As soon I hit comment I saw the part of the issue that mentioned the option to switch normalising on/off, never mind me

@andrjohns
Copy link
Contributor

Paul, I worked up an initial implementation on this branch. It's currently only for simple outcome likelihoods but let me know if the basic approach is consistent with how you would tackle it, or if you'd prefer a different method.

As an example, calling:

make_stancode(rating ~ treat + period + carry,
              data = inhaler, normalise = FALSE)

Gives the model block:

  // likelihood including all constants
  if (!prior_only) {
    target += normal_id_glm_lupdf(Y | Xc, Intercept, b, sigma);
  }
  // priors including all constants
  target += student_t_lpdf(Intercept | 3, 1, 2.5);
  target += student_t_lpdf(sigma | 3, 0, 2.5)
    - 1 * student_t_lccdf(0 | 3, 0, 2.5);
}

Which compiles and samples under the cmdstanr backend

@paul-buerkner
Copy link
Owner

Yes, this looks exactly like the approach I would have used!

@rok-cesnovar
Copy link
Contributor

rok-cesnovar commented Nov 9, 2020

Nice! The problem is again this only works with stan2.25 and on.

@paul-buerkner
Copy link
Owner

Yes, so we should only merge once rstan is at 2.25 as well or make the stan code generation conditional, which I personally want to avoid.

@paul-buerkner
Copy link
Owner

Or just allow normalize = FALSE when cmdstanr with Stan 2.25+ is used, which would be fine and easy to check.

@andrjohns
Copy link
Contributor

Great! Will work on updating and testing the rest of the likelihoods

@andrjohns
Copy link
Contributor

Quick clarification for the priors, am I right in assuming that if normalise=TRUE gives:

  target += student_t_lpdf(Intercept | 3, 1, 2.5);
  target += student_t_lpdf(sigma | 3, 0, 2.5)
    - 1 * student_t_lccdf(0 | 3, 0, 2.5);

Then normalise = FALSE gives:

  target += student_t_lupdf(Intercept | 3, 1, 2.5);
  target += student_t_lupdf(sigma | 3, 0, 2.5);

In other words it no longer needs the lccdf adjustments for parameters with bounds, right?

@paul-buerkner
Copy link
Owner

paul-buerkner commented Nov 10, 2020 via email

@andrjohns
Copy link
Contributor

Thanks!

@andrjohns
Copy link
Contributor

Paul - got this pretty close to a PR-ready state (on this branch). I've tested the models in the tests.model_new.R file, and all looks good. Do you have any other models that this should be tested across before I move to a PR?

@paul-buerkner
Copy link
Owner

Amazing, thank you! Testing all from model_new seems sufficient I think. Once you make a PR, I am happy to review it and perhaps make some edits.

@paul-buerkner
Copy link
Owner

I realize we can close this isse since your PR has beem merged already. Thank you again for working in it!

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

No branches or pull requests

5 participants