mattpitkin / samplers-demo

A demonstration of various Python MCMC samplers
MIT License
7 stars 0 forks source link

Add UltraNest to demonstration #1

Closed mattpitkin closed 6 years ago

mattpitkin commented 6 years ago

It might be nice to add @johannesbuchner's UltraNest to the demonstration, just showing use of the RadFriends algorithm. At the moment the UltraNest repo doesn't build due to the nested_sampling/samplers/hamiltonian not existing (I could fork it, remove the offending line, and send a pull request), so it's not as simple to add to the Docker builds yet. It also seems that the Python code does not actually have an interface to the actual ultranest algorithm yet, but I could just use a single sampler (e.g. the standalone RadFriends algorithm).

Also, I could add a link to the UltraNest test suite demonstration to the notebook.

mattpitkin commented 6 years ago

I'd probably also need the johannesbuchner/UltraNest#1 Python 3 compatibility request to also be merged.

JohannesBuchner commented 6 years ago

I merged the two pull-request and it seems to run for me now on Python 3. Could you check if it works for you?

JohannesBuchner commented 6 years ago

You probably want either nested_sampling.samplers.hiermetriclearn.MetricLearningFriendsConstrainer set up something like this:

constrainer = MetricLearningFriendsConstrainer( 
    metriclearner='truncatedscaling', force_shrink=True, 
    rebuild_every=50, verbose=False)

The older alternative is the nested_sampling.samplers.friends.FriendsConstrainer which is RadFriends with radial metric, i.e. dimensions are the same scale in each dimension, thus less efficient.

def priortransform(u):
    # scale unit cube to physical parameters
    return u

def loglikelihood(u):
    x = 10 * pi * numpy.asarray(u)
    l = (2 + cos(x[0]/2)*cos(x[1]/2))**5
    return l

from nested_sampling.nested_integrator import nested_integrator
from nested_sampling.nested_sampler import NestedSampler
from nested_sampling.termination_criteria import TerminationCriterion, MaxErrorCriterion, BootstrappedCriterion, RememberingBootstrappedCriterion, DecliningBootstrappedCriterion, NoisyBootstrappedCriterion, NoiseDetectingBootstrappedCriterion
from nested_sampling.postprocess import equal_weighted_posterior, marginal_plots

termination = TerminationCriterion(tolerance=0.5, maxRemainderFraction=0.001)
sampler = NestedSampler(nlive_points = nlive_points, 
    priortransform=priortransform, loglikelihood=loglikelihood, 
    draw_constrained = constrainer.draw_constrained, ndim=ndim,
    constrainer_get_Lmax = constrainer_get_Lmax)
constrainer.sampler = sampler
result = nested_integrator(sampler=sampler, max_samples=max_samples,
    terminationcriterion=termination)

print(result['logZ'], result['logZerr'], result['niterations'])
# get posterior points
posterioru, posteriorx = equal_weighted_posterior(result['weights'])
mattpitkin commented 6 years ago

Thanks @JohannesBuchner . If I try:

Python 3.5.2 (default, Nov 23 2017, 16:37:01) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from nested_sampling.samplers.hiermetriclearn import MetricLearningFriendsConstrainer

I get the error:

Using slow, high-memory neighborhood function nearest_rdistance_guess because: /usr/local/lib/python3.5/dist-packages/nested_sampling/clustering/cneighbors.so: cannot open shared object file: No such file or directory
Using slow, high-memory neighborhood function nearest_rdistance_guess because: /usr/local/lib/python3.5/dist-packages/nested_sampling/clustering/cclustering.so: cannot open shared object file: No such file or directory
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.5/dist-packages/nested_sampling/samplers/hiermetriclearn.py", line 6, in <module>
    from nested_sampling.clustering.sdml import IdentityMetric, SimpleScaling, TruncatedScaling, MahalanobisMetric, TruncatedMahalanobisMetric, SDML
  File "/usr/local/lib/python3.5/dist-packages/nested_sampling/clustering/sdml.py", line 319, in <module>
    import metric_learn
ImportError: No module named 'metric_learn'
mattpitkin commented 6 years ago

I had a look and I imagine I just need to install this repo. I'll give that a go and try again.

mattpitkin commented 6 years ago

With metric-learn installed I now get the error:

from nested_sampling.samplers.hiermetriclearn import MetricLearningFriendsConstrainer
Using slow, high-memory neighborhood function nearest_rdistance_guess because: /usr/local/lib/python3.5/dist-packages/nested_sampling/clustering/cneighbors.so: cannot open shared object file: No such file or directory
Using slow, high-memory neighborhood function nearest_rdistance_guess because: /usr/local/lib/python3.5/dist-packages/nested_sampling/clustering/cclustering.so: cannot open shared object file: No such file or directory

It looks like the setup script is not building and copying the libraries.

JohannesBuchner commented 6 years ago

Hmm, yes, I have not figured out how to do that. If you keep the nested_sampling directory and go to that folder (clustering) and run make, it should build the .so file for you. Pointing PYTHONPATH to the folder containing nested_sampling should allow you to run the accelerated version.

PS: metric_learn is also on pypi.

JohannesBuchner commented 6 years ago

BTW, That's not an error message, things should still work. It's just that it could be faster.

mattpitkin commented 6 years ago

Thanks for the advice and for the updates to the UltraNest repo. I've now got a bit further, but...

...I'm now having issues with the progressbar. I've installed progressbar2 from PyPI, as progressbar does not seem to install for Python >= 3.5. When running this with your example above it fails with a complaint (in nested_integrator) about the progressbar.Counter('%f') widget requiring a float rather than an int. Changing it to instead be progressbar.Counter('%d') then gets a complaint about trying to pass it a dict. If I remove the progressbar.Counter('%f') widget completely, I then hit the following error:

In [1]: %run test_nested_sampler.py
|51/100050 samples+1024/1074|lnZ = 235.56 +- 0.055 + 2.006|L=1.92 @ [0.167  0.3917] 51%Elapsed Time: 0:00:00---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
/work/test_nested_sampler.py in <module>()
     29 constrainer.sampler = sampler
     30 
---> 31 result = nested_integrator(sampler=sampler, max_samples=max_samples, terminationcriterion=termination)
     32 

/usr/local/lib/python3.5/dist-packages/nested_sampling/nested_integrator.py in nested_integrator(sampler, terminationcriterion, check_every, max_samples)
     60                 logZerr = (H / sampler.nlive_points)**0.5
     61 
---> 62                 pbar.update(i)
     63 
     64                 # expected number of iterations:

/usr/local/lib/python3.5/dist-packages/progressbar/bar.py in update(self, value, force, **kwargs)
    554                 raise ValueError(
    555                     'Value %s is out of range, should be between %s and %s'
--> 556                     % (value, self.min_value, self.max_value))
    557             else:
    558                 self.max_value = value

ValueError: Value 101 is out of range, should be between 0 and 100

Any ideas?

The test_nested_sampler.py script is just essentially what you had above:

from nested_sampling.samplers.hiermetriclearn import MetricLearningFriendsConstrainer
import numpy as np

ndim = 2
nlive_points = 1024
max_samples = 2000

constrainer = MetricLearningFriendsConstrainer( metriclearner='truncatedscaling', force_shrink=True, re
build_every=50, verbose=False )

def priortransform(u):
    return u

def loglikelihood(u):
    x = 10 * np.pi * np.asarray(u)
    l = (2 + np.cos(x[0]/2)*np.cos(x[1]/2))**5
    return l

from nested_sampling.nested_integrator import nested_integrator
from nested_sampling.nested_sampler import NestedSampler
from nested_sampling.termination_criteria import TerminationCriterion, MaxErrorCriterion, BootstrappedCriterion, RememberingBootstrappedCriterion, DecliningBootstrappedCriterion, NoisyBootstrappedCriterion, NoiseDetectingBootstrappedCriterion
from nested_sampling.postprocess import equal_weighted_posterior, marginal_plots

termination = TerminationCriterion(tolerance=0.5, maxRemainderFraction=0.001)

constrainer_get_Lmax = constrainer.get_Lmax

sampler = NestedSampler(nlive_points = nlive_points, priortransform=priortransform, loglikelihood=loglikelihood, draw_constrained = constrainer.draw_constrained, ndim=ndim, constrainer_get_Lmax = constrainer_get_Lmax)

constrainer.sampler = sampler

result = nested_integrator(sampler=sampler, max_samples=max_samples, terminationcriterion=termination)
JohannesBuchner commented 6 years ago

try progressbar-latest instead.

mattpitkin commented 6 years ago

try progressbar-latest instead.

Yep, thanks. It all works now! :+1: