JohannesBuchner / UltraNest

Fit and compare complex models reliably and rapidly. Advanced nested sampling.
https://johannesbuchner.github.io/UltraNest/
Other
142 stars 30 forks source link

Example of derived_param_names #88

Closed JorisDeRidder closed 1 year ago

JorisDeRidder commented 1 year ago

Would it be possible to provide an example on how to use derived_param_names? I can see in the API that the feature of derived parameters is present, but its use is not very clear to me.

JohannesBuchner commented 1 year ago

If you provide also derived_param_names=["a", "b"] then the prior transform should return two additional columns with these parameters.

JorisDeRidder commented 1 year ago

Still not very clear, I'm afraid. Following your explanation, the following example modelling a simple straight line:

def my_prior_transform(cube):
    params = cube.copy()
    params[0] = sp.stats.norm.ppf(cube[0], 0, 10)                              # intercept
    params[1] = sp.stats.uniform.ppf(cube[1], -np.pi/2, np.pi)                 # alpha: loc,scale -> [loc, loc+scale] = [-pi/2, +pi/2]
    params[2] = sp.stats.halfcauchy.ppf(cube[2], 0.0, 3.0)                     # sigma
    params[3] = np.tan(params[1])                                              # slope
    return params

def my_loglikelihood(params):
    intercept, alpha, sigma, slope = params
    mu = intercept + slope * xobs
    loglike = sp.stats.norm.logpdf(yobs, mu, sigma).sum()
    return loglike

param_names = ["intercept", "alpha", "sigma"]
derived_param_names = ["slope"]
sampler = ultranest.ReactiveNestedSampler(param_names, my_loglikelihood, my_prior_transform, derived_param_names)
results = sampler.run()
sampler.print_results()

gives the error message:

IndexError: index 3 is out of bounds for axis 0 with size 3

pointing to the line with params[[3] = ....
What I'm trying to achieve here is the equivalent of a "Deterministic" in PyMC or a "transformed_parameter" in Stan, so that I can put a prior on the angle, but include the corresponding slope in the trace.

JohannesBuchner commented 1 year ago

This line is wrong: params = cube.copy(), because you need a larger array than cube.

JohannesBuchner commented 1 year ago

params = np.empty(4) should work, for example.

JorisDeRidder commented 1 year ago

That solved the problem. Thanks!