def figure2(): """Make a figure for MCMC inference """ num_mcmc_iters = 10000 def stimulus(t): return (1 * (t < 50)) + (-100 * (t >= 50) & (t < 75)) + (1 * (t >= 75)) # Generate data y0 = np.array([0.0, 0.0]) m = diffeqinf.DampedOscillator(stimulus, y0, 'RK45') m.set_tolerance(1e-8) true_params = [1.0, 0.2, 1.0] times = np.linspace(0, 100, 500) y = m.simulate(true_params, times) y += np.random.normal(0, 0.01, len(times)) # Run inference with correct model problem = pints.SingleOutputProblem(m, times, y) likelihood = pints.GaussianLogLikelihood(problem) prior = pints.UniformLogPrior([0] * 4, [1e6] * 4) posterior = pints.LogPosterior(likelihood, prior) x0 = [true_params + [0.01]] * 3 mcmc = pints.MCMCController(posterior, 3, x0) mcmc.set_max_iterations(num_mcmc_iters) chains_correct = mcmc.run() # Run inference with incorrect model m.set_tolerance(1e-2) problem = pints.SingleOutputProblem(m, times, y) likelihood = pints.GaussianLogLikelihood(problem) prior = pints.UniformLogPrior([0] * 4, [1e6] * 4) posterior = pints.LogPosterior(likelihood, prior) mcmc = pints.MCMCController(posterior, 3, x0) mcmc.set_max_iterations(num_mcmc_iters) chains_incorrect = mcmc.run() # Plot MCMC chains pints.plot.trace(chains_incorrect) plt.show() # Plot posteriors diffeqinf.plot.plot_grouped_parameter_posteriors( [chains_correct[0, num_mcmc_iters // 2:, :]], [chains_incorrect[0, num_mcmc_iters // 2:, :]], [chains_incorrect[1, num_mcmc_iters // 2:, :]], [chains_incorrect[2, num_mcmc_iters // 2:, :]], true_model_parameters=true_params, method_names=[ 'Correct', 'PoorTol_Chain1', 'PoorTol_Chain2', 'PoorTol_Chain3' ], parameter_names=['k', 'c', 'm'], fname=None) plt.show()
def test_single_chain(self): # tests that single chain is broken up into two bits xs = [self.real_parameters * 0.9] mcmc = pints.MCMCController(self.log_posterior, 1, xs, method=pints.HaarioBardenetACMC) mcmc.set_max_iterations(200) mcmc.set_initial_phase_iterations(50) mcmc.set_log_to_screen(False) chains = mcmc.run() results = pints.MCMCSummary(chains) chains1 = results.chains() self.assertEqual(chains[0].shape[0], chains1[0].shape[0]) self.assertEqual(chains[0].shape[1], chains1[0].shape[1]) self.assertEqual(chains[0][10, 1], chains[0][10, 1]) self.assertEqual(results.time(), None) self.assertEqual(results.ess_per_second(), None) self.assertTrue(len(results.ess()), 3) self.assertTrue(len(results.mean()), 3) self.assertTrue(len(results.rhat()), 3) self.assertTrue(len(results.std()), 3) # check positive quantities are so for i in range(3): self.assertTrue(results.ess()[i] > 0) self.assertTrue(results.ess()[i] < 1000) self.assertTrue(results.rhat()[i] > 0) self.assertTrue(results.std()[i] > 0) self.assertTrue(results.mean()[i] > 0) # check means are vaguely near true values self.assertTrue(np.abs(results.mean()[0] - 0.015) < 0.5) self.assertTrue(np.abs(results.mean()[1] - 500) < 200) self.assertTrue(np.abs(results.mean()[2] - 10) < 30) # check quantiles object quantiles = results.quantiles() self.assertEqual(quantiles.shape[0], 5) self.assertEqual(quantiles.shape[1], 3) for i in range(5): for j in range(3): self.assertTrue(quantiles[i, j] > 0) # Test with odd number of iterations mcmc = pints.MCMCController(self.log_posterior, 1, xs, method=pints.HaarioBardenetACMC) mcmc.set_max_iterations(99) mcmc.set_initial_phase_iterations(40) mcmc.set_log_to_screen(False) chains = mcmc.run() results = pints.MCMCSummary(chains)
def test_build_tree_nan(self): # This method gives nan in the hamiltonian_dash # in the build_tree function # Needed for coverage model = pints.toy.LogisticModel() real_parameters = np.array([0.015, 20]) times = np.linspace(0, 1000, 50) org_values = model.simulate(real_parameters, times) np.random.seed(1) noise = 0.1 values = org_values + np.random.normal(0, noise, org_values.shape) problem = pints.SingleOutputProblem(model, times, values) log_likelihood = pints.GaussianKnownSigmaLogLikelihood(problem, noise) log_prior = pints.UniformLogPrior([0.0001, 1], [1, 500]) log_posterior = pints.LogPosterior(log_likelihood, log_prior) xs = [[0.36083914, 1.99013825]] nuts_mcmc = pints.MCMCController(log_posterior, len(xs), xs, method=pints.NoUTurnMCMC) nuts_mcmc.set_max_iterations(50) nuts_mcmc.set_log_to_screen(False) np.random.seed(5) nuts_chains = nuts_mcmc.run() self.assertFalse(np.isnan(np.sum(nuts_chains)))
def test_model_that_gives_nan(self): # This model will return a nan in the gradient evaluation, which # originally tripped up the find_reasonable_epsilon function in nuts. # Run it for a bit so that we get coverage on the if statement! model = pints.toy.LogisticModel() real_parameters = model.suggested_parameters() times = model.suggested_parameters() org_values = model.simulate(real_parameters, times) np.random.seed(1) noise = 0.2 values = org_values + np.random.normal(0, noise, org_values.shape) problem = pints.SingleOutputProblem(model, times, values) log_likelihood = pints.GaussianKnownSigmaLogLikelihood(problem, noise) log_prior = pints.UniformLogPrior([0.01, 40], [0.2, 60]) log_posterior = pints.LogPosterior(log_likelihood, log_prior) xs = [real_parameters * 1.1] nuts_mcmc = pints.MCMCController(log_posterior, len(xs), xs, method=pints.NoUTurnMCMC) nuts_mcmc.set_max_iterations(10) nuts_mcmc.set_log_to_screen(False) nuts_chains = nuts_mcmc.run() self.assertFalse(np.isnan(np.sum(nuts_chains)))
def run(model, real_parameters, noise_used, log_prior_used): # Create some toy data times = np.linspace(1, 1000, 50) org_values = model.simulate(real_parameters, times) # Add noise noise = 10 values = org_values + np.random.normal(0, noise, org_values.shape) real_parameters = np.array(real_parameters) # Create an object with links to the model and time series problem = pints.SingleOutputProblem(model, times, values) # Create a log-likelihood function (adds an extra parameter!) log_likelihood_used = pints.GaussianKnownSigmaLogLikelihood(problem, [noise_used]) # Create a uniform prior over both the parameters and the new noise variable # Create a posterior log-likelihood (log(likelihood * prior)) log_posterior = pints.LogPosterior(log_likelihood_used, log_prior_used) # Choose starting points for 3 mcmc chains xs = [ real_parameters, real_parameters * 1.01, real_parameters * 0.99, ] # Create mcmc routine with four chains mcmc = pints.MCMCController(log_posterior, 3, xs, method=pints.HaarioACMC) sample_size = 4000 # Add stopping criterion mcmc.set_max_iterations(sample_size) # Start adapting after 1000 iterations mcmc.set_initial_phase_iterations(sample_size//4) # Disable logging mode mcmc.set_log_to_screen(False) # Run! print('Running...') chains = mcmc.run() print('Done!') s = sample_size//4+1 #HMC: s = 1 b = False while s < sample_size: chains_cut = chains[:,sample_size//4:s+1] rhat = pints.rhat(chains_cut) s+=1 if rhat[0] < 1.05: b = True break print(s) return chains[0][s:][:, 0]
def main(): #constants indices_to_use = [[1, 2499], [2549, 2999], [3049, 4999], [5049, 14999], [15049, 19999], [20049, 29999], [30049, 64999], [65049, 69999], [70049, -1]] self.starting_parameters = [ 2.26E-04, 0.0699, 3.45E-05, 0.05462, 0.0873, 8.92E-03, 5.150E-3, 0.03158, 0.1524 ] plt.rcParams['axes.axisbelow'] = True # Check input arguments parser = argparse.ArgumentParser( description='Plot sensitivities of the Beattie model') parser = get_parser(data_reqd=True) parser.add_argument("-n", "--no_chains", default=5, help="number of chains to use") parser.add_argument("-l", "--chain_length", default=1000, help="length of chain to use") args = parser.parse_args() data = pd.read_csv(args.data_file_path, delim_whitespace=True) times = data["time"] data = data["current"].values print("outputting to {}".format(args.output)) # Create output directory if not os.path.exists(args.output): os.mkdir(args.output) if not os.path.exists(args.data_file_path): print("Input file not provided. Doing nothing.") return par = Params() skip = int(par.timestep / 0.1) dat = extract_times(data, indices_to_use, skip) model = PintsWrapper(data, par, args, times) mcmc = pints.MCMCController(model, args.no_chains, args.no_chains * [starting_parameters], method=pints.HaarioBardenetACMC) mcmc.set_max_iterations(args.chain_length) chains = mcmc.run() print(chains)
def test_initial_phase(self): # 2 chains x0 = np.array(self.real_parameters) * 1.1 x1 = np.array(self.real_parameters) * 1.15 xs = [x0, x1] nchains = len(xs) # Initial phase mcmc = pints.MCMCController(self.log_posterior, nchains, xs) self.assertTrue(mcmc.method_needs_initial_phase()) self.assertNotEqual(mcmc.initial_phase_iterations(), 10) mcmc.set_initial_phase_iterations(10) self.assertEqual(mcmc.initial_phase_iterations(), 10) self.assertRaisesRegex(ValueError, 'negative', mcmc.set_initial_phase_iterations, -1) for sampler in mcmc._samplers: self.assertTrue(sampler.in_initial_phase()) mcmc.set_max_iterations(9) mcmc.set_log_to_screen(False) mcmc.run() for sampler in mcmc._samplers: self.assertTrue(sampler.in_initial_phase()) mcmc = pints.MCMCController(self.log_posterior, nchains, xs) mcmc.set_initial_phase_iterations(10) for sampler in mcmc._samplers: self.assertTrue(sampler.in_initial_phase()) mcmc.set_max_iterations(11) mcmc.set_log_to_screen(False) mcmc.run() for sampler in mcmc._samplers: self.assertFalse(sampler.in_initial_phase()) # No initial phase mcmc = pints.MCMCController(self.log_posterior, nchains, xs) mcmc.set_initial_phase_iterations(0) mcmc.set_max_iterations(1) mcmc.set_log_to_screen(False) mcmc.run() for sampler in mcmc._samplers: self.assertFalse(sampler.in_initial_phase())
def test_logging(self): # Test logging includes name. x = [self.real_parameters] * 3 mcmc = pints.MCMCController( self.log_posterior, 3, x, method=pints.RaoBlackwellACMC) mcmc.set_max_iterations(5) with StreamCapture() as c: mcmc.run() text = c.text() self.assertIn('Rao-Blackwell adaptive covariance MCMC', text)
def test_logging(self): # Test logging includes name and custom fields. log_pdf = pints.toy.GaussianLogPDF([5, 5], [[4, 1], [1, 3]]) x0 = [np.array([2, 2]), np.array([8, 8])] mcmc = pints.MCMCController(log_pdf, 2, x0, method=pints.NoUTurnMCMC) mcmc.set_max_iterations(5) with StreamCapture() as c: mcmc.run() text = c.text() self.assertIn('No-U-Turn MCMC', text)
def test_logging(self): # Test logging includes name. x = [self.real_parameters] * 3 mcmc = pints.MCMCController( self.log_posterior, 3, x, method=pints.DramACMC) mcmc.set_max_iterations(5) with StreamCapture() as c: mcmc.run() text = c.text() self.assertIn('Delayed Rejection Adaptive Metropolis (Dram) MCMC', text)
def test_logging(self): """ Test logging includes name and custom fields. """ x = [self.real_parameters] * 3 mcmc = pints.MCMCController( self.log_posterior, 3, x, method=pints.DreamMCMC) mcmc.set_max_iterations(5) with StreamCapture() as c: mcmc.run() text = c.text() self.assertIn('DREAM', text)
def test_logging(self): # Test logging includes name and custom fields. log_pdf = pints.toy.GaussianLogPDF([5, 5], [[4, 1], [1, 3]]) x0 = [np.array([2, 2]), np.array([8, 8])] mcmc = pints.MCMCController(log_pdf, 2, x0, method=pints.MALAMCMC) mcmc.set_max_iterations(5) with StreamCapture() as c: mcmc.run() text = c.text() self.assertIn('Metropolis-Adjusted Langevin Algorithm (MALA)', text) self.assertIn(' Accept.', text)
def setUpClass(cls): """ Set up problem for tests. """ # Create toy model cls.model = toy.LogisticModel() cls.real_parameters = [0.015, 500] cls.times = np.linspace(0, 1000, 1000) cls.values = cls.model.simulate(cls.real_parameters, cls.times) # Add noise cls.noise = 10 cls.values += np.random.normal(0, cls.noise, cls.values.shape) cls.real_parameters.append(cls.noise) cls.real_parameters = np.array(cls.real_parameters) # Create an object with links to the model and time series cls.problem = pints.SingleOutputProblem(cls.model, cls.times, cls.values) # Create a uniform prior over both the parameters and the new noise # variable cls.log_prior = pints.UniformLogPrior([0.01, 400, cls.noise * 0.1], [0.02, 600, cls.noise * 100]) # Create a log likelihood cls.log_likelihood = pints.GaussianLogLikelihood(cls.problem) # Create an un-normalised log-posterior (log-likelihood + log-prior) cls.log_posterior = pints.LogPosterior(cls.log_likelihood, cls.log_prior) # Run MCMC sampler xs = [ cls.real_parameters * 1.1, cls.real_parameters * 0.9, cls.real_parameters * 1.15, ] mcmc = pints.MCMCController(cls.log_posterior, 3, xs, method=pints.HaarioBardenetACMC) mcmc.set_max_iterations(200) mcmc.set_initial_phase_iterations(50) mcmc.set_log_to_screen(False) start = time.time() cls.chains = mcmc.run() end = time.time() cls.time = end - start
def test_logging(self): # Test logging includes name and custom fields. x = [self.real_parameters] * 3 mcmc = pints.MCMCController(self.log_posterior, 3, x, method=pints.MetropolisRandomWalkMCMC) mcmc.set_max_iterations(5) with StreamCapture() as c: mcmc.run() text = c.text() self.assertIn('Metropolis random walk MCMC', text) self.assertIn(' Accept. ', text)
def test_logging(self): # Test logging includes name and custom fields. x = [self.real_parameters] * 3 mcmc = pints.MCMCController( self.log_posterior, 3, x, method=pints.PopulationMCMC) mcmc.set_max_iterations(5) with StreamCapture() as c: mcmc.run() text = c.text() self.assertIn('Population MCMC', text) self.assertIn(' i ', text) self.assertIn(' j ', text) self.assertIn(' Ex. ', text)
def run_mcmc(self, num_mcmc_samples, num_chains, iprint=True, method=pints.PopulationMCMC, enforce_convergence=False): """Run MCMC to obtain posterior samples. Parameters ---------- num_mcmc_samples : int The total number of MCMC samples to run num_chains : int Number of separate MCMC chains to run iprint : bool, optional (True) Whether or not to print iteration number method : type, optional (pints.PopulationMCMC) Which MCMC method (pints.MCMCSampler) to use enforce_convergence : bool, optional (False) Whether to raise an error if the Rhat convergence statistic is less than 1.05. Returns ------- np.ndarray MCMC chain, with shape (num_samples, num_parameters) """ starting_points = self.get_initial_conditions(num_chains) mcmc = pints.MCMCController(self.posterior, num_chains, starting_points, method=method) mcmc.set_max_iterations(num_mcmc_samples) mcmc.set_log_to_screen(iprint) chains = mcmc.run() # Check convergence rs = pints.rhat(chains[:, num_mcmc_samples // 2:, :]) if max(rs) > 1.05: message = 'MCMC chains failed to converge, R={}'.format(str(rs)) if enforce_convergence: raise RuntimeError(message) else: warnings.warn(message) # Get one chain and discard burn in chain = chains[0][num_mcmc_samples // 2:] return chain
def test_logging(self): # Test logging includes acceptance rate, evaluations, iterations and # time. x = [self.real_parameters] * 3 mcmc = pints.MCMCController( self.log_posterior, 3, x, method=pints.HaarioACMC) mcmc.set_max_iterations(5) with StreamCapture() as c: mcmc.run() text = c.text() self.assertIn('Accept.', text) self.assertIn('Eval.', text) self.assertIn('Iter.', text) self.assertIn('Time m:s', text)
def test_logging(self): """ Test logging includes name and acceptance rate. """ x = [self.real_parameters] * 3 mcmc = pints.MCMCController(self.log_posterior, 3, x, method=pints.AdaptiveCovarianceMCMC) mcmc.set_max_iterations(5) with StreamCapture() as c: mcmc.run() text = c.text() self.assertIn('Adaptive covariance', text) self.assertIn('Accept.', text)
def test_logging(self): """ Test logging includes name and custom fields. """ log_pdf = pints.toy.GaussianLogPDF([5, 5], [[4, 1], [1, 3]]) x0 = [np.array([2, 2]), np.array([8, 8])] mcmc = pints.MCMCController( log_pdf, 2, x0, method=pints.MonomialGammaHamiltonianMCMC) mcmc.set_max_iterations(5) with StreamCapture() as c: mcmc.run() text = c.text() self.assertIn('Monomial-Gamma Hamiltonian Monte Carlo', text) self.assertIn(' Accept.', text)
def inference_problem_setup(self, times, num_iter, wd=1, wp=1): """ Runs the parameter inference routine for the PHE model. Parameters ---------- times (list) List of time points at which we have data for the log-likelihood computation. num_iter Number of iterations the MCMC sampler algorithm is run for. wd Proportion of contribution of the deaths_data to the log-likelihood. wp Proportion of contribution of the poritives_data to the log-likelihood. """ # Starting points using optimisation object x0 = [self.optimisation_problem_setup(times, wd, wp)[0].tolist()] * 3 # Create MCMC routine mcmc = pints.MCMCController(self._log_posterior, 3, x0) mcmc.set_max_iterations(num_iter) mcmc.set_log_to_screen(True) mcmc.set_parallel(True) print('Running...') chains = mcmc.run() print('Done!') param_names = ['initial_r'] for region in self._model.regions: param_names.extend([ 'beta_W{}_{}'.format(i + 1, region) for i in range(len(np.arange(44, len(times), 7))) ]) param_names.extend(['sigma_b']) # Check convergence and other properties of chains results = pints.MCMCSummary(chains=chains, time=mcmc.time(), parameter_names=param_names) print(results) return chains
def run(chains): # Filter nones to get expected output expected = np.array([[x for x in chain if x is not None] for chain in chains]) # Get initial position x0 = [chain[0] for chain in chains] # Create log pdf f = SumDistribution(len(x0[0])) # Get expected evaluations exp_evals = np.array([[[f(x)] for x in chain] for chain in expected]) # Set up controller nc = len(x0) mcmc = pints.MCMCController(f, nc, x0, method=SingleListSampler) mcmc.set_log_to_screen(False) mcmc.set_max_iterations(len(expected[0])) # Pass chains to samplers for i, sampler in enumerate(mcmc.samplers()): sampler.set_chain(chains[i]) # Run, while logging to disk with TemporaryDirectory() as d: # Store chains chain_path = d.path('chain.csv') mcmc.set_chain_filename(chain_path) # Store log pdfs evals_path = d.path('evals.csv') mcmc.set_log_pdf_filename(evals_path) # Run obtained = mcmc.run() # Load chains and log_pdfs disk_samples = np.array(pints.io.load_samples(chain_path, nc)) disk_evals = np.array(pints.io.load_samples(evals_path, nc)) # Return expected and obtained values return expected, obtained, disk_samples, exp_evals, disk_evals
def test_stopping(self): """ Test different stopping criteria. """ nchains = 1 xs = [np.array(self.real_parameters) * 1.1] mcmc = pints.MCMCController(self.log_posterior, nchains, xs) # Test setting max iterations maxi = mcmc.max_iterations() + 2 self.assertNotEqual(maxi, mcmc.max_iterations()) mcmc.set_max_iterations(maxi) self.assertEqual(maxi, mcmc.max_iterations()) self.assertRaisesRegex(ValueError, 'negative', mcmc.set_max_iterations, -1) # Test without stopping criteria mcmc.set_max_iterations(None) self.assertIsNone(mcmc.max_iterations()) self.assertRaisesRegex(ValueError, 'At least one stopping criterion', mcmc.run)
def test_parallel(self): """ Test running MCMC with parallisation. """ xs = [] for i in range(10): f = 0.9 + 0.2 * np.random.rand() xs.append(np.array(self.real_parameters) * f) nchains = len(xs) nparameters = len(xs[0]) niterations = 20 mcmc = pints.MCMCController(self.log_posterior, nchains, xs, method=pints.AdaptiveCovarianceMCMC) mcmc.set_max_iterations(niterations) mcmc.set_log_to_screen(debug) # Test with auto-detected number of worker processes self.assertFalse(mcmc.parallel()) mcmc.set_parallel(True) self.assertTrue(mcmc.parallel()) chains = mcmc.run() self.assertEqual(chains.shape[0], nchains) self.assertEqual(chains.shape[1], niterations) self.assertEqual(chains.shape[2], nparameters) # Test with fixed number of worker processes mcmc.set_parallel(2) mcmc.set_log_to_screen(True) self.assertIs(mcmc._parallel, True) self.assertEqual(mcmc._n_workers, 2) with StreamCapture() as c: chains = mcmc.run() self.assertIn('with 2 worker', c.text()) self.assertEqual(chains.shape[0], nchains) self.assertEqual(chains.shape[1], niterations) self.assertEqual(chains.shape[2], nparameters)
def test_live_chain_and_eval_logging(self): np.random.seed(1) xs = [] for i in range(3): f = 0.9 + 0.2 * np.random.rand() xs.append(np.array(self.real_parameters) * f) nchains = len(xs) # Test writing chains - not evals to disk (using LogPosterior) mcmc = pints.MCMCController(self.log_posterior, nchains, xs) mcmc.set_initial_phase_iterations(5) mcmc.set_max_iterations(20) mcmc.set_log_to_screen(True) mcmc.set_log_to_file(False) with StreamCapture() as c: with TemporaryDirectory() as d: cpath = d.path('chain.csv') p0 = d.path('chain_0.csv') p1 = d.path('chain_1.csv') p2 = d.path('chain_2.csv') epath = d.path('evals.csv') p3 = d.path('evals_0.csv') p4 = d.path('evals_1.csv') p5 = d.path('evals_2.csv') # Test files aren't created before mcmc runs mcmc.set_chain_filename(cpath) mcmc.set_log_pdf_filename(None) self.assertFalse(os.path.exists(cpath)) self.assertFalse(os.path.exists(epath)) self.assertFalse(os.path.exists(p0)) self.assertFalse(os.path.exists(p1)) self.assertFalse(os.path.exists(p2)) self.assertFalse(os.path.exists(p3)) self.assertFalse(os.path.exists(p4)) self.assertFalse(os.path.exists(p5)) # Test files are created afterwards chains1 = mcmc.run() self.assertFalse(os.path.exists(cpath)) self.assertFalse(os.path.exists(epath)) self.assertTrue(os.path.exists(p0)) self.assertTrue(os.path.exists(p1)) self.assertTrue(os.path.exists(p2)) self.assertFalse(os.path.exists(p3)) self.assertFalse(os.path.exists(p4)) self.assertFalse(os.path.exists(p5)) # Test files contain the correct chains import pints.io as io chains2 = np.array(io.load_samples(cpath, nchains)) self.assertTrue(np.all(chains1 == chains2)) text = c.text() self.assertIn('Writing chains to', text) self.assertIn('chain_0.csv', text) self.assertNotIn('Writing evaluations to', text) self.assertNotIn('evals_0.csv', text) # Test writing evals - not chains to disk (using LogPosterior) mcmc = pints.MCMCController(self.log_posterior, nchains, xs) mcmc.set_initial_phase_iterations(5) mcmc.set_max_iterations(20) mcmc.set_log_to_screen(True) mcmc.set_log_to_file(False) with StreamCapture() as c: with TemporaryDirectory() as d: cpath = d.path('chain.csv') p0 = d.path('chain_0.csv') p1 = d.path('chain_1.csv') p2 = d.path('chain_2.csv') epath = d.path('evals.csv') p3 = d.path('evals_0.csv') p4 = d.path('evals_1.csv') p5 = d.path('evals_2.csv') # Test files aren't created before mcmc runs mcmc.set_chain_filename(None) mcmc.set_log_pdf_filename(epath) self.assertFalse(os.path.exists(cpath)) self.assertFalse(os.path.exists(epath)) self.assertFalse(os.path.exists(p0)) self.assertFalse(os.path.exists(p1)) self.assertFalse(os.path.exists(p2)) self.assertFalse(os.path.exists(p3)) self.assertFalse(os.path.exists(p4)) self.assertFalse(os.path.exists(p5)) # Test files are created afterwards chains1 = mcmc.run() self.assertFalse(os.path.exists(cpath)) self.assertFalse(os.path.exists(epath)) self.assertFalse(os.path.exists(p0)) self.assertFalse(os.path.exists(p1)) self.assertFalse(os.path.exists(p2)) self.assertTrue(os.path.exists(p3)) self.assertTrue(os.path.exists(p4)) self.assertTrue(os.path.exists(p5)) # Test files contain the correct values import pints.io as io evals2 = np.array(io.load_samples(epath, nchains)) evals1 = [] for chain in chains1: logpdfs = np.array([self.log_posterior(x) for x in chain]) logpriors = np.array([self.log_prior(x) for x in chain]) loglikelihoods = logpdfs - logpriors evals = np.array([logpdfs, loglikelihoods, logpriors]).T evals1.append(evals) evals1 = np.array(evals1) self.assertTrue(np.all(evals1 == evals2)) text = c.text() self.assertNotIn('Writing chains to', text) self.assertNotIn('chain_0.csv', text) self.assertIn('Writing evaluations to', text) self.assertIn('evals_0.csv', text) # Test writing chains and evals to disk # With a LogPosterior - Single chain method mcmc = pints.MCMCController(self.log_posterior, nchains, xs) mcmc.set_initial_phase_iterations(5) mcmc.set_max_iterations(20) mcmc.set_log_to_screen(True) mcmc.set_log_to_file(False) with StreamCapture() as c: with TemporaryDirectory() as d: cpath = d.path('chain.csv') p0 = d.path('chain_0.csv') p1 = d.path('chain_1.csv') p2 = d.path('chain_2.csv') epath = d.path('evals.csv') p3 = d.path('evals_0.csv') p4 = d.path('evals_1.csv') p5 = d.path('evals_2.csv') # Test files aren't created before mcmc runs mcmc.set_chain_filename(cpath) mcmc.set_log_pdf_filename(epath) self.assertFalse(os.path.exists(cpath)) self.assertFalse(os.path.exists(epath)) self.assertFalse(os.path.exists(p0)) self.assertFalse(os.path.exists(p1)) self.assertFalse(os.path.exists(p2)) self.assertFalse(os.path.exists(p3)) self.assertFalse(os.path.exists(p4)) self.assertFalse(os.path.exists(p5)) # Test files are created afterwards chains1 = mcmc.run() self.assertFalse(os.path.exists(cpath)) self.assertFalse(os.path.exists(epath)) self.assertTrue(os.path.exists(p0)) self.assertTrue(os.path.exists(p1)) self.assertTrue(os.path.exists(p2)) self.assertTrue(os.path.exists(p3)) self.assertTrue(os.path.exists(p4)) self.assertTrue(os.path.exists(p5)) # Test chain files contain the correct values import pints.io as io chains2 = np.array(io.load_samples(cpath, nchains)) self.assertTrue(np.all(chains1 == chains2)) # Test eval files contain the correct values evals2 = np.array(io.load_samples(epath, nchains)) evals1 = [] for chain in chains1: logpdfs = np.array([self.log_posterior(x) for x in chain]) logpriors = np.array([self.log_prior(x) for x in chain]) loglikelihoods = logpdfs - logpriors evals = np.array([logpdfs, loglikelihoods, logpriors]).T evals1.append(evals) evals1 = np.array(evals1) self.assertTrue(np.all(evals1 == evals2)) text = c.text() self.assertIn('Writing chains to', text) self.assertIn('chain_0.csv', text) self.assertIn('Writing evaluations to', text) self.assertIn('evals_0.csv', text) # Test writing chains and evals to disk # With a LogPosterior - multi-chain method mcmc = pints.MCMCController(self.log_posterior, nchains, xs, method=pints.DifferentialEvolutionMCMC) mcmc.set_max_iterations(20) mcmc.set_log_to_screen(True) mcmc.set_log_to_file(False) with StreamCapture() as c: with TemporaryDirectory() as d: cpath = d.path('chain.csv') p0 = d.path('chain_0.csv') p1 = d.path('chain_1.csv') p2 = d.path('chain_2.csv') epath = d.path('evals.csv') p3 = d.path('evals_0.csv') p4 = d.path('evals_1.csv') p5 = d.path('evals_2.csv') # Test files aren't created before mcmc runs mcmc.set_chain_filename(cpath) mcmc.set_log_pdf_filename(epath) self.assertFalse(os.path.exists(cpath)) self.assertFalse(os.path.exists(epath)) self.assertFalse(os.path.exists(p0)) self.assertFalse(os.path.exists(p1)) self.assertFalse(os.path.exists(p2)) self.assertFalse(os.path.exists(p3)) self.assertFalse(os.path.exists(p4)) self.assertFalse(os.path.exists(p5)) # Test files are created afterwards chains1 = mcmc.run() self.assertFalse(os.path.exists(cpath)) self.assertFalse(os.path.exists(epath)) self.assertTrue(os.path.exists(p0)) self.assertTrue(os.path.exists(p1)) self.assertTrue(os.path.exists(p2)) self.assertTrue(os.path.exists(p3)) self.assertTrue(os.path.exists(p4)) self.assertTrue(os.path.exists(p5)) # Test chain files contain the correct values import pints.io as io chains2 = np.array(io.load_samples(cpath, nchains)) self.assertTrue(np.all(chains1 == chains2)) # Test eval files contain the correct values evals2 = np.array(io.load_samples(epath, nchains)) evals1 = [] for chain in chains1: logpdfs = np.array([self.log_posterior(x) for x in chain]) logpriors = np.array([self.log_prior(x) for x in chain]) loglikelihoods = logpdfs - logpriors evals = np.array([logpdfs, loglikelihoods, logpriors]).T evals1.append(evals) evals1 = np.array(evals1) self.assertTrue(np.all(evals1 == evals2)) text = c.text() self.assertIn('Writing chains to', text) self.assertIn('chain_0.csv', text) self.assertIn('Writing evaluations to', text) self.assertIn('evals_0.csv', text) # Test writing chains and evals to disk (with LogLikelihood) mcmc = pints.MCMCController(self.log_likelihood, nchains, xs) mcmc.set_initial_phase_iterations(5) mcmc.set_max_iterations(20) mcmc.set_log_to_screen(True) mcmc.set_log_to_file(False) with StreamCapture() as c: with TemporaryDirectory() as d: cpath = d.path('chain.csv') p0 = d.path('chain_0.csv') p1 = d.path('chain_1.csv') p2 = d.path('chain_2.csv') epath = d.path('evals.csv') p3 = d.path('evals_0.csv') p4 = d.path('evals_1.csv') p5 = d.path('evals_2.csv') # Test files aren't created before mcmc runs mcmc.set_chain_filename(cpath) mcmc.set_log_pdf_filename(epath) self.assertFalse(os.path.exists(cpath)) self.assertFalse(os.path.exists(epath)) self.assertFalse(os.path.exists(p0)) self.assertFalse(os.path.exists(p1)) self.assertFalse(os.path.exists(p2)) self.assertFalse(os.path.exists(p3)) self.assertFalse(os.path.exists(p4)) self.assertFalse(os.path.exists(p5)) # Test files are created afterwards chains1 = mcmc.run() self.assertFalse(os.path.exists(cpath)) self.assertFalse(os.path.exists(epath)) self.assertTrue(os.path.exists(p0)) self.assertTrue(os.path.exists(p1)) self.assertTrue(os.path.exists(p2)) self.assertTrue(os.path.exists(p3)) self.assertTrue(os.path.exists(p4)) self.assertTrue(os.path.exists(p5)) # Test chain files contain the correct values import pints.io as io chains2 = np.array(io.load_samples(cpath, nchains)) self.assertTrue(np.all(chains1 == chains2)) # Test eval files contain the correct values evals2 = np.array(io.load_samples(epath, nchains)) evals1 = [] for chain in chains1: evals1.append( np.array([self.log_likelihood(x) for x in chain]).T) evals1 = np.array(evals1).reshape(3, 20, 1) self.assertTrue(np.all(evals1 == evals2)) text = c.text() self.assertIn('Writing chains to', text) self.assertIn('chain_0.csv', text) self.assertIn('Writing evaluations to', text) self.assertIn('evals_0.csv', text) # Test logging can be disabled again mcmc = pints.MCMCController(self.log_posterior, nchains, xs) mcmc.set_initial_phase_iterations(5) mcmc.set_max_iterations(20) mcmc.set_log_to_screen(True) mcmc.set_log_to_file(False) with StreamCapture() as c: with TemporaryDirectory() as d: cpath = d.path('chain.csv') p0 = d.path('chain_0.csv') p1 = d.path('chain_1.csv') p2 = d.path('chain_2.csv') epath = d.path('evals.csv') p3 = d.path('evals_0.csv') p4 = d.path('evals_1.csv') p5 = d.path('evals_2.csv') # Test files aren't created before mcmc runs mcmc.set_chain_filename(cpath) mcmc.set_log_pdf_filename(epath) self.assertFalse(os.path.exists(cpath)) self.assertFalse(os.path.exists(epath)) self.assertFalse(os.path.exists(p0)) self.assertFalse(os.path.exists(p1)) self.assertFalse(os.path.exists(p2)) self.assertFalse(os.path.exists(p3)) self.assertFalse(os.path.exists(p4)) self.assertFalse(os.path.exists(p5)) # Test files are not created afterwards mcmc.set_chain_filename(None) mcmc.set_log_pdf_filename(None) mcmc.run() self.assertFalse(os.path.exists(cpath)) self.assertFalse(os.path.exists(epath)) self.assertFalse(os.path.exists(p0)) self.assertFalse(os.path.exists(p1)) self.assertFalse(os.path.exists(p2)) self.assertFalse(os.path.exists(p3)) self.assertFalse(os.path.exists(p4)) self.assertFalse(os.path.exists(p5)) text = c.text() self.assertNotIn('Writing chains to', text) self.assertNotIn('chain_0.csv', text) self.assertNotIn('Writing evaluations to', text) self.assertNotIn('evals_0.csv', text) # Test with a single chain nchains = 1 mcmc = pints.MCMCController(self.log_posterior, nchains, xs[:1]) mcmc.set_initial_phase_iterations(5) mcmc.set_max_iterations(20) mcmc.set_log_to_screen(True) mcmc.set_log_to_file(False) with StreamCapture() as c: with TemporaryDirectory() as d: cpath = d.path('chain.csv') p0 = d.path('chain_0.csv') p1 = d.path('chain_1.csv') p2 = d.path('chain_2.csv') epath = d.path('evals.csv') p3 = d.path('evals_0.csv') p4 = d.path('evals_1.csv') p5 = d.path('evals_2.csv') # Test files aren't created before mcmc runs mcmc.set_chain_filename(cpath) mcmc.set_log_pdf_filename(epath) self.assertFalse(os.path.exists(cpath)) self.assertFalse(os.path.exists(epath)) self.assertFalse(os.path.exists(p0)) self.assertFalse(os.path.exists(p1)) self.assertFalse(os.path.exists(p2)) self.assertFalse(os.path.exists(p3)) self.assertFalse(os.path.exists(p4)) self.assertFalse(os.path.exists(p5)) # Test files are created afterwards chains1 = mcmc.run() self.assertFalse(os.path.exists(cpath)) self.assertFalse(os.path.exists(epath)) self.assertTrue(os.path.exists(p0)) self.assertFalse(os.path.exists(p1)) self.assertFalse(os.path.exists(p2)) self.assertTrue(os.path.exists(p3)) self.assertFalse(os.path.exists(p4)) self.assertFalse(os.path.exists(p5)) # Test chain files contain the correct values import pints.io as io chains2 = np.array(io.load_samples(cpath, nchains)) self.assertTrue(np.all(chains1 == chains2)) # Test eval files contain the correct values evals2 = np.array(io.load_samples(epath, nchains)) evals1 = [] for chain in chains1: logpdfs = np.array([self.log_posterior(x) for x in chain]) logpriors = np.array([self.log_prior(x) for x in chain]) loglikelihoods = logpdfs - logpriors evals = np.array([logpdfs, loglikelihoods, logpriors]).T evals1.append(evals) evals1 = np.array(evals1) self.assertTrue(np.all(evals1 == evals2)) text = c.text() self.assertIn('Writing chains to', text) self.assertIn('chain_0.csv', text) self.assertIn('Writing evaluations to', text) self.assertIn('evals_0.csv', text)
def __init__(self, name): super(TestPlot, self).__init__(name) # Create toy model (single output) self.model = toy.LogisticModel() self.real_parameters = [0.015, 500] self.times = np.linspace(0, 1000, 100) # small problem self.values = self.model.simulate(self.real_parameters, self.times) # Add noise self.noise = 10 self.values += np.random.normal(0, self.noise, self.values.shape) self.real_parameters.append(self.noise) self.real_parameters = np.array(self.real_parameters) # Create an object with links to the model and time series self.problem = pints.SingleOutputProblem(self.model, self.times, self.values) # Create a uniform prior over both the parameters and the new noise # variable self.lower = [0.01, 400, self.noise * 0.1] self.upper = [0.02, 600, self.noise * 100] self.log_prior = pints.UniformLogPrior(self.lower, self.upper) # Create a log likelihood self.log_likelihood = pints.GaussianLogLikelihood(self.problem) # Create an un-normalised log-posterior (log-likelihood + log-prior) self.log_posterior = pints.LogPosterior(self.log_likelihood, self.log_prior) # Run MCMC self.x0 = [ self.real_parameters * 1.1, self.real_parameters * 0.9, self.real_parameters * 1.05 ] mcmc = pints.MCMCController(self.log_posterior, 3, self.x0) mcmc.set_max_iterations(300) # make it as small as possible mcmc.set_log_to_screen(False) self.samples = mcmc.run() # Create toy model (multi-output) self.model2 = toy.LotkaVolterraModel() self.real_parameters2 = self.model2.suggested_parameters() self.times2 = self.model2.suggested_times()[::10] # down sample it self.values2 = self.model2.simulate(self.real_parameters2, self.times2) # Add noise self.noise2 = 0.05 self.values2 += np.random.normal(0, self.noise2, self.values2.shape) # Create an object with links to the model and time series self.problem2 = pints.MultiOutputProblem(self.model2, self.times2, self.values2) # Create a uniform prior over both the parameters and the new noise # variable self.log_prior2 = pints.UniformLogPrior([1, 1, 1, 1], [6, 6, 6, 6]) # Create a log likelihood self.log_likelihood2 = pints.GaussianKnownSigmaLogLikelihood( self.problem2, self.noise2) # Create an un-normalised log-posterior (log-likelihood + log-prior) self.log_posterior2 = pints.LogPosterior(self.log_likelihood2, self.log_prior2) # Run MCMC self.x02 = [ self.real_parameters2 * 1.1, self.real_parameters2 * 0.9, self.real_parameters2 * 1.05 ] mcmc = pints.MCMCController(self.log_posterior2, 3, self.x02) mcmc.set_max_iterations(300) # make it as small as possible mcmc.set_log_to_screen(False) self.samples2 = mcmc.run() # Create toy model (single-output, single-parameter) self.real_parameters3 = [0] self.log_posterior3 = toy.GaussianLogPDF(self.real_parameters3, [1]) self.lower3 = [-3] self.upper3 = [3] # Run MCMC self.x03 = [[1], [-2], [3]] mcmc = pints.MCMCController(self.log_posterior3, 3, self.x03) mcmc.set_max_iterations(300) # make it as small as possible mcmc.set_log_to_screen(False) self.samples3 = mcmc.run()
log_prior_incorrect = pints.UniformLogPrior([200], [800]) log_posterior = pints.LogPosterior(log_likelihood, log_prior) # Choose starting points for 3 mcmc chains xs = [theta, theta * 1.01, theta * 0.99] isinf = False for x in xs: if (math.isinf(log_posterior.evaluateS1(x)[0])): isinf = True d += 1 break if (isinf == True): continue # Create mcmc routine with three chains mcmc = pints.MCMCController(log_posterior, 3, xs, method=pints.HaarioACMC) # Add stopping criterion sample_size = Ldash mcmc.set_max_iterations(sample_size) # Start adapting after 1000 iterations mcmc.set_initial_phase_iterations(sample_size // 4) # Disable logging mode mcmc.set_log_to_screen(False) # Run! #print('Running...') chains = mcmc.run()
def _run(self, result, log_path): import pints import pints.toy import numpy as np import logging log = logging.getLogger(__name__) DEBUG = False # Store method name result['method'] = self._method log.info('Using method: ' + self._method) # Get method class method = getattr(pints, self._method) # Check number of chains if isinstance(method, pints.SingleChainMCMC) and self._nchains > 1: log.warn('SingleChainMCMC run with more than 1 chain.') elif isinstance(method, pints.MultiChainMCMC) and self._nchains == 1: log.warn('MultiChainMCMC run with only 1 chain.') # Create a log pdf xtrue = np.array([2, 4]) sigma = np.diag(np.array([1, 3])) log_pdf = pints.toy.GaussianLogPDF(xtrue, sigma) # Create a log prior log_prior = pints.MultivariateGaussianLogPrior(xtrue + 1, sigma * 2) # Generate random points x0 = log_prior.sample(self._nchains) # Create a realistic sigma - for some methods only! sigma = None if method == pints.HamiltonianMCMC: sigma = np.diag(np.array([1, 3])) # Create a sampling routine mcmc = pints.MCMCController( log_pdf, self._nchains, x0, sigma0=sigma, method=method) mcmc.set_parallel(True) # Log to file if not DEBUG: mcmc.set_log_to_screen(False) mcmc.set_log_to_file(log_path) # Set max iterations n_iter = self._max_iter n_burn = int(self._max_iter * 0.5) n_init = int(self._max_iter * 0.1) mcmc.set_max_iterations(n_iter) if mcmc.method_needs_initial_phase(): mcmc.set_initial_phase_iterations(n_init) # Run chains = mcmc.run() if DEBUG: import matplotlib.pyplot as plt import pints.plot pints.plot.trace(chains) plt.show() # Combine chains (weaving, so we can see the combined progress per # iteration for multi-chain methods) chain = pfunk.weave(chains) # Calculate KLD for a sliding window n_samples = len(chain) # Total samples n_window = 500 * self._nchains # Window size n_jump = 20 * self._nchains # Spacing between windows iters = list(range(0, n_samples - n_window + n_jump, n_jump)) result['iters'] = iters result['klds'] = [ log_pdf.kl_divergence(chain[i:i + n_window]) for i in iters] # Remove burn-in # For multi-chain, multiply by n_chains because we wove the chains # together. chain = chain[n_burn * self._nchains:] log.info('Chain shape (without burn-in): ' + str(chain.shape)) log.info('Chain mean: ' + str(np.mean(chain, axis=0))) # Store kullback-leibler divergence after burn-in result['kld'] = log_pdf.kl_divergence(chain) # Store effective sample size result['ess'] = pints.effective_sample_size(chain) # Store status result['status'] = 'done'
try: noisy_data = np.loadtxt('noisy_data0.txt') except: noisy_data = data + pints.noise.multiplicative_gaussian(1, 0.1, data) np.savetxt('data/kCatsAllData.txt', noisy_data) # fit to this data using MCMC default_params_noise = np.hstack([default_params, 0.1]) problem = pints.MultiOutputProblem(model, times, noisy_data) log_prior = pints.UniformLogPrior(pints.RectangularBoundaries(0.1*default_params_noise, 10*default_params_noise)) log_likelihood = MultiplicativeGaussianLogLikelihood(problem) log_posterior = pints.LogPosterior(log_likelihood, log_prior) mcmc = pints.MCMCController(log_posterior, 3, [default_params_noise, default_params_noise*0.8, default_params_noise*1.25], method=pints.HaarioBardenetACMC) mcmc.set_parallel(False) mcmc.set_max_iterations(2000) chains = mcmc.run() reps = 1 while max(pints.rhat(chains[:, :, :])) > 1.10 or min(pints.effective_sample_size(chains[0, :, :-1])) < 450: mcmc = pints.MCMCController(log_posterior, 3, chains[:, -1, :], method=pints.HaarioBardenetACMC) mcmc.set_parallel(False) mcmc.set_max_iterations(2000) mcmc.set_log_to_screen(False) chain = mcmc.run() new_chains = np.zeros((chains.shape[0], chains.shape[1] + 2000, chains.shape[2])) new_chains[:, :-2000, :] = chains new_chains[:, -2000:, :] = chain[:, :, :] chains = new_chains reps += 1
def inference(model, values, times): # Create an object with links to the model and time series problem = pints.SingleOutputProblem(model, times, values) # Create a log-likelihood function (adds an extra parameter!) log_likelihood = pints.GaussianLogLikelihood(problem) # Create a uniform prior over both the parameters and the new noise variable lower_bounds = np.array([1e-3, 0.0, 0.4, 0.1, 1e-6, 8.0, 1e-4]) upper_bounds = np.array([10.0, 0.4, 0.6, 100.0, 100e-6, 10.0, 0.2]) log_prior = pints.UniformLogPrior(lower_bounds, upper_bounds) # Create a posterior log-likelihood (log(likelihood * prior)) log_posterior = pints.LogPosterior(log_likelihood, log_prior) # Choose starting points for 3 mcmc chains # params = ['k0', 'E0', 'a', 'Ru', 'Cdl', 'freq', 'sigma'] start_parameters = np.array( [0.0101, 0.214, 0.53, 8.0, 20.0e-6, 9.0152, 0.01]) transform = pints.ComposedTransformation( pints.LogTransformation(1), pints.RectangularBoundariesTransformation(lower_bounds[1:], upper_bounds[1:]), ) sigma0 = [0.1 * (h - l) for l, h in zip(lower_bounds, upper_bounds)] boundaries = pints.RectangularBoundaries(lower_bounds, upper_bounds) found_parameters, found_value = pints.optimise(log_posterior, start_parameters, sigma0, boundaries, transform=transform, method=pints.CMAES) xs = [ found_parameters * 1.001, found_parameters * 1.002, found_parameters * 1.003, ] for x in xs: x[5] = found_parameters[5] print('start_parameters', start_parameters) print('found_parameters', found_parameters) print('lower_bounds', lower_bounds) print('upper_bounds', upper_bounds) # Create mcmc routine with four chains mcmc = pints.MCMCController(log_posterior, 3, xs, method=pints.HaarioBardenetACMC, transform=transform) # Add stopping criterion mcmc.set_max_iterations(10000) # Run! chains = mcmc.run() # Save chains for plotting and analysis pickle.dump((xs, pints.GaussianLogLikelihood, log_prior, chains, 'HaarioBardenetACMC'), open('results.pickle', 'wb'))
# Load fitting results calloaddir = './out/' + which_model load_seed = 542811797 fit_idx = [1, 2, 3] transform_x0_list = [] print('MCMC starting point: ') for i in fit_idx: f = '%s/%s-solution-%s-%s.txt' % (calloaddir, which_data, load_seed, i) p = np.loadtxt(f) transform_x0_list.append(np.append(transform_from_model_param(p), noise_sigma)) print(transform_x0_list[-1]) # Run mcmc = pints.MCMCController(logposterior, 3, transform_x0_list, method=pints.PopulationMCMC) n_iter = 100000 mcmc.set_max_iterations(n_iter) mcmc.set_initial_phase_iterations(int(0.05 * n_iter)) mcmc.set_parallel(False) mcmc.set_chain_filename('%s/%s-chain.csv' % (savedir, saveas)) mcmc.set_log_pdf_filename('%s/%s-pdf.csv' % (savedir, saveas)) chains = mcmc.run() # De-transform parameters chains_param = np.zeros(chains.shape) for i, c in enumerate(chains): c_tmp = np.copy(c) chains_param[i, :, :-1] = transform_to_model_param(c_tmp[:, :-1]) chains_param[i, :, -1] = c_tmp[:, -1] del(c_tmp)