Creating a brmsfit object with a modified brms-generated Stan model

I would like to create a brmsfit object with a modified brms-generated Stan model. [This makes it for example easier to generate posterior predictive distributions.]

One way to do this I can think of is to

  1. generate a brmsfit model with a first call of brm. Lets call this brms_orig
  2. extract the Stan model code brms_orig$model, change it and put the modified model back into the brms_orig$model slot
  3. recompile the modified brms_orig and sample from it with brms_modified = update(brms_orig, recompile = TRUE)

I can imagine that this works if the modified Stan model has the same parameters as the original model, but I am not sure. I am even less sure that this would work if the modified Stan model had additional parameters (e.g. to implement types of imputations brms does not support yet.)

My specific questions are:

  • Does the above outlined workflow work as long as the modified Stan model has the same parameters as the original brms-generated Stan model?
  • What would one need to do in addition, if the modified Stan model had additional parameters?

Thanks in advance!

Guido

##########################################################
Please also provide the following information in addition to your question:

  • Operating System: Windows 10
  • brms Version: 2.6
1 Like

The model must have the same likelihood structure, because this is what is picked up by the post processing methods such as posterior_predict. That is, you may add additional parameters as long as they just come into play via the prior. See ?stanvar for an example.

With regard to your workflow, I would replace the whole stan model in slot fit. Slot model is merely a high level storage point of the stan code that is actually also stored somewhere deeper in fit. The workflow would be something like:

  1. Create an “empty” brmsfit object of your model via brm(..., chains = 0).
  2. Generate and amend the Stan code and replace slot fit with the output of rstan::stan_model (you may also want to change the Stan code in slot model).
  3. Run update(<model>, recompile = FALSE)

Not entirely sure if it works exactly this way, but it should provide a start to play around with.

4 Likes

Is this possible with cmdstanr backend? I’m trying to implement my needs from this post: Shared parameters in multiple models

It is a little bit more complicated since brmsfit$fit needs to be a stanfit object. Perhaps the code of brms:::.fit_model_cmdstanr can help you to transform the output of cmdstanr into a stanfit object.

Thanks, I just gave up on this for now and am just doing everything in stan; its a shame to have to handcode all the prediction stuff. Great package though! Incredibly useful.

@paul.buerkner

To clarify, is this workflow only possible if the likelihood has not changed?

More specifically, I am trying to fit a binomial measurement error model, which is not currently supported by brms. I think I’ve figured out the model and the Stan code, but it involves replacing the arguments of the binomial_logit_lpmf with parameters corresponding to the measurement error model. It’s therefore not possible using stanvars.

Is there a way to fit the “empty” model (setting empty = TRUE), plug in a separate stanfit object (with a different likelihood), and then get all the post-fitting functions like predict methods to work?

Hmm, this is unlikely to work. I think your best shot is to try to define a custom family representing your case. There, you can specify your own posterior_predict, log_lik etc. functions to make sure the post-processing matches what happens in the stan code.

Thanks for the response. However, I want to clarify my previous post.

I said that the likelihood has changed, which is true. However, what has not changed is the right hand side of the regression equation. I think that in this case, the posterior_linpred function would work exactly the same, since it only depends on the ability to calculate mu. Does that sound right?

As luck would have it, this is the post-processing function that I need for my use case.

If the mean parameter of your likelihood remains the same then yes.