roualdes / bridgestan

BridgeStan provides efficient in-memory access through Python, Julia, and R to the methods of a Stan model.
https://roualdes.github.io/bridgestan
BSD 3-Clause "New" or "Revised" License
88 stars 12 forks source link

add no_warnings / quiet option to StanModel$new() #217

Closed avehtari closed 6 months ago

avehtari commented 6 months ago

There are many use cases where there is a need to call StanModel$new() thousands of time with different data. After the second call there is always a warning message

Warning message:
In initialize(...) :
  Loading a shared object '/u/77/ave/unix/proj/cwolfe/multi_sim_missx_model.so' which is already loaded.
If the file has changed since the last time it was loaded, this load may not update the library!

Please add an option to turn this off. I could use R suppressWarnings(), but then I can miss other warnings. For example, if I have

    suppressWarnings(mod2bs <- StanModel$new(lib = mod2bs_lib,
                                             data = to_stan_json(standati),
                                             seed = 1))

I may miss useful warnings from to_stan_json() function, and I would not like to create another variable to store the json before calling StanModelnew()

roualdes commented 6 months ago

Thanks, @avehtari, for bringing this up.

I could use R suppressWarnings()

In my opinion, it's better to handle this at the BridgeStan level since similar use cases might come up in other languages, too.

@WardBrian It looks like we could just add a quiet (or whatever) keyword argument to line #33 of R/bridgestan.R. And there's probably a similar change for each of the other interfaces. What do you think?

More broadly, Aki, you are just looking for automatic differentiation of a statistical model as data changes, right? I was bringing this up at StanCon last year. I'd really like, but don't fully understand the implications, of making data non-const in a Stan model class.

bob-carpenter commented 6 months ago

don't fully understand the implications, of making data non-const in a Stan model class.

[edit: Aki didn't say he was making it non-const, just that he was instantiating a bunch of instances of the same Stan class with different data.]

As is, Stan model objects are immutable after construction. This automatically guarantees thread safety. As soon as you start allowing a model class to be modified, it's going to have to be synchronized.

A motivation would be to do something like stochastic gradient descent. If you could change the data each iteration, you could implement that. This has come up multiple times before, usually around things like wanting access to iteration number, or other things that would store state on the model. I've generally been resistant to that.

WardBrian commented 6 months ago

We could definitely do this for each interface, yes. The hardest part is deciding on a name for said argument I think.

avehtari commented 6 months ago

There are many use cases. So far I've used it 1) getting group specific conditional log density in hierarchical models (conditional on hyperparameters, changing data for each group), 2) and doing post-hoc missing data inference (conditional on original model parameters without missing data, changing data is the new observed target y, and get the log density for missing x). It would also be useful 3) in various cross-validation, bootstrap, and covariate importance methods. In 2) I did use a second model where missing x is declared as parameter, but even then ended up not using gradients as slice sampling for 1D is so fast. A Stan discourse thread has code for using adaptive Gauss-Hermite quadrature or slice sampling https://discourse.mc-stan.org/t/post-hoc-prediction-use-samples-from-fitted-model-in-a-prediction-task/34319/13. In the latter code, I did end up passing previous posterior draws as parameters and not data, as the instantiation overhead was dominating the computation time, but I was still passing y as data.

avehtari commented 6 months ago

The hardest part is deciding on a name for said argument I think.

Relevant discussion about this: https://ropensci.org/blog/2024/02/06/verbosity-control-packages/

roualdes commented 6 months ago

I propose, from my most to least preferred,

  1. warn
  2. verbose
  3. quiet

for a signature like initialize = function(lib, data, seed, stanc_args = NULL, make_args = NULL, warn = TRUE) to match our current behavior.

I'm also open to other suggestions.

WardBrian commented 6 months ago

I do wonder if one day the constructor could have other warnings, and we’d want to be able to silence just some of them, in which case this should be called something like silence_reload_warning

roualdes commented 6 months ago

That's a good thought. In that case though, I'd still think there should be one argument to prevent all warnings, instead of forcing users to type out each individually.

WardBrian commented 6 months ago

Sure, so I guess we can go with a general name for now and add a more specific one if the need ever does arise.

I can knock this out tomorrow I think

roualdes commented 6 months ago

And if you can't, just ping me and I'll cover it next week. Spring break next week, so I should have enough time.