Skip to content

Commit 4b8070d

Browse files
committed
Additional edits
1 parent 92f15dc commit 4b8070d

File tree

2 files changed

+290
-422
lines changed

2 files changed

+290
-422
lines changed

examples/time_series/Euler-Maruyama_and_SDEs.ipynb

Lines changed: 210 additions & 339 deletions
Large diffs are not rendered by default.

examples/time_series/Euler-Maruyama_and_SDEs.myst.md

Lines changed: 80 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,12 @@ run_control:
2525
slideshow:
2626
slide_type: '-'
2727
---
28-
%pylab inline
2928
import arviz as az
30-
import pymc3 as pm
31-
import scipy
32-
import theano.tensor as tt
33-
34-
from pymc3.distributions.timeseries import EulerMaruyama
29+
import matplotlib.pyplot as plt
30+
import numpy as np
31+
import pymc as pm
32+
import pytensor.tensor as pt
33+
import scipy as sp
3534
```
3635

3736
```{code-cell} ipython3
@@ -57,8 +56,8 @@ run_control:
5756
read_only: false
5857
---
5958
# parameters
60-
λ = -0.78
61-
σ2 = 5e-3
59+
lam = -0.78
60+
s2 = 5e-3
6261
N = 200
6362
dt = 1e-1
6463
@@ -68,13 +67,13 @@ x_t = []
6867
6968
# simulate
7069
for i in range(N):
71-
x += dt * λ * x + sqrt(dt) * σ2 * randn()
70+
x += dt * lam * x + np.sqrt(dt) * s2 * np.random.randn()
7271
x_t.append(x)
7372
74-
x_t = array(x_t)
73+
x_t = np.array(x_t)
7574
7675
# z_t noisy observation
77-
z_t = x_t + randn(x_t.size) * 5e-3
76+
z_t = x_t + np.random.randn(x_t.size) * 5e-3
7877
```
7978

8079
```{code-cell} ipython3
@@ -88,14 +87,16 @@ run_control:
8887
slideshow:
8988
slide_type: subslide
9089
---
91-
figure(figsize=(10, 3))
92-
subplot(121)
93-
plot(x_t[:30], "k", label="$x(t)$", alpha=0.5), plot(z_t[:30], "r", label="$z(t)$", alpha=0.5)
94-
title("Transient"), legend()
95-
subplot(122)
96-
plot(x_t[30:], "k", label="$x(t)$", alpha=0.5), plot(z_t[30:], "r", label="$z(t)$", alpha=0.5)
97-
title("All time")
98-
tight_layout()
90+
plt.figure(figsize=(10, 3))
91+
plt.plot(x_t[:30], "k", label="$x(t)$", alpha=0.5)
92+
plt.plot(z_t[:30], "r", label="$z(t)$", alpha=0.5)
93+
plt.title("Transient")
94+
plt.legend()
95+
plt.subplot(122)
96+
plt.plot(x_t[30:], "k", label="$x(t)$", alpha=0.5)
97+
plt.plot(z_t[30:], "r", label="$z(t)$", alpha=0.5)
98+
plt.title("All time")
99+
plt.legend();
99100
```
100101

101102
+++ {"button": false, "new_sheet": false, "run_control": {"read_only": false}}
@@ -114,7 +115,7 @@ run_control:
114115
read_only: false
115116
---
116117
def lin_sde(x, lam):
117-
return lam * x, σ2
118+
return lam * x, s2
118119
```
119120

120121
+++ {"button": false, "new_sheet": false, "run_control": {"read_only": false}, "slideshow": {"slide_type": "subslide"}}
@@ -134,11 +135,11 @@ slideshow:
134135
---
135136
with pm.Model() as model:
136137
# uniform prior, but we know it must be negative
137-
lam = pm.Flat("lam")
138+
l = pm.Flat("l")
138139
139140
# "hidden states" following a linear SDE distribution
140141
# parametrized by time step (det. variable) and lam (random variable)
141-
xh = EulerMaruyama("xh", dt, lin_sde, (lam,), shape=N, testval=x_t)
142+
xh = pm.EulerMaruyama("xh", dt=dt, sde_fn=lin_sde, sde_pars=(l,), shape=N)
142143
143144
# predicted observation
144145
zh = pm.Normal("zh", mu=xh, sigma=5e-3, observed=z_t)
@@ -156,32 +157,28 @@ run_control:
156157
read_only: false
157158
---
158159
with model:
159-
trace = pm.sample(2000, tune=1000)
160+
trace = pm.sample()
160161
```
161162

162163
+++ {"button": false, "new_sheet": false, "run_control": {"read_only": false}, "slideshow": {"slide_type": "subslide"}}
163164

164165
Next, we plot some basic statistics on the samples from the posterior,
165166

166167
```{code-cell} ipython3
167-
---
168-
button: false
169-
nbpresent:
170-
id: 925f1829-24cb-4c28-9b6b-7e9c9e86f2fd
171-
new_sheet: false
172-
run_control:
173-
read_only: false
174-
---
175-
figure(figsize=(10, 3))
176-
subplot(121)
177-
plot(percentile(trace[xh], [2.5, 97.5], axis=0).T, "k", label=r"$\hat{x}_{95\%}(t)$")
178-
plot(x_t, "r", label="$x(t)$")
179-
legend()
180-
181-
subplot(122)
182-
hist(trace[lam], 30, label=r"$\hat{\lambda}$", alpha=0.5)
183-
axvline(λ, color="r", label=r"$\lambda$", alpha=0.5)
184-
legend();
168+
plt.figure(figsize=(10, 3))
169+
plt.subplot(121)
170+
plt.plot(
171+
trace.posterior.quantile((0.025, 0.975), dim=("chain", "draw"))["xh"].values.T,
172+
"k",
173+
label=r"$\hat{x}_{95\%}(t)$",
174+
)
175+
plt.plot(x_t, "r", label="$x(t)$")
176+
plt.legend()
177+
178+
plt.subplot(122)
179+
plt.hist(az.extract(trace.posterior)["l"], 30, label=r"$\hat{\lambda}$", alpha=0.5)
180+
plt.axvline(lam, color="r", label=r"$\lambda$", alpha=0.5)
181+
plt.legend();
185182
```
186183

187184
+++ {"button": false, "new_sheet": false, "run_control": {"read_only": false}, "slideshow": {"slide_type": "subslide"}}
@@ -194,20 +191,20 @@ In other words, we
194191
- check that the new observations fit with the original data
195192

196193
```{code-cell} ipython3
197-
---
198-
button: false
199-
new_sheet: false
200-
run_control:
201-
read_only: false
202-
---
203194
# generate trace from posterior
204-
ppc_trace = pm.sample_posterior_predictive(trace, model=model)
195+
with model:
196+
pm.sample_posterior_predictive(trace, extend_inferencedata=True)
197+
```
205198

206-
# plot with data
207-
figure(figsize=(10, 3))
208-
plot(percentile(ppc_trace["zh"], [2.5, 97.5], axis=0).T, "k", label=r"$z_{95\% PP}(t)$")
209-
plot(z_t, "r", label="$z(t)$")
210-
legend()
199+
```{code-cell} ipython3
200+
plt.figure(figsize=(10, 3))
201+
plt.plot(
202+
trace.posterior_predictive.quantile((0.025, 0.975), dim=("chain", "draw"))["zh"].values.T,
203+
"k",
204+
label=r"$z_{95\% PP}(t)$",
205+
)
206+
plt.plot(z_t, "r", label="$z(t)$")
207+
plt.legend();
211208
```
212209

213210
+++ {"button": false, "new_sheet": false, "run_control": {"read_only": false}}
@@ -231,28 +228,22 @@ As the next model, let's use a 2D deterministic oscillator,
231228
with noisy observation $z(t) = m x + (1 - m) y + N(0, 0.05)$.
232229

233230
```{code-cell} ipython3
234-
---
235-
button: false
236-
new_sheet: false
237-
run_control:
238-
read_only: false
239-
---
240-
N, τ, a, m, σ2 = 200, 3.0, 1.05, 0.2, 1e-1
231+
N, tau, a, m, s2 = 200, 3.0, 1.05, 0.2, 1e-1
241232
xs, ys = [0.0], [1.0]
242233
for i in range(N):
243234
x, y = xs[-1], ys[-1]
244-
dx = τ * (x - x**3.0 / 3.0 + y)
245-
dy = (1.0 / τ) * (a - x)
246-
xs.append(x + dt * dx + sqrt(dt) * σ2 * randn())
247-
ys.append(y + dt * dy + sqrt(dt) * σ2 * randn())
248-
xs, ys = array(xs), array(ys)
249-
zs = m * xs + (1 - m) * ys + randn(xs.size) * 0.1
250-
251-
figure(figsize=(10, 2))
252-
plot(xs, label="$x(t)$")
253-
plot(ys, label="$y(t)$")
254-
plot(zs, label="$z(t)$")
255-
legend()
235+
dx = tau * (x - x**3.0 / 3.0 + y)
236+
dy = (1.0 / tau) * (a - x)
237+
xs.append(x + dt * dx + np.sqrt(dt) * s2 * np.random.randn())
238+
ys.append(y + dt * dy + np.sqrt(dt) * s2 * np.random.randn())
239+
xs, ys = np.array(xs), np.array(ys)
240+
zs = m * xs + (1 - m) * ys + np.random.randn(xs.size) * 0.1
241+
242+
plt.figure(figsize=(10, 2))
243+
plt.plot(xs, label="$x(t)$")
244+
plt.plot(ys, label="$y(t)$")
245+
plt.plot(zs, label="$z(t)$")
246+
plt.legend()
256247
```
257248

258249
+++ {"button": false, "new_sheet": false, "run_control": {"read_only": false}, "slideshow": {"slide_type": "subslide"}}
@@ -268,12 +259,12 @@ new_sheet: false
268259
run_control:
269260
read_only: false
270261
---
271-
def osc_sde(xy, τ, a):
262+
def osc_sde(xy, tau, a):
272263
x, y = xy[:, 0], xy[:, 1]
273-
dx = τ * (x - x**3.0 / 3.0 + y)
274-
dy = (1.0 / τ) * (a - x)
275-
dxy = tt.stack([dx, dy], axis=0).T
276-
return dxy, σ2
264+
dx = tau * (x - x**3.0 / 3.0 + y)
265+
dy = (1.0 / tau) * (a - x)
266+
dxy = pt.stack([dx, dy], axis=0).T
267+
return dxy, s2
277268
```
278269

279270
+++ {"button": false, "new_sheet": false, "run_control": {"read_only": false}}
@@ -291,14 +282,20 @@ new_sheet: false
291282
run_control:
292283
read_only: false
293284
---
294-
xys = c_[xs, ys]
285+
xys = np.c_[xs, ys]
295286
296287
with pm.Model() as model:
297-
τh = pm.Uniform("τh", lower=0.1, upper=5.0)
298-
ah = pm.Uniform("ah", lower=0.5, upper=1.5)
299-
mh = pm.Uniform("mh", lower=0.0, upper=1.0)
300-
xyh = EulerMaruyama("xyh", dt, osc_sde, (τh, ah), shape=xys.shape, testval=xys)
301-
zh = pm.Normal("zh", mu=mh * xyh[:, 0] + (1 - mh) * xyh[:, 1], sigma=0.1, observed=zs)
288+
tau_h = pm.Uniform("tau_h", lower=0.1, upper=5.0)
289+
a_h = pm.Uniform("a_h", lower=0.5, upper=1.5)
290+
m_h = pm.Uniform("m_h", lower=0.0, upper=1.0)
291+
xy_h = pm.EulerMaruyama(
292+
"xy_h", dt=dt, sde_fn=osc_sde, sde_pars=(tau_h, a_h), shape=xys.shape, initval=xys
293+
)
294+
zh = pm.Normal("zh", mu=m_h * xy_h[:, 0] + (1 - m_h) * xy_h[:, 1], sigma=0.1, observed=zs)
295+
```
296+
297+
```{code-cell} ipython3
298+
pm.__version__
302299
```
303300

304301
```{code-cell} ipython3

0 commit comments

Comments
 (0)