symbolic-pymc
symbolic-pymc copied to clipboard
Automatically convert PyMC3 `Distribution`s to `RandomVariable`s
We can create a function that constructs a RandomVariable class for a given PyMC3 Distribution class. The basic requirements are
- that #109 be in place and
log_lik = Distribution.logp(out_var), Distribution.__init__is utilized inRandomVariable.make_nodeand its signature is used to determine the signature ofRandomVariable.make_node, as well (see the examples here),- and
Distribution.randomis the backing implementation withinRandomVariable.perform.
One complication that comes to mind involves requirement 3.; most implementations of Distribution.random use draw_values, which would be redundant within RandomVariable.perform, since pre-computed samples of all dependent terms already appear as arguments
to RandomVariable.perform. We would have to override draw_values in that context so that it simply returns RandomVariable.perform arguments. It seems like we could use something like mock to accomplish that easily.
Here's a prototype conversion function that does almost everything mentioned above.
There is a lot of room for error, especially when a Distribution demands test values or uses instance fields in Distribution.random that can't be converted to Theano objects. Both of these are poor practice in general, but the former is effectively required in some situations—I imagine.
@lucianopaz, this is a good starting point for considering class-level Distribution field additions—beyond support and parameter dimension sizes. For instance, while setting up that prototype, I realized that one of the biggest issues is the lack of information about distribution parameters in general. The connections between Distribution.__init__ signatures and the assignments to Distribution.__dict__ aren't strong enough to work with, so perhaps we could add more class-level information like that (e.g. names of essential parameters, or keep a list of said parameters within a class instance, etc.)
This looks really promising!