|
| 1 | +from __future__ import division |
| 2 | + |
| 3 | +from ..model import Model |
| 4 | +from ..distributions.continuous import Flat, Normal |
| 5 | +from ..distributions.timeseries import EulerMaruyama |
| 6 | +from ..tuning.starting import find_MAP |
| 7 | +from ..sampling import sample, sample_ppc |
| 8 | +from ..step_methods.nuts import NUTS |
| 9 | + |
| 10 | +import numpy as np |
| 11 | +from scipy.optimize import fmin_l_bfgs_b |
| 12 | + |
| 13 | + |
| 14 | +def _gen_sde_path(sde, pars, dt, n, x0): |
| 15 | + xs = [x0] |
| 16 | + wt = np.random.normal(size=(n,) if isinstance(x0, float) else (n, x0.size)) |
| 17 | + for i in range(n): |
| 18 | + f, g = sde(xs[-1], *pars) |
| 19 | + xs.append( |
| 20 | + xs[-1] + f * dt + np.sqrt(dt) * g * wt[i] |
| 21 | + ) |
| 22 | + return np.array(xs) |
| 23 | + |
| 24 | + |
| 25 | +def test_linear(): |
| 26 | + lam = -0.78 |
| 27 | + sig2 = 5e-3 |
| 28 | + N = 300 |
| 29 | + dt = 1e-1 |
| 30 | + sde = lambda x, lam: (lam * x, sig2) |
| 31 | + x = _gen_sde_path(sde, (lam,), dt, N, 5.0) |
| 32 | + z = x + np.random.randn(x.size) * 5e-3 |
| 33 | + # build model |
| 34 | + with Model() as model: |
| 35 | + lamh = Flat('lamh') |
| 36 | + xh = EulerMaruyama('xh', dt, sde, (lamh,), shape=N + 1, testval=x) |
| 37 | + zh = Normal('zh', mu=xh, sd=5e-3, observed=z) |
| 38 | + # invert |
| 39 | + with model: |
| 40 | + start = find_MAP(vars=[xh], fmin=fmin_l_bfgs_b) |
| 41 | + warmup = sample(200, NUTS(scaling=start)) |
| 42 | + trace = sample(1000, NUTS(scaling=warmup[-1], gamma=0.25), start=warmup[-1]) |
| 43 | + ppc = sample_ppc(trace, model=model) |
| 44 | + # test |
| 45 | + p95 = [2.5, 97.5] |
| 46 | + lo, hi = np.percentile(trace[lamh], p95, axis=0) |
| 47 | + assert (lo < lam) and (lam < hi) |
| 48 | + lo, hi = np.percentile(ppc['zh'], p95, axis=0) |
| 49 | + assert ((lo < z) * (z < hi)).mean() > 0.95 |
0 commit comments