# Thoughts pipeline-style API for \`sample()\`

**URL:** https://discourse.pymc.io/t/thoughts-pipeline-style-api-for-sample/395
**Category:** Development
**Created:** [October 4, 2017, 2:31pm UTC](https://discourse.pymc.io/t/thoughts-pipeline-style-api-for-sample/395 "2017-10-04T14:31:42Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![pstjohn](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/pstjohn/32/268_2.png) [@pstjohn](https://discourse.pymc.io/u/pstjohn)
#### Post date: [October 4, 2017, 2:31pm UTC](https://discourse.pymc.io/t/thoughts-pipeline-style-api-for-sample/395/1 "2017-10-04T14:31:43Z")

</div>

So as a pymc3 user, the initialization recipes in `pymc3/sampling.py` are really useful for getting started. But often I’ll want to customize / change a certain kwarg for one of those intermediate steps (i.e., the optimizer used for ADVI in `init_advi`, the minimizer for `find_MAP`) which aren’t exposed from the main `sample(*args, **kwargs)` API.

I’m then left trying to re-create some of those recipies in my main script so I can access those features, but that’s cumbersome and requires a bit of hunting around for the right inputs.

We could certainly expose additional workings to the main sample API, but I’m not sure that’s the best option. scikit-learn has a similar problem and has solved it really nicely with their `Pipeline` class, which allows you to chain together different methods while customizing their hyperparameters. I.e.,

```python
Pipeline([('anova', anova_filter),
          ('svc', clf)])

```

What we’re really building in `sample.py` (and changing with the different `init` arguments) is an ‘inference pipeline’, with various initialization, approximation, and sampling methods.  
It would be awesome if we could do something similar in pymc3, and build up our inference algorithm with something like

```python
pm.Pipeline([
    ('map', pm.find_MAP(...)),
    ('advi', pm.AVDI(n=50000, optimizer=...)),
    ('adapt_diag', pm.some_fn()),
    ('hmc', pm.NUTS(...))

```

It would be 1) more customizable, instead of continuing to accumulate recipes in `sample(init='...')`, and 2) would allow you to go back and inspect, for instance, how closely the advi fit came to approximating your sampler.

Just a thought, I’m sure it would take a pretty concerted effort to re-engineer the API.

---

<div class="post-metadata">

### Author: ![junpenglao](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/junpenglao/32/8_2.png) [@junpenglao](https://discourse.pymc.io/u/junpenglao)
#### Post date: [October 4, 2017, 3:17pm UTC](https://discourse.pymc.io/t/thoughts-pipeline-style-api-for-sample/395/2 "2017-10-04T15:17:53Z")

</div>

Thanks @pstjohn, I like the scikit-learn pipeline API - it’s great for standardizing analysis workflow. That being said, I am not a big fan of introducing the same concept in PyMC3. The reason is being: `pm.sample()` and `pm.fit()` is what we aim to archived as an “Inference button”. The goal is that user just write down the model and PyMC3 choose the optimal (that we can think of) approach to fit/sample from the model. Many of the option you mention (e.g., hand tunning the ‘adapt\_diag’ method) is not supposed to expose to the users - you need to know what you are doing.

I think in general, my take is that if the default method doesnt work, beside some easy kwarg to try (e.g., increasing `target_accept` in NUTS), the instincts should be reparameterization.

---

<div class="post-metadata">

### Author: ![bwengals](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/bwengals/32/1237_2.png) [@bwengals](https://discourse.pymc.io/u/bwengals)
#### Post date: [October 4, 2017, 11:07pm UTC](https://discourse.pymc.io/t/thoughts-pipeline-style-api-for-sample/395/3 "2017-10-04T23:07:11Z")

</div>

I can see sometimes in advanced cases when you may want specialized routines, like maybe using OPVI to initialize NUTS mass matrix, or find\_MAP with a minimization routine that handles discrete parameters.

All of these routines can be used independently of `sample` of course, so it’s not too hard to pipeline your own routine. The implementation within `sample` is straightforward, so you can see how to do it for your unique case [here](https://github.com/pymc-devs/pymc3/blob/master/pymc3/sampling.py#L769).
