def check_gaussian(sampler_instance): KL_proposer = KL_norm(S1=sampler_instance.model.likelihood["gaussian_mixture"].covs[0], S2=sampler_instance.proposer.get_covariance()) KL_sample = KL_norm(m1=sampler_instance.model.likelihood["gaussian_mixture"].means[0], S1=sampler_instance.model.likelihood["gaussian_mixture"].covs[0], m2=sampler_instance.collection.mean( first=int(sampler_instance.n() / 2)), S2=sampler_instance.collection.cov( first=int(sampler_instance.n() / 2))) print("KL proposer: %g ; KL sample: %g" % (KL_proposer, KL_sample))
def test_example(): # temporarily change working directory to be able to run the files "as is" cwd = os.getcwd() try: os.chdir(docs_src_folder) info_yaml = yaml_load_file("gaussian.yaml") info_yaml.pop("output") globals_example = {} exec( open(os.path.join(docs_src_folder, "create_info.py")).read(), globals_example) assert is_equal_info(info_yaml, globals_example["info"]), ( "Inconsistent info between yaml and interactive.") exec( open(os.path.join(docs_src_folder, "load_info.py")).read(), globals_example) globals_example["info_from_yaml"].pop("output") assert is_equal_info(info_yaml, globals_example["info_from_yaml"]), ( "Inconsistent info between interactive and *loaded* yaml.") # Run the chain -- constant seed so results are the same! globals_example["info"]["sampler"]["mcmc"] = ( globals_example["info"]["sampler"]["mcmc"] or {}) exec( open(os.path.join(docs_src_folder, "run.py")).read(), globals_example) # Run the minimizer -- output doesn't matter. Just checking that it does not fail exec( open(os.path.join(docs_src_folder, "run_min.py")).read(), globals_example) # Analyze and plot -- capture print output stream = StringIO() with stdout_redirector(stream): exec( open(os.path.join(docs_src_folder, "analyze.py")).read(), globals_example) # Checking results mean, covmat = [ globals_example["info"]["likelihood"]["gaussian_mixture"][x] for x in ["means", "covs"] ] assert (KL_norm(m1=mean, S1=covmat, m2=globals_example["mean"], S2=globals_example["covmat"]) <= KL_tolerance ), ("Sampling appears not to have worked too well. Run again?") finally: # Back to the working directory of the tests, just in case os.chdir(cwd)
def test_post_prior(tmpdir): # Generate original chain info = { _output_prefix: os.path.join(str(tmpdir), "gaussian"), _force: True, _params: info_params, kinds.sampler: info_sampler, kinds.likelihood: { "one": None }, _prior: { "gaussian": sampled_pdf } } run(info) info_post = { _output_prefix: info[_output_prefix], _force: True, _post: { _post_suffix: "foo", _post_remove: { _prior: { "gaussian": None } }, _post_add: { _prior: { "target": target_pdf_prior } } } } post(info_post) # Load with GetDist and compare mcsamples = loadMCSamples(info_post[_output_prefix] + _post_ + info_post[_post][_post_suffix]) new_mean = mcsamples.mean(["a", "b"]) new_cov = mcsamples.getCovMat().matrix assert abs(KL_norm(target["mean"], target["cov"], new_mean, new_cov)) < 0.02
def test_post_prior(tmpdir): # Generate original chain info = { "output": os.path.join(str(tmpdir), "gaussian"), "force": True, "params": info_params, "sampler": info_sampler, "likelihood": { "one": None }, "prior": { "gaussian": sampled_pdf } } run(info) info_post = { "output": info["output"], "force": True, "post": { "suffix": "foo", "remove": { "prior": { "gaussian": None } }, "add": { "prior": { "target": target_pdf } } } } post(info_post) # Load with GetDist and compare mcsamples = loadMCSamples(info_post["output"] + "_post_" + info_post["post"]["suffix"]) new_mean = mcsamples.mean(["a", "b"]) new_cov = mcsamples.getCovMat().matrix assert abs(KL_norm(target["mean"], target["cov"], new_mean, new_cov)) < 0.02
def body_of_test(dimension=1, n_modes=1, info_sampler={}, tmpdir="", modules=None): comm = MPI.COMM_WORLD rank = comm.Get_rank() # Info of likelihood and prior ranges = np.array([[-1, 1] for _ in range(dimension)]) while True: info = info_random_gaussian_mixture(ranges=ranges, n_modes=n_modes, prefix="a_", O_std_min=O_std_min, O_std_max=O_std_max, derived=True) if n_modes == 1: break means = info["likelihood"]["gaussian_mixture"]["means"] distances = chain(*[[np.linalg.norm(m1 - m2) for m2 in means[i + 1:]] for i, m1 in enumerate(means)]) if min(distances) >= distance_factor * O_std_max: break if rank == 0: print("Original mean of the gaussian mode:") print(info["likelihood"]["gaussian_mixture"]["means"]) print("Original covmat of the gaussian mode:") print(info["likelihood"]["gaussian_mixture"]["covs"]) info[_sampler] = info_sampler if list(info_sampler.keys())[0] == "mcmc": if "covmat" in info_sampler["mcmc"]: info[_sampler]["mcmc"]["covmat_params"] = (list( info["params"].keys())[:dimension]) info[_debug] = False info[_debug_file] = None info[_output_prefix] = getattr(tmpdir, "realpath()", lambda: tmpdir)() if modules: info[_path_install] = process_modules_path(modules) # Delay to one chain to check that MPI communication of the sampler is non-blocking # if rank == 1: # info["likelihood"]["gaussian_mixture"]["delay"] = 0.1 updated_info, products = run(info) # Done! --> Tests if rank == 0: if list(info_sampler.keys())[0] == "mcmc": ignore_rows = 0.5 else: ignore_rows = 0 results = loadCobayaSamples(updated_info, products["sample"], ignore_rows=ignore_rows, name_tag="sample") clusters = None if "clusters" in products: clusters = [ loadCobayaSamples(updated_info, products["clusters"][i]["sample"], name_tag="cluster %d" % (i + 1)) for i in products["clusters"] ] # Plots! try: import getdist.plots as gdplots from getdist.gaussian_mixtures import MixtureND mixture = MixtureND( info[_likelihood]["gaussian_mixture"]["means"], info[_likelihood]["gaussian_mixture"]["covs"], names=[p for p in info[_params] if "deriv" not in p], label="truth") g = gdplots.getSubplotPlotter() to_plot = [mixture, results] if clusters: to_plot = to_plot + clusters g.triangle_plot(to_plot, ) g.export("test.png") except: print("Plotting failed!") # 1st test: KL divergence if n_modes == 1: cov_sample, mean_sample = results.getCov(), results.getMeans() KL_final = KL_norm( m1=info[_likelihood]["gaussian_mixture"]["means"][0], S1=info[_likelihood]["gaussian_mixture"]["covs"][0], m2=mean_sample[:dimension], S2=cov_sample[:dimension, :dimension]) print("Final KL: ", KL_final) assert KL_final <= KL_tolerance # 2nd test: clusters else: if "clusters" in products: assert len(products["clusters"].keys()) >= n_modes, ( "Not all clusters detected!") for c2 in clusters: cov_c2, mean_c2 = c2.getCov(), c2.getMeans() KLs = [ KL_norm(m1=info[_likelihood]["gaussian_mixture"] ["means"][i_c1], S1=info[_likelihood]["gaussian_mixture"] ["covs"][i_c1], m2=mean_c2[:dimension], S2=cov_c2[:dimension, :dimension]) for i_c1 in range(n_modes) ] extra_tol = 4 * n_modes if n_modes > 1 else 1 assert min(KLs) <= KL_tolerance * extra_tol else: assert 0, "Could not check sample convergence: multimodal but no clusters" # 3rd test: Evidence if "logZ" in products: logZprior = sum(np.log(ranges[:, 1] - ranges[:, 0])) assert (products["logZ"] - logZ_nsigmas * products["logZstd"] < -logZprior < products["logZ"] + logZ_nsigmas * products["logZstd"])
def test_post_likelihood(tmpdir): """ Swaps likelihood "gaussian" for "target". It also tests aggregated chi2's by removing and adding a likelihood to an existing type. """ # Generate original chain info_params_local = deepcopy(info_params) info_params_local["dummy"] = 0 dummy_loglike_add = 0.1 dummy_loglike_remove = 0.01 info = { _output_prefix: os.path.join(str(tmpdir), "gaussian"), _force: True, _params: info_params_local, kinds.sampler: info_sampler, kinds.likelihood: { "gaussian": { "external": sampled_pdf, "type": "A" }, "dummy": { "external": lambda dummy: 1, "type": "B" }, "dummy_remove": { "external": lambda dummy: dummy_loglike_add, "type": "B" } } } info_run_out, sampler_run = run(info) info_post = { _output_prefix: info[_output_prefix], _force: True, _post: { _post_suffix: "foo", _post_remove: { kinds.likelihood: { "gaussian": None, "dummy_remove": None } }, _post_add: { kinds.likelihood: { "target": { "external": target_pdf, "type": "A", "output_params": ["cprime"] }, "dummy_add": { "external": lambda dummy: dummy_loglike_remove, "type": "B" } } } } } info_post_out, products_post = post(info_post) # Load with GetDist and compare mcsamples = loadMCSamples(info_post[_output_prefix] + _post_ + info_post[_post][_post_suffix]) new_mean = mcsamples.mean(["a", "b"]) new_cov = mcsamples.getCovMat().matrix assert abs(KL_norm(target["mean"], target["cov"], new_mean, new_cov)) < 0.02 assert np.allclose(products_post["sample"]["chi2__A"], products_post["sample"]["chi2__target"]) assert np.allclose( products_post["sample"]["chi2__B"], products_post["sample"]["chi2__dummy"] + products_post["sample"]["chi2__dummy_add"])
def body_of_sampler_test(info_sampler: SamplersDict, dimension=1, n_modes=1, tmpdir="", packages_path=None, skip_not_installed=False, fixed=False, random_state=None): # Info of likelihood and prior ranges = np.array([[-1, 1] for _ in range(dimension)]) if fixed: info = fixed_info.copy() else: info = generate_random_info(n_modes, ranges, random_state=random_state) if mpi.is_main_process(): print("Original mean of the gaussian mode:") print(info["likelihood"]["gaussian_mixture"]["means"]) print("Original covmat of the gaussian mode:") print(info["likelihood"]["gaussian_mixture"]["covs"]) info["sampler"] = info_sampler sampler_name = list(info_sampler)[0] if random_state is not None: info_sampler[sampler_name]["seed"] = random_state.integers(0, 2**31) if sampler_name == "mcmc": if "covmat" in info_sampler["mcmc"]: info["sampler"]["mcmc"]["covmat_params"] = (list( info["params"])[:dimension]) info["debug"] = False info["debug_file"] = None info["output"] = os.path.join(tmpdir, 'out_chain') if packages_path: info["packages_path"] = process_packages_path(packages_path) updated_info, sampler = install_test_wrapper(skip_not_installed, run, info) products = sampler.products() products["sample"] = mpi.gather(products["sample"]) # Done! --> Tests if mpi.is_main_process(): if sampler_name == "mcmc": ignore_rows = 0.5 else: ignore_rows = 0 results = MCSamplesFromCobaya(updated_info, products["sample"], ignore_rows=ignore_rows, name_tag="sample") clusters = None if "clusters" in products: clusters = [ MCSamplesFromCobaya(updated_info, products["clusters"][i]["sample"], name_tag="cluster %d" % (i + 1)) for i in products["clusters"] ] # Plots! if not is_travis(): try: import getdist.plots as gdplots from getdist.gaussian_mixtures import MixtureND sampled_params = [ p for p, v in info["params"].items() if "prior" not in v ] mixture = MixtureND( info["likelihood"]["gaussian_mixture"]["means"], info["likelihood"]["gaussian_mixture"]["covs"], names=sampled_params, label="truth") g = gdplots.getSubplotPlotter() to_plot = [mixture, results] if clusters: to_plot += clusters g.triangle_plot(to_plot, params=sampled_params) g.export("test.png") except: print("Plotting failed!") # 1st test: KL divergence if n_modes == 1: cov_sample, mean_sample = results.getCov( dimension), results.getMeans() KL_final = KL_norm( m1=info["likelihood"]["gaussian_mixture"]["means"][0], S1=info["likelihood"]["gaussian_mixture"]["covs"][0], m2=mean_sample[:dimension], S2=cov_sample) print("Final KL: ", KL_final) assert KL_final <= KL_tolerance # 2nd test: clusters else: if "clusters" in products: assert len(products["clusters"]) >= n_modes, ( "Not all clusters detected!") for i, c2 in enumerate(clusters): cov_c2, mean_c2 = c2.getCov(), c2.getMeans() KLs = [ KL_norm(m1=info["likelihood"]["gaussian_mixture"] ["means"][i_c1], S1=info["likelihood"]["gaussian_mixture"] ["covs"][i_c1], m2=mean_c2[:dimension], S2=cov_c2[:dimension, :dimension]) for i_c1 in range(n_modes) ] extra_tol = 4 * n_modes if n_modes > 1 else 1 print("Final KL for cluster %d: %g", i, min(KLs)) assert min(KLs) <= KL_tolerance * extra_tol else: assert 0, "Could not check sample convergence: multimodal but no clusters" # 3rd test: Evidence if "logZ" in products: logZprior = sum(np.log(ranges[:, 1] - ranges[:, 0])) assert (products["logZ"] - logZ_nsigmas * products["logZstd"] < -logZprior < products["logZ"] + logZ_nsigmas * products["logZstd"])