def test_custom_dist_sum_stat_scalar(self): """ Test that automatically wrapped functions cope well with scalar inputs """ scalar_data = 5 with pm.Model() as m: s = pm.Simulator( "s", self.normal_sim, 0, 1, distance=self.abs_diff, sum_stat=self.quantiles, observed=scalar_data, ) assert self.count_rvs(m.logpt) == 1 with pm.Model() as m: s = pm.Simulator( "s", self.normal_sim, 0, 1, distance=self.abs_diff, sum_stat="mean", observed=scalar_data, ) assert self.count_rvs(m.logpt) == 1
def test_nested_simulators(self): true_a = 2 rng = self.get_random_state() data = rng.normal(true_a, 0.1, size=1000) with pm.Model() as m: sim1 = pm.Simulator( "sim1", self.normal_sim, params=(0, 4), distance="gaussian", sum_stat="identity", ) sim2 = pm.Simulator( "sim2", self.normal_sim, params=(sim1, 0.1), distance="gaussian", sum_stat="mean", epsilon=0.1, observed=data, ) assert self.count_rvs(m.logpt) == 2 with m: trace = pm.sample_smc(return_inferencedata=False) assert np.abs(true_a - trace["sim1"].mean()) < 0.1
def test_multiple_simulators(self): true_a = 2 true_b = -2 data1 = np.random.normal(true_a, 0.1, size=1000) data2 = np.random.normal(true_b, 0.1, size=1000) with pm.Model() as m: a = pm.Normal("a", mu=0, sigma=3) b = pm.Normal("b", mu=0, sigma=3) sim1 = pm.Simulator( "sim1", self.normal_sim, a, 0.1, distance="gaussian", sum_stat="sort", observed=data1, ) sim2 = pm.Simulator( "sim2", self.normal_sim, b, 0.1, distance="laplace", sum_stat="mean", epsilon=0.1, observed=data2, ) assert self.count_rvs(m.logpt()) == 2 # Check that the logps use the correct methods a_val = m.rvs_to_values[a] sim1_val = m.rvs_to_values[sim1] logp_sim1 = pm.joint_logpt(sim1, sim1_val) logp_sim1_fn = aesara.function([a_val], logp_sim1) b_val = m.rvs_to_values[b] sim2_val = m.rvs_to_values[sim2] logp_sim2 = pm.joint_logpt(sim2, sim2_val) logp_sim2_fn = aesara.function([b_val], logp_sim2) assert any( node for node in logp_sim1_fn.maker.fgraph.toposort() if isinstance(node.op, SortOp) ) assert not any( node for node in logp_sim2_fn.maker.fgraph.toposort() if isinstance(node.op, SortOp) ) with m: trace = pm.sample_smc(return_inferencedata=False) assert abs(true_a - trace["a"].mean()) < 0.05 assert abs(true_b - trace["b"].mean()) < 0.05
def test_simulator_error_msg(self): msg = "The distance metric not_real is not implemented" with pytest.raises(ValueError, match=msg): with pm.Model() as m: sim = pm.Simulator("sim", self.normal_sim, 0, 1, distance="not_real") msg = "The summary statistic not_real is not implemented" with pytest.raises(ValueError, match=msg): with pm.Model() as m: sim = pm.Simulator("sim", self.normal_sim, 0, 1, sum_stat="not_real") msg = "Cannot pass both unnamed parameters and `params`" with pytest.raises(ValueError, match=msg): with pm.Model() as m: sim = pm.Simulator("sim", self.normal_sim, 0, params=(1))
def setup_class(self): super().setup_class() self.data = np.random.normal(loc=0, scale=1, size=1000) with pm.Model() as self.SMABC_test: a = pm.Normal("a", mu=0, sigma=1) b = pm.HalfNormal("b", sigma=1) s = pm.Simulator("s", self.normal_sim, a, b, sum_stat="sort", observed=self.data) self.s = s with pm.Model() as self.SMABC_potential: a = pm.Normal("a", mu=0, sigma=1, initval=0.5) b = pm.HalfNormal("b", sigma=1) c = pm.Potential("c", pm.math.switch(a > 0, 0, -np.inf)) s = pm.Simulator("s", self.normal_sim, a, b, observed=self.data)
def get_results(self): lattice = pymc.GrapheneLattice(6) FK = pymc.Hamiltonian(lattice, t=-1, U=2, cp=1, T=0.2) FK.put_adatoms(18, "random") obs = pymc.ObsList([pymc.DeltaObs(FK), pymc.EnergyObs(FK), pymc.CVObs(FK), pymc.CorrelationObs(FK), pymc.NeObs(FK)]) obs_conv = pymc.ObsList( [pymc.DeltaObs(FK), pymc.EnergyObs(FK), pymc.CorrelationObs(FK)]) series = pymc.ObsSeries(obs, ["T"]) sym = pymc.Simulator(FK, pymc.metropolis_numpy, obs, obs_conv) T_range = [0.2, 0.18, 0.16, 0.14, 0.12, 0.10, 0.08, 0.06, 0.04, 0.03, 0.02, 0.01] for T in T_range: FK.T = T sym.run_termalization(10**2) res = sym.run_measurements(10**2) series.add(res, [T]) expected = np.loadtxt( "tests/simulate/half_filling_1.csv", delimiter=",") res = series.get_df().values return (expected, res)
def test_automatic_use_of_sort(self): with pm.Model() as model: s_k = pm.Simulator( "s_k", None, params=None, distance="kullback_leibler", sum_stat="sort", observed=self.data, ) assert s_k.distribution.sum_stat is pm.distributions.simulator.identity
def test_named_model(self): # Named models used to fail with Simulator because the arguments to the # random fn used to be passed by name. This is no longer true. # https://github.com/pymc-devs/pymc/pull/4365#issuecomment-761221146 name = "NamedModel" with pm.Model(name=name): a = pm.Normal("a", mu=0, sigma=1) b = pm.HalfNormal("b", sigma=1) s = pm.Simulator("s", self.normal_sim, a, b, observed=self.data) trace = pm.sample_smc(draws=10, chains=2, return_inferencedata=False) assert f"{name}/a" in trace.varnames assert f"{name}/b" in trace.varnames assert f"{name}/b_log__" in trace.varnames
def test_custom_dist_sum_stat(self): with pm.Model() as m: a = pm.Normal("a", mu=0, sigma=1) b = pm.HalfNormal("b", sigma=1) s = pm.Simulator( "s", self.normal_sim, a, b, distance=self.abs_diff, sum_stat=self.quantiles, observed=self.data, ) assert self.count_rvs(m.logpt) == 1 with m: pm.sample_smc(draws=100)
lattice = pymc.GrapheneLattice(6) FK = pymc.Hamiltonian(lattice, t=-1, U=2, cp=-1, T=0.2) FK.put_adatoms(6 * 3, "random") obs = pymc.ObsList([ pymc.DeltaObs(FK), pymc.EnergyObs(FK), pymc.CVObs(FK), pymc.CorrelationObs(FK), pymc.NeObs(FK) ]) obs_conv = pymc.ObsList( [pymc.DeltaObs(FK), pymc.EnergyObs(FK), pymc.CorrelationObs(FK)]) series = pymc.ObsSeries(obs, ["T"]) sym = pymc.Simulator(FK, pymc.metropolis_numpy, obs, obs_conv) T_range = [ 0.2, 0.18, 0.16, 0.14, 0.12, 0.10, 0.08, 0.06, 0.04, 0.03, 0.02, 0.01 ] for T in tqdm(T_range, desc="Main loop"): FK.T = T sym.run_termalization(10**4) res = sym.run_measurements(10**4) series.add(res, [T]) res = series.get_df().values np.savetxt("half_filling_2.csv", res, delimiter=",")