Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API change maxent and quartile functions #517

Closed
aloctavodia opened this issue Aug 14, 2024 · 5 comments · Fixed by #523
Closed

API change maxent and quartile functions #517

aloctavodia opened this issue Aug 14, 2024 · 5 comments · Fixed by #523

Comments

@aloctavodia
Copy link
Contributor

maxent and quartile both accept a distribution, modify it in place and by default plot the modified distribution. They both return the axes and the optimization object from scipy.optimize. This is usually ok. But there are instances that a different behaviour will be more useful for instance a common pattern when working with GPs in PyMC is to do something like this

ell_t_params = pm.find_constrained_prior(
    pm.Lognormal, lower=0.5, upper=4.0, mass=0.95, init_guess={"mu": 1.0, "sigma": 1.0}
)
ell_t = pm.Lognormal("ell_t", **ell_t_params)

To do that with maxent we need to write something like

dist = pz.Lognormal()
pz.maxent(dist, 0.5, 4, 0.95, plot=False)
ell_t = pm.Lognormal("ell_t", **zip(dist.param_names, dist.params)

Those extra steps are annoying. We should have something that allows a single line, like this:

ell_t_params = pz.maxent(pz.Lognormal(), 0.5, 4, 0.95, return_params=True)
ell_t = pm.Lognormal("ell_t", **ell_t_params)

This will disable the plot and change the output from (axes, opt-object) to dict

What do you think? What other alternatives could we implement?

@aloctavodia
Copy link
Contributor Author

This is related to #518

@aloctavodia
Copy link
Contributor Author

aloctavodia commented Aug 14, 2024

Maybe something even simpler is to get rid of the optimization object, it will not be useful for most users anyway (or we can save it as an attribute) and instead return a tuple with the two elements, first the axes and second the dict with names:vals. So we should be able to do this

_, ell_t_params = pz.maxent(pz.Lognormal(), 0.5, 4, 0.95, plot=False)
ell_t = pm.Lognormal("ell_t", **ell_t_params)

@bwengals
Copy link

bwengals commented Aug 15, 2024

My least favorite thing about

ell_t_params = pm.find_constrained_prior(
    pm.Lognormal, lower=0.5, upper=4.0, mass=0.95, init_guess={"mu": 1.0, "sigma": 1.0}
)
ell_t = pm.Lognormal("ell_t", **ell_t_params)

is having to write pm.Lognormal twice.

Would it be crazy to do something like

ell_t = pz.maxent(pz.Lognormal, 0.5, 4, 0.95, pymc_kwargs={"name": "ell_t"})

or similar, and make it a one liner somehow?

@bwengals
Copy link

I do also like what you had here

_, ell_t_params = pz.maxent(pz.Lognormal(), 0.5, 4, 0.95, plot=False)
ell_t = pm.Lognormal("ell_t", **ell_t_params)

@aloctavodia
Copy link
Contributor Author

aloctavodia commented Aug 15, 2024

Thanks for the input! This makes me think that we need a .to_pymc() method so we can do

ell_t = pz.maxent(pz.LogNormal(), 0.5, 4, 0.95, plot=False).to_pymc("ell_t")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants