def test_gibbs_chain_get_probabilities(): start_location = array([2.0, -4.0]) width_guesses = array([5.0, 0.05]) chain = GibbsChain(posterior=rosenbrock, start=start_location, widths=width_guesses) steps = 10 chain.advance(steps) probabilities = chain.get_probabilities() assert len(probabilities) == steps assert probabilities[-1] > probabilities[0] burn = 2 probabilities = chain.get_probabilities(burn=burn) assert len(probabilities) == expected_len(steps, start=burn) assert probabilities[-1] > probabilities[0] thin = 2 probabilities = chain.get_probabilities(thin=thin) assert len(probabilities) == expected_len(steps, step=thin) assert probabilities[-1] > probabilities[0] probabilities = chain.get_probabilities(burn=burn, thin=thin) assert len(probabilities) == expected_len(steps, start=burn, step=thin) assert probabilities[-1] > probabilities[0]
def test_gibbs_chain_non_negative(line_posterior): chain = GibbsChain(posterior=line_posterior, start=[0.5, 0.1]) chain.set_non_negative(1) chain.advance(100) offset = array(chain.get_parameter(1)) assert all(offset >= 0)
def test_gibbs_chain_set_boundary(line_posterior): chain = GibbsChain(posterior=line_posterior, start=[0.5, 0.1]) left, right = (0.45, 0.55) chain.set_boundaries(0, [left, right]) chain.advance(100) gradient = array(chain.get_parameter(0)) assert all(gradient >= left) assert all(gradient <= right)
def test_gibbs_chain_remove_boundary(line_posterior): chain = GibbsChain(posterior=line_posterior, start=[0.5, 0.1]) left, right = (0.45, 0.4500000000001) chain.set_boundaries(0, [left, right]) chain.set_boundaries(0, None, remove=True) chain.advance(100) gradient = array(chain.get_parameter(0)) # Some values should be outside the original boundary assert not all(gradient >= left) or not all(gradient <= right)
def test_gibbs_chain_advance(): start_location = array([2.0, -4.0]) width_guesses = array([5.0, 0.05]) chain = GibbsChain(posterior=rosenbrock, start=start_location, widths=width_guesses) first_n = chain.n steps = 104 chain.advance(steps) assert chain.n == first_n + steps assert len(chain.params[0].samples) == chain.n assert len(chain.probs) == chain.n
def test_gibbs_chain_thin(): start_location = array([2.0, -4.0]) width_guesses = array([5.0, 0.05]) chain = GibbsChain(posterior=rosenbrock, start=start_location, widths=width_guesses) steps = 50 chain.advance(steps) with warnings.catch_warnings(): warnings.simplefilter("ignore") chain.autoselect_thin() assert 0 < chain.thin <= steps
def test_gibbs_chain_burn_in(): start_location = array([2.0, -4.0]) width_guesses = array([5.0, 0.05]) chain = GibbsChain(posterior=rosenbrock, start=start_location, widths=width_guesses) steps = 50 chain.advance(steps) burn = chain.estimate_burn_in() assert 0 < burn <= steps chain.autoselect_burn() assert chain.burn == burn
def test_gibbs_chain_restore(tmp_path): start_location = array([2.0, -4.0]) width_guesses = array([5.0, 0.05]) chain = GibbsChain(posterior=rosenbrock, start=start_location, widths=width_guesses) steps = 50 chain.advance(steps) filename = tmp_path / "restore_file.npz" chain.save(filename) new_chain = GibbsChain.load(filename) assert new_chain.n == chain.n assert new_chain.probs == chain.probs assert new_chain.get_sample() == chain.get_sample()
def test_gibbs_chain_get_parameter(): start_location = array([2.0, -4.0]) width_guesses = array([5.0, 0.05]) chain = GibbsChain(posterior=rosenbrock, start=start_location, widths=width_guesses) steps = 5 chain.advance(steps) samples = chain.get_parameter(0) assert len(samples) == expected_len(steps) burn = 2 samples = chain.get_parameter(0, burn=burn) assert len(samples) == expected_len(steps, burn) thin = 2 samples = chain.get_parameter(1, thin=thin) assert len(samples) == expected_len(steps, step=thin) samples = chain.get_parameter(1, burn=burn, thin=thin) assert len(samples) == expected_len(steps, start=burn, step=thin)
# The maximum of the rosenbrock function is [0,0] - here we intentionally # start the chain far from the mode. start_location = array([2., -4.]) # Here we make our initial guess for the proposal widths intentionally # poor, to demonstrate that gibbs sampling allows each proposal width # to be adjusted individually toward an optimal value. width_guesses = array([5., 0.05]) # create the chain object chain = GibbsChain(posterior=rosenbrock, start=start_location, widths=width_guesses) # advance the chain 150k steps chain.advance(150000) # the samples for the n'th parameter can be accessed through the # get_parameter(n) method. We could use this to plot the path of # the chain through the 2D parameter space: p = chain.get_probabilities() # color the points by their probability value plt.scatter(chain.get_parameter(0), chain.get_parameter(1), c=exp(p - max(p)), marker='.') plt.xlabel('parameter 1') plt.ylabel('parameter 2') plt.grid() plt.show()
# plot the synthetic data and underlying line plt.plot(x, m*x + c) plt.plot(x, y, '.') plt.grid() plt.show() # create an instance of the posterior class posterior = LinePosterior(x = x, y = y, err = ones(N)*sigma) # pass the posterior to the MCMC sampler chain = GibbsChain(posterior = posterior, start = [0.5, 0.1]) # Now suppose we know the offset parameter must be non-negative. # This constraint can be imposed by passing the index of the # parameter to the set_non_negative method as follows: chain.set_non_negative(1) # For the purposes of this demo, let's assume we also know that # the gradient must exist in the range [0.45, 0.55]. # The gradient can be constrained to values between chosen boundaries # by passing the parameter index and the boundary values to the # set_boundaries method as follows: chain.set_boundaries(0, [0.45, 0.55]) # Advance the chain chain.advance(50000) chain.burn = 5000 # Use the matrix plot functionality to check the constraints are working chain.matrix_plot()
As an initial guess the covariance matrix is taken to be diagonal, which results in standard gibbs sampling for the first samples in the chain. Subsequently, the covariance matrix periodically updated with an estimate derived from the sample itself, and the eigenvectors are re-calculated. """ # create our posterior with two highly-correlated parameters posterior = CorrelatedLinePosterior() # create a PcaChain, and also a GibbsChain for comparison pca = PcaChain(posterior=posterior, start=[-1, 1, -1]) gibbs = GibbsChain(posterior=posterior, start=[-1, 1, -1]) # advance both chains for the same amount of samples pca.advance(50000) gibbs.advance(50000) # get an estimate of the marginal distribution of one of the correlated parameters pca_pdf = pca.get_marginal(2, burn=5000) gibbs_pdf = gibbs.get_marginal(2, burn=5000) # over-plot the marginal estimates to compare the performance marginal_axis = linspace(-4, 2, 500) plt.plot(marginal_axis, pca_pdf(marginal_axis), lw=2, label='PcaChain estimate') plt.plot(marginal_axis, gibbs_pdf(marginal_axis), lw=2, label='GibbsChain estimate')
from numpy import array, exp import matplotlib.pyplot as plt def rosenbrock(t): x, y = t x2 = x**2 b = 15. # correlation strength parameter v = 3. # variance of the gaussian term return -x2 - b * (y - x2)**2 - 0.5 * (x2 + y**2) / v # create the chain object from inference.mcmc import GibbsChain gibbs = GibbsChain(posterior=rosenbrock, start=array([2., -4.])) gibbs.advance(150000) gibbs.burn = 10000 gibbs.thin = 70 p = gibbs.get_probabilities() # color the points by their probability value fig = plt.figure(figsize=(5, 4)) ax1 = fig.add_subplot(111) ax1.scatter(gibbs.get_parameter(0), gibbs.get_parameter(1), c=exp(p - max(p)), marker='.') ax1.set_ylim([None, 2.8]) ax1.set_xlim([-1.8, 1.8]) ax1.set_xticks([]) ax1.set_yticks([]) # ax1.set_title('Gibbs sampling')