data-science 2024-11-21

Hi @daslu, @hoppy and I have made some headway into understanding what an ffi wrapper for STAN with bridgestan might look like. However, it unfortunately seems like the architecture of bridgestan means that there's not much benefit over cmdstan. More details in ๐Ÿงต

Here's the basic flow for a typical usage of bridge stan: 1. write a .stan file with a model description 2. Use the cli stanc tool to compile the model to a shared library 3. load the shared library via the JVM 4. construct the model and pass it data via a JSON filename or string 5. run the model Typically, wrapping a native library has the benefits of improving performance and simplifying deployment. Passing data via a json string negates the benefits of shared memory and means performance is probably not much better. Requiring stanc from a local stan installation means that deploying models isn't much easier unless you can precompile the model ahead of time. If you need to tweak and recompile models, then you need to shell out to stanc regardless.

We were wondering whether there are any other benefits of a bridgestan approach for existing use cases.

Hi! That is great. Thanks for these notes. For using Stan "the usual way", indeed it may not add much. Bridgestan will mostly be helpful in writing our own inference algorithms, and can be a foundation for a Clojure library for Bayesian Statistics. I will write more a bit later.

so the use case of "I wanna bundle my prebaked stan model with some higher-level library is what we would be shooting at?" I see some point in that.

๐Ÿ‘ 1
โœจ 1

that's a perfect way to explain it!

I've done something similar before with Sqlite extension modules. The thing that makes this hard is that you are effectively proposing shipping a boatload of different platform specific libs and picking the right one at runtime. You would need your stan models compiled for quite a few platforms, and hope it all mates up on the target.

Ohh I see

stan-model -> stanc -> g++ -> dirty native .so

That is a good question. I will try to learn more about how they did it in other languages.

It looks like the intent is that you pull bridgestan and it pulls the pieces together for you to do the native build yourself with minimal ceremony. You just need a viable g++ toolchain, for your platform, available

๐Ÿ‘ 1

I would do that, then run my python to snarf in the .so with an import.

the "bridge" part is effectively a loader with a "clean" interface that in turns loads the stanc generated gnarl

it goes circular - want to avoid native compilation, so we strap on a prebuilt library that has virutally no chance of working on the target unless it's built natively.

As we discussed, this is not high priority for our short-term needs. We thought it would be an easy use case for exploring interop, but it turns out more complicated. Maybe the next step should be to justify it with a use case, e.g. by first using the BridgeStan bindings of another language, and connecting to them from Clojure by some way of communication between two processes.

(To motivate our interest in it, there is a currently going discussion in the Zulip chat about a topic called Active Inference, where our program not only infers but also acts. Then, observations are interlaced with actions, in a changing environment. To explore such systems in Clojure, BridgeStan seems like the right level of abstraction we could hope for. But this is not a high priority as far as I understand.)

------------ So, if this seem troublesome on the implementation side, I would suggest puting it on hold till we demonstrate what we want (which may take some time). Does it make sense?

I would bring up CmdStan in this context, and ask what sort of use case breaks this or makes it ugly

โž• 1

we can certainly make the bridgestan c-shim into an FFI type deal, which would at least give you the benefit of not having to restart an executable on every call into the model.

you would still be left with having to have a native-built .so for your box in hand - it would just give you a way to manage lifecycle a little better.

> I would bring up CmdStan in this context, and ask what sort of use case breaks this or makes it ugly Exactly. I'm proposing we will explore some use cases (like active inference) where https://scicloj.github.io/cmdstan-clj/ are not good enough. The Active Inference project can be one such case.

I lack knowledge of the quantity of back and forth traffic between "app" and "model". I think if I had to attack the problem bridgestan was trying to solve, I would have approached it as some sort of RPC thing with language neutrality on the app side - rather than cranking out a bunch of native bindings - invalidate of course if we are slinging K's or M's over the interface

That makes sense. We can at least do that for a proof-of-concept.

Many thanks for looking into this, and I'm sorry that it went complicated.

meh - software does that

And if you are curious about the use cases on the statistics side, I'd be glad to look together.

yes, I'd be interested to see this action

๐Ÿ‘ 1

a currently going discussion in the Zulip chat about a topic called Active Inference
for reference: https://clojurians.zulipchat.com/#narrow/channel/151924-data-science/topic/active.20inference

I need to reincarnate my zulip creds

๐Ÿ™ 1

> yes, I'd be interested to see this action great, I'll write some thoughts later

title it "why not cmdstan"?

then maybe we can solve that problem

Just started a Zulip topic thread on that: https://clojurians.zulipchat.com/#narrow/channel/151924-data-science/topic/why.20not.20cmdstan.3F.20.2F.20do.20we.20need.20bridgestan.3F There, we can keep chatting with a few of the relevant people.