joshspeagle / dynesty

Dynamic Nested Sampling package for computing Bayesian posteriors and evidences
https://dynesty.readthedocs.io/
MIT License
347 stars 76 forks source link

Crashes on few live points #424

Closed frgsimpson closed 1 year ago

frgsimpson commented 1 year ago

Dynesty version 2.1

Describe the bug When running n_live_points < 11, the code crashes because it cannot find >10 valid likelihood values (due to a new check added here https://github.com/joshspeagle/dynesty/blob/b237972175009dda0fb5efda32871330a8428ea8/py/dynesty/dynamicsampler.py#L475)

Throws this error: "RuntimeError: After 1000 attempts, we cound not find at least 10 points that have a valid log-likelihood! Please check your prior transform and/or log-likelihood."

Expected behaviour would be either (a) throw an error when the argument is passed in or (b) adjust the tolerance for smaller n_live_points. While we shouldn't expect such a small value to produce meaningful results, it can be a useful setting for running smoke tests, so option (b) is preferable.

segasai commented 1 year ago

Hi,

I am not 100% convinced there is necessary an issue here (or at least I'm not sure there is a better behaviour)

The rationale that I've put in is the code should either run normally or crash early, rather than be in an infinite loop. Also, ideally i'd prefer not to have too many tuning parameters.

The behaviour that you are observing is caused by sampling ~ 10000 times and failing to get at least 10 finite logl values. Going to the extreme, if the logl is -np.inf everywhere except a tiny volume, I think it is reasonable for the code to bail out early.

The only modification that I can think of, is that if after sampling say the current 1000 times we managed to get at least 1 normal sample, a warning can be displayed and sampling can be continued till the minimum number of pts is achieved. But if none have been found after 1000 iterations, I think it is right to quit.

I am not sure I fully understand your proposed options a and b to be honest.

frgsimpson commented 1 year ago

Sorry I wasn't clear - I'm not referring to a case where the likelihood is pathological. It crashes even if the likelihood is completely fine.

segasai commented 1 year ago

Can you give an reproduceable example please ? I dont' quite see how what you tell can happen if logl is finite (almost) everywhere. Because even if you have nlive=2, you should have 2000 valid points after _initialize_livepoints(). (unless I am missing some bug there)

frgsimpson commented 1 year ago

Sure, here's an adaptation of the test code from http://mattpitkin.github.io/samplers-demo/pages/dynesty/ but you can try it out on any example:

` def prior_transform(theta): """ A function defining the tranform between the parameterisation in the unit hypercube to the true parameters.

Args:
    theta (tuple): a tuple containing the parameters.

Returns:
    tuple: a new tuple or array with the transformed parameters.
"""

mprime, cprime = theta # unpack the parameters (in their unit hypercube form)

cmin = -10.  # lower bound on uniform prior on c
cmax = 10.   # upper bound on uniform prior on c

mmu = 0.     # mean of Gaussian prior on m
msigma = 10. # standard deviation of Gaussian prior on m

m = mmu + msigma*ndtri(mprime) # convert back to m
c = cprime*(cmax-cmin) + cmin  # convert back to c

return (m, c)

def loglikelihood_dynesty(theta): """ The log-likelihood function. """

m, c = theta

return m + c

nlive = 8 # number of (initial) live points. Fails when less than 11 bound = 'multi' # use MutliNest algorithm sample = 'rwalk' # use the random walk to draw new samples ndims = 2 # two parameters

dsampler = DynamicNestedSampler(loglikelihood_dynesty, prior_transform, ndims, bound=bound, sample=sample) dsampler.run_nested(nlive_init=nlive) `

I believe the issue lies here:

        # Check to make sure there are enough finite
        # log-likelihood value within the initial set of live
        # points.
        if ngoods > min_npoints:

I believe "ngoods" has a maximum value of n_live_points (as the comment suggests) while min_npoints is 10. So it will always fail here for n_live_points < 11.

segasai commented 1 year ago

Yes, i can see the problem now, thanks. I'll fix it later today/tomorrow.

segasai commented 1 year ago

I think the https://github.com/joshspeagle/dynesty/commit/bc3f25163057846d052ee70c94bb1ff94f6d1cce should fix the issue. Thanks for reporting!