def __init__(self, mean=0, sigma=1, name="", model=None): super().__init__(name, model) self.Var("v1", Normal.dist(mu=mean, sigma=sigma)) Normal("v2", mu=mean, sigma=sigma) Normal("v3", mu=mean, sigma=HalfCauchy("sd", beta=10, testval=1.0)) Deterministic("v3_sq", self.v3**2) Potential("p1", tt.constant(1))
def test_density_scaling_with_genarator(self): # We have different size generators def gen1(): i = 0 while True: yield np.ones((10, 100)) * i i += 1 def gen2(): i = 0 while True: yield np.ones((20, 100)) * i i += 1 # We have same size models with pm.Model() as model1: Normal('n', observed=gen1(), total_size=100) p1 = theano.function([], model1.logpt) with pm.Model() as model2: gen_var = generator(gen2()) Normal('n', observed=gen_var, total_size=100) p2 = theano.function([], model2.logpt) # We want densities to be equal for _ in range(10): np.testing.assert_almost_equal(p1(), p2())
def test_acceptance_rate_against_coarseness(self): """Test that the acceptance rate increases when the coarse model is closer to the fine model.""" with Model() as coarse_model_0: Normal("x", 5.0, 1.0) with Model() as coarse_model_1: Normal("x", 6.0, 2.0) with Model() as coarse_model_2: Normal("x", 20.0, 5.0) possible_coarse_models = [ coarse_model_0, coarse_model_1, coarse_model_2 ] acc = [] with Model(): Normal("x", 5.0, 1.0) for coarse_model in possible_coarse_models: step = MLDA(coarse_models=[coarse_model], subsampling_rates=3, tune=True) trace = sample(chains=1, draws=500, tune=100, step=step) acc.append(trace.get_sampler_stats("accepted").mean()) assert acc[0] > acc[1] > acc[2], ("Acceptance rate is not " "strictly increasing when" "coarse model is closer to " "fine model. Acceptance rates" "were: {}".format(acc))
def __init__(self, mean=0, sd=1, name='', model=None): super(DocstringModel, self).__init__(name, model) self.Var('v1', Normal.dist(mu=mean, sd=sd)) Normal('v2', mu=mean, sd=sd) Normal('v3', mu=mean, sd=HalfCauchy('sd', beta=10, testval=1.)) Deterministic('v3_sq', self.v3**2) Potential('p1', tt.constant(1))
def test_density_scaling_with_genarator(self): # We have different size generators def true_dens(): g = gen1() for i, point in enumerate(g): yield stats.norm.logpdf(point).sum() * 10 t = true_dens() # We have same size models with pm.Model() as model1: Normal('n', observed=gen1(), total_size=100) p1 = theano.function([], model1.logpt) with pm.Model() as model2: gen_var = generator(gen2()) Normal('n', observed=gen_var, total_size=100) p2 = theano.function([], model2.logpt) for i in range(10): _1, _2, _t = p1(), p2(), next(t) np.testing.assert_almost_equal(_1, _t, decimal=select_by_precision( float64=7, float32=2)) # Value O(-50,000) np.testing.assert_almost_equal(_1, _2)
def test_multiple_subsampling_rates(self): """Test that when you give a signle integer it is applied to all levels and when you give a list the list is applied correctly.""" with Model() as coarse_model_0: Normal("n", 0, 2.2, shape=(3, )) with Model() as coarse_model_1: Normal("n", 0, 2.1, shape=(3, )) with Model(): Normal("n", 0, 2.0, shape=(3, )) step_1 = MLDA(coarse_models=[coarse_model_0, coarse_model_1], subsampling_rates=3) assert len(step_1.subsampling_rates) == 2 assert step_1.subsampling_rates[0] == step_1.subsampling_rates[ 1] == 3 step_2 = MLDA(coarse_models=[coarse_model_0, coarse_model_1], subsampling_rates=[3, 4]) assert step_2.subsampling_rates[0] == 3 assert step_2.subsampling_rates[1] == 4 with pytest.raises(ValueError): step_3 = MLDA( coarse_models=[coarse_model_0, coarse_model_1], subsampling_rates=[3, 4, 10], )
def test_density_scaling(self): with pm.Model() as model1: Normal('n', observed=[[1]], total_size=1) p1 = theano.function([], model1.logpt) with pm.Model() as model2: Normal('n', observed=[[1]], total_size=2) p2 = theano.function([], model2.logpt) self.assertEqual(p1() * 2, p2())
def test_float64(self): with Model() as model: x = Normal('x', testval=np.array(1., dtype='float64')) obs = Normal('obs', mu=x, sigma=1., observed=np.random.randn(5)) assert x.dtype == 'float64' assert obs.dtype == 'float64' for sampler in self.samplers: with model: sample(10, sampler())
def test_float64(self): with Model() as model: x = Normal("x", testval=np.array(1.0, dtype="float64")) obs = Normal("obs", mu=x, sigma=1.0, observed=np.random.randn(5)) assert x.dtype == "float64" assert obs.dtype == "float64" for sampler in self.samplers: with model: sample(10, sampler())
def check_trace(self, step_method): """Tests whether the trace for step methods is exactly the same as on master. Code changes that effect how random numbers are drawn may change this, and require `master_samples` to be updated, but such changes should be noted and justified in the commit. This method may also be used to benchmark step methods across commits, by running, for example ``` BENCHMARK=100000 ./scripts/test.sh -s pymc3/tests/test_step.py:TestStepMethods ``` on multiple commits. """ n_steps = 100 with Model() as model: x = Normal("x", mu=0, sd=1) y = Normal("y", mu=x, sd=1, observed=1) if step_method.__name__ == "SMC": trace = sample(draws=200, random_seed=1, progressbar=False, step=step_method()) elif step_method.__name__ == "NUTS": step = step_method(scaling=model.test_point) trace = sample( 0, tune=n_steps, discard_tuned_samples=False, step=step, random_seed=1, chains=1, ) else: trace = sample( 0, tune=n_steps, discard_tuned_samples=False, step=step_method(), random_seed=1, chains=1, ) assert_array_almost_equal( trace["x"], self.master_samples[step_method], decimal=select_by_precision(float64=6, float32=4), )
def test_float64(self): theano.config.floatX = 'float64' theano.config.warn_float64 = 'ignore' with Model() as model: x = Normal('x', testval=np.array(1., dtype='float64')) obs = Normal('obs', mu=x, sd=1., observed=np.random.randn(5)) assert x.dtype == 'float64' assert obs.dtype == 'float64' for sampler in self.samplers: with model: sample(10, sampler())
def test_linalg(self): with Model(): a = Normal('a', shape=2) a = tt.switch(a > 0, np.inf, a) b = tt.slinalg.solve(floatX(np.eye(2)), a) Normal('c', mu=b, shape=2) with warnings.catch_warnings(record=True) as warns: trace = sample(20, init=None, tune=5) assert np.any(trace['diverging']) assert any('diverging samples after tuning' in str(warn.message) for warn in warns) assert any('contains only' in str(warn.message) for warn in warns) with pytest.raises(SamplingError): sample(20, init=None, nuts_kwargs={'on_error': 'raise'})
def test_trace_length(self): """Check if trace length is as expected.""" tune = 100 draws = 50 with Model() as coarse_model: Normal("n", 0, 2.2, shape=(3, )) with Model(): Normal("n", 0, 2, shape=(3, )) step = MLDA(coarse_models=[coarse_model]) trace = sample(tune=tune, draws=draws, step=step, chains=1, discard_tuned_samples=False) assert len(trace) == tune + draws
def test_constant_step(): with Model() as model: x = Normal('x', 0, 1) start = {'x': -1} tr = sample(10, step=Constant([x]), start=start) assert_almost_equal(tr['x'], start['x'], decimal=10)
def test_competence(self, variable, has_grad, outcome): with Model() as pmodel: Normal('n', 0, 2, shape=(3, )) Binomial('b', n=2, p=0.3) assert DEMetropolisZ.competence(pmodel[variable], has_grad=has_grad) == outcome pass
def test_competence(self, variable, has_grad, outcome): """Test if competence function returns expected results for different models""" with Model() as pmodel: Normal("n", 0, 2, shape=(3, )) Binomial("b", n=2, p=0.3) assert MLDA.competence(pmodel[variable], has_grad=has_grad) == outcome
def test_parallelized_chains_are_random(self): """Test that parallel chain are not identical when parallelisation is applied""" with Model() as coarse_model: Normal("x", 0.3, 1) with Model(): Normal("x", 0, 1) for stepper in TestMLDA.steppers: step = stepper(coarse_models=[coarse_model]) trace = sample(chains=2, cores=2, draws=20, tune=0, step=step) samples = np.array(trace.get_values("x", combine=False))[:, 5] assert ( len(set(samples)) == 2 ), "Parallelized {} " "chains are identical.".format(stepper)
def __init__(self, mean=0, sigma=1, name='', model=None): super().__init__(name, model) self.Var('v1', Normal.dist(mu=mean, sigma=sigma)) Normal('v2', mu=mean, sigma=sigma) Normal('v3', mu=mean, sigma=HalfCauchy('sd', beta=10, testval=1.)) Deterministic('v3_sq', self.v3 ** 2) Potential('p1', tt.constant(1))
def test_assign_step_methods(): with Model() as model: x = Bernoulli('x', 0.5) steps = assign_step_methods(model, []) assert isinstance(steps, BinaryMetropolis) with Model() as model: x = Normal('x', 0, 1) steps = assign_step_methods(model, []) assert isinstance(steps, NUTS) with Model() as model: x = Categorical('x', np.array([0.25, 0.75])) steps = assign_step_methods(model, []) assert isinstance(steps, BinaryMetropolis) with Model() as model: x = Categorical('x', np.array([0.25, 0.70, 0.05])) steps = assign_step_methods(model, []) assert isinstance(steps, Metropolis) with Model() as model: x = Binomial('x', 10, 0.5) steps = assign_step_methods(model, []) assert isinstance(steps, Metropolis)
def check_trace(self, step_method): """Tests whether the trace for step methods is exactly the same as on master. Code changes that effect how random numbers are drawn may change this, and require `master_samples` to be updated, but such changes should be noted and justified in the commit. This method may also be used to benchmark step methods across commits, by running, for example ``` BENCHMARK=100000 ./scripts/test.sh -s pymc3/tests/test_step.py:TestStepMethods ``` on multiple commits. """ test_steps = 100 n_steps = int(os.getenv('BENCHMARK', 100)) benchmarking = (n_steps != test_steps) if benchmarking: tqdm.write('Benchmarking {} with {:,d} samples'.format(step_method.__name__, n_steps)) else: tqdm.write('Checking {} has same trace as on master'.format(step_method.__name__)) with Model() as model: Normal('x', mu=0, sd=1) trace = sample(n_steps, step=step_method(), random_seed=1) if not benchmarking: assert_array_almost_equal(trace.get_values('x'), self.master_samples[step_method])
def test_sampler_stats(self): with Model() as model: x = Normal("x", mu=0, sigma=1) trace = sample(draws=10, tune=1, chains=1) # Assert stats exist and have the correct shape. expected_stat_names = { "depth", "diverging", "energy", "energy_error", "model_logp", "max_energy_error", "mean_tree_accept", "step_size", "step_size_bar", "tree_size", "tune", } assert trace.stat_names == expected_stat_names for varname in trace.stat_names: assert trace.get_sampler_stats(varname).shape == (10, ) # Assert model logp is computed correctly: computing post-sampling # and tracking while sampling should give same results. model_logp_ = np.array([ model.logp(trace.point(i, chain=c)) for c in trace.chains for i in range(len(trace)) ]) assert (trace.model_logp == model_logp_).all()
def check_trace(self, step_method): """Tests whether the trace for step methods is exactly the same as on master. Code changes that effect how random numbers are drawn may change this, and require `master_samples` to be updated, but such changes should be noted and justified in the commit. This method may also be used to benchmark step methods across commits, by running, for example ``` BENCHMARK=100000 ./scripts/test.sh -s pymc3/tests/test_step.py:TestStepMethods ``` on multiple commits. """ n_steps = 100 with Model(): x = Normal('x', mu=0, sd=1) if step_method.__name__ == 'SMC': Deterministic('like', - 0.5 * tt.log(2 * np.pi) - 0.5 * x.T.dot(x)) trace = smc.ATMIP_sample(n_steps=n_steps, step=step_method(random_seed=1), n_jobs=1, progressbar=False, homepath=self.temp_dir) else: trace = sample(0, tune=n_steps, discard_tuned_samples=False, step=step_method(), random_seed=1) assert_array_almost_equal( trace.get_values('x'), self.master_samples[step_method], decimal=select_by_precision(float64=6, float32=4))
def test_float32_MLDA(self): data = np.random.randn(5).astype("float32") with Model() as coarse_model: x = Normal("x", testval=np.array(1.0, dtype="float32")) obs = Normal("obs", mu=x, sigma=1.0, observed=data + 0.5) with Model() as model: x = Normal("x", testval=np.array(1.0, dtype="float32")) obs = Normal("obs", mu=x, sigma=1.0, observed=data) assert x.dtype == "float32" assert obs.dtype == "float32" with model: sample(10, MLDA(coarse_models=[coarse_model]))
def test_float32_MLDA(self): data = np.random.randn(5).astype('float32') with Model() as coarse_model: x = Normal('x', testval=np.array(1., dtype='float32')) obs = Normal('obs', mu=x, sigma=1., observed=data + 0.5) with Model() as model: x = Normal('x', testval=np.array(1., dtype='float32')) obs = Normal('obs', mu=x, sigma=1., observed=data) assert x.dtype == 'float32' assert obs.dtype == 'float32' with model: sample(10, MLDA(coarse_models=[coarse_model]))
def test_gradient_with_scaling(self): with pm.Model() as model1: genvar = generator(gen1()) m = Normal('m') Normal('n', observed=genvar, total_size=1000) grad1 = theano.function([m], tt.grad(model1.logpt, m)) with pm.Model() as model2: m = Normal('m') shavar = theano.shared(np.ones((1000, 100))) Normal('n', observed=shavar) grad2 = theano.function([m], tt.grad(model2.logpt, m)) for i in range(10): shavar.set_value(np.ones((100, 100)) * i) g1 = grad1(1) g2 = grad2(1) np.testing.assert_almost_equal(g1, g2)
def test_posterior_estimate(self): alpha_true, sigma_true = 1., 0.5 beta_true = 1. size = 1000 X = np.random.randn(size) Y = alpha_true + beta_true * X + np.random.randn(size) * sigma_true decimal = 1 with Model() as model: alpha = Normal('alpha', mu=0, sd=100, testval=alpha_true) beta = Normal('beta', mu=0, sd=100, testval=beta_true) sigma = InverseGamma('sigma', 10., testval=sigma_true) mu = alpha + beta * X Y_obs = Normal('Y_obs', mu=mu, sd=sigma, observed=Y) for step_method, params in ((NUTS, { "target_accept": 0.95 }), (Slice, {}), (Metropolis, { 'scaling': 10. })): trace = sample(100000, step=step_method(**params), progressbar=False, tune=1000) trace_ = trace[-300::5] # We do the same for beta - using more burnin. np.testing.assert_almost_equal(np.mean(trace_.alpha), alpha_true, decimal=decimal) np.testing.assert_almost_equal(np.mean(trace_.beta), beta_true, decimal=decimal) np.testing.assert_almost_equal(np.mean(trace_.sigma), sigma_true, decimal=decimal) # Make sure posteriors are normal _, p_alpha = stats.normaltest(trace_.alpha) _, p_beta = stats.normaltest(trace_.beta) # p-values should be > .05 to indiciate np.testing.assert_array_less(0.05, p_alpha, verbose=True) np.testing.assert_array_less(0.05, p_beta, verbose=True)
def test_linalg(self, caplog): with Model(): a = Normal('a', shape=2) a = tt.switch(a > 0, np.inf, a) b = tt.slinalg.solve(floatX(np.eye(2)), a) Normal('c', mu=b, shape=2) caplog.clear() trace = sample(20, init=None, tune=5, chains=2) warns = [msg.msg for msg in caplog.records] assert np.any(trace['diverging']) assert (any('divergences after tuning' in warn for warn in warns) or any('only diverging samples' in warn for warn in warns)) with pytest.raises(ValueError) as error: trace.report.raise_ok() error.match('issues during sampling') assert not trace.report.ok
def test_linalg(self): with Model(): a = Normal('a', shape=2) a = tt.switch(a > 0, np.inf, a) b = tt.slinalg.solve(floatX(np.eye(2)), a) Normal('c', mu=b, shape=2) with pytest.warns(None) as warns: trace = sample(20, init=None, tune=5) warns = [str(warn.message) for warn in warns] assert np.any(trace['diverging']) assert any('diverging samples after tuning' in warn for warn in warns) # FIXME This test fails sporadically on py27. # It seems that capturing warnings doesn't work as expected. # assert any('contains only' in warn for warn in warns) with pytest.raises(SamplingError): sample(20, init=None, nuts_kwargs={'on_error': 'raise'})
def test_normal_nograd_op(self): """Test normal distribution without an implemented gradient is assigned slice method""" with Model() as model: x = Normal('x', 0, 1) # a custom Theano Op that does not have a grad: is_64 = theano.config.floatX == "float64" itypes = [tt.dscalar] if is_64 else [tt.fscalar] otypes = [tt.dscalar] if is_64 else [tt.fscalar] @theano.as_op(itypes, otypes) def kill_grad(x): return x data = np.random.normal(size=(100,)) Normal("y", mu=kill_grad(x), sd=1, observed=data.astype(theano.config.floatX)) steps = assign_step_methods(model, []) assert isinstance(steps, Slice)
def test_checks_population_size(self): """Test that population samplers check the population size.""" with Model() as model: n = Normal('n', mu=0, sd=1) for stepper in TestPopulationSamplers.steppers: step = stepper() with pytest.raises(ValueError): trace = sample(draws=100, chains=1, step=step) trace = sample(draws=100, chains=4, step=step) pass
def test_checks_population_size(self): """Test that population samplers check the population size.""" with Model() as model: n = Normal("n", mu=0, sigma=1) for stepper in TestPopulationSamplers.steppers: step = stepper() with pytest.raises(ValueError): sample(draws=10, tune=10, chains=1, cores=1, step=step) # don't parallelize to make test faster sample(draws=10, tune=10, chains=4, cores=1, step=step) pass