Inconsistent kwargs methods for single step / multi step samplers

The interface of sample is different according to the specific model used. This makes it extremely cumbersome to abstract and modularize the model.

For example, this is how you sample from a model that contains both discrete and continuous variables:

trace = pm.sample(
    nuts={'target_accept': 0.95, 'max_treedepth': 25}

And this is how to do it when the model only has continuous variables:

trace = pm.sample(
    target_accept=0.95, max_treedepth=25

And what is worse is that these two are not compatible. Using the first version with a model that does not have discrete variables gives the error:

TypeError: function() got an unexpected keyword argument 'nuts'

While using the second version with a model containing discrete variables gives the error:

ValueError: Unused step method arguments: {'target_accept', 'max_treedepth'}

Is it possible to find a way that works in both cases? Possibly the simplest solution is to check if 'nuts' is in the kwargs before calling init_nuts (here). I am open to work on a pull request for this.

Use case: I am comparing two models that are very similar except that one contains a “sparsity prior” through a Bernoulli distribution. Since the models are otherwise very similar, I abstracted away this sparsity part and the rest of the model. The inconsistent interface of sample, however, makes this quite ugly, as I am essentially forced to try one method and use the other if I an exception is thrown.

Yeah this is because when you need CompoundStep (i.e two different samplers, like NUTS and Metropolis for instance), you need to address the kwargs directly to the corresponding step method. Whereas when you only need one sampler, you can access the sampler directly in sample.

The docs are indeed not very clear about that, but it was sorted out by a recent PR – see this issue for discussion and associated PR.

If you have an idea to improve this API, I think this would be great! We’re always welcoming of PRs :slight_smile:

Thank you!

I think it would be good software engineering practice to have an API that is not dependent on the specific model, but I am not sure what is the preferred way to do this as I am not very deep into pymc3. I will come up with something and we continue the discussion in the PR :slight_smile:

1 Like