Skip to content

Commit cb37afa

Browse files
authored
Fix Flaky Euler-Maruyama Tests (#6287)
* seeding the test * being nice to the docs * seeding and flipping any * switch from seed arg to random_seed for initial point * using the numpy_rng instance where applicable * change back the test after discussion
1 parent e153121 commit cb37afa

File tree

2 files changed

+16
-10
lines changed

2 files changed

+16
-10
lines changed

pymc/distributions/timeseries.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -905,11 +905,11 @@ class EulerMaruyama(Distribution):
905905
906906
Parameters
907907
----------
908-
dt: float
908+
dt : float
909909
time step of discretization
910-
sde_fn: callable
910+
sde_fn : callable
911911
function returning the drift and diffusion coefficients of SDE
912-
sde_pars: tuple
912+
sde_pars : tuple
913913
parameters of the SDE, passed as ``*args`` to ``sde_fn``
914914
init_dist : unnamed distribution, optional
915915
Scalar distribution for initial values. Unnamed refers to distributions created with

pymc/tests/distributions/test_timeseries.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -835,8 +835,11 @@ class TestEulerMaruyama:
835835
@pytest.mark.parametrize("batched_param", [1, 2])
836836
@pytest.mark.parametrize("explicit_shape", (True, False))
837837
def test_batched_size(self, explicit_shape, batched_param):
838+
RANDOM_SEED = 42
839+
numpy_rng = np.random.default_rng(RANDOM_SEED)
840+
838841
steps, batch_size = 100, 5
839-
param_val = np.square(np.random.randn(batch_size))
842+
param_val = np.square(numpy_rng.standard_normal(batch_size))
840843
if explicit_shape:
841844
kwargs = {"shape": (batch_size, steps)}
842845
else:
@@ -853,7 +856,7 @@ def sde_fn(x, k, d, s):
853856
"y", dt=0.02, sde_fn=sde_fn, sde_pars=sde_pars, init_dist=init_dist, **kwargs
854857
)
855858

856-
y_eval = draw(y, draws=2)
859+
y_eval = draw(y, draws=2, random_seed=numpy_rng)
857860
assert y_eval[0].shape == (batch_size, steps)
858861
assert not np.any(np.isclose(y_eval[0], y_eval[1]))
859862

@@ -873,7 +876,7 @@ def sde_fn(x, k, d, s):
873876
**kwargs,
874877
)
875878

876-
t0_init = t0.initial_point()
879+
t0_init = t0.initial_point(random_seed=RANDOM_SEED)
877880
t1_init = {f"y_{i}": t0_init["y"][i] for i in range(batch_size)}
878881
np.testing.assert_allclose(
879882
t0.compile_logp()(t0_init),
@@ -919,17 +922,20 @@ def test_linear_model(self):
919922
N = 300
920923
dt = 1e-1
921924

925+
RANDOM_SEED = 42
926+
numpy_rng = np.random.default_rng(RANDOM_SEED)
927+
922928
def _gen_sde_path(sde, pars, dt, n, x0):
923929
xs = [x0]
924-
wt = np.random.normal(size=(n,) if isinstance(x0, float) else (n, x0.size))
930+
wt = numpy_rng.normal(size=(n,) if isinstance(x0, float) else (n, x0.size))
925931
for i in range(n):
926932
f, g = sde(xs[-1], *pars)
927933
xs.append(xs[-1] + f * dt + np.sqrt(dt) * g * wt[i])
928934
return np.array(xs)
929935

930936
sde = lambda x, lam: (lam * x, sig2)
931937
x = floatX(_gen_sde_path(sde, (lam,), dt, N, 5.0))
932-
z = x + np.random.randn(x.size) * sig2
938+
z = x + numpy_rng.standard_normal(size=x.size) * sig2
933939
# build model
934940
with Model() as model:
935941
lamh = Flat("lamh")
@@ -939,9 +945,9 @@ def _gen_sde_path(sde, pars, dt, n, x0):
939945
Normal("zh", mu=xh, sigma=sig2, observed=z)
940946
# invert
941947
with model:
942-
trace = sample(chains=1)
948+
trace = sample(chains=1, random_seed=numpy_rng)
943949

944-
ppc = sample_posterior_predictive(trace, model=model)
950+
ppc = sample_posterior_predictive(trace, model=model, random_seed=numpy_rng)
945951

946952
p95 = [2.5, 97.5]
947953
lo, hi = np.percentile(trace.posterior["lamh"], p95, axis=[0, 1])

0 commit comments

Comments
 (0)