Skip to content

Commit 46927c3

Browse files
committed
updates
1 parent 58d1cd2 commit 46927c3

1 file changed

Lines changed: 82 additions & 51 deletions

File tree

lectures/imp_sample.md

Lines changed: 82 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ We start by importing some Python packages.
3232
```{code-cell} ipython3
3333
import jax
3434
import jax.numpy as jnp
35-
import jax.random as jr
3635
import matplotlib.pyplot as plt
3736
from jax.scipy.special import gammaln
3837
from typing import NamedTuple
@@ -105,13 +104,18 @@ def g(w, params=params):
105104
```
106105

107106
```{code-cell} ipython3
107+
---
108+
mystnb:
109+
figure:
110+
caption: 'Beta density functions $f$ and $g$'
111+
name: fig_imp_densities
112+
---
108113
w_range = jnp.linspace(1e-2, 1-1e-5, 1000)
109114
110-
plt.plot(w_range, g(w_range), label='g')
111-
plt.plot(w_range, f(w_range), label='f')
115+
plt.plot(w_range, g(w_range), lw=2, label='g')
116+
plt.plot(w_range, f(w_range), lw=2, label='f')
112117
plt.xlabel(r'$\omega$')
113118
plt.legend()
114-
plt.title('density functions $f$ and $g$')
115119
plt.show()
116120
```
117121

@@ -124,8 +128,13 @@ def l(w):
124128
```
125129

126130
```{code-cell} ipython3
127-
plt.plot(w_range, l(w_range))
128-
plt.title(r'$\ell(\omega)$')
131+
---
132+
mystnb:
133+
figure:
134+
caption: 'Likelihood ratio $\ell(\omega)$'
135+
name: fig_imp_likelihood_ratio
136+
---
137+
plt.plot(w_range, l(w_range), lw=2)
129138
plt.xlabel(r'$\omega$')
130139
plt.show()
131140
```
@@ -183,23 +192,21 @@ The plots compare $g$ and $h$.
183192
```{code-cell} ipython3
184193
g_a, g_b = params.G_a, params.G_b
185194
h_a, h_b = 0.5, 0.5
186-
187-
key = jr.PRNGKey(0)
188195
```
189196

190197
```{code-cell} ipython3
191198
---
192199
mystnb:
193200
figure:
194-
caption: 'Real data generating process $g$ and importance distribution $h$'
201+
caption: 'Data and importance sampling distributions'
195202
name: fig_imp_real
196203
---
197204
w_range = jnp.linspace(1e-5, 1-1e-5, 1000)
198205
199206
plt.plot(w_range, g(w_range),
200-
label=f'g=Beta({g_a}, {g_b})')
207+
lw=2, label=f'g=Beta({g_a}, {g_b})')
201208
plt.plot(w_range, beta_pdf(w_range, 0.5, 0.5),
202-
label=f'h=Beta({h_a}, {h_b})')
209+
lw=2, label=f'h=Beta({h_a}, {h_b})')
203210
plt.legend()
204211
plt.ylim([0., 3.])
205212
plt.show()
@@ -232,8 +239,8 @@ def estimate_single_path(key, p_a, p_b, q_a, q_b, T):
232239
233240
def loop_body(i, carry):
234241
L, weight, key_state = carry
235-
key_state, subkey = jr.split(key_state)
236-
w = jr.beta(subkey, q_a, q_b)
242+
key_state, subkey = jax.random.split(key_state)
243+
w = jax.random.beta(subkey, q_a, q_b)
237244
238245
# Compute likelihood ratio using f/g functions
239246
likelihood_ratio = f(w) / g(w)
@@ -255,7 +262,7 @@ def estimate_single_path(key, p_a, p_b, q_a, q_b, T):
255262
@partial(jax.jit, static_argnames=['N'])
256263
def estimate(key, p_a, p_b, q_a, q_b, T=1, N=10000):
257264
"""Estimation of a batch of sample paths."""
258-
keys = jr.split(key, N)
265+
keys = jax.random.split(key, N)
259266
260267
# Use vmap for vectorized computation
261268
estimates = jax.vmap(
@@ -271,15 +278,15 @@ Consider the case when $T=1$, which amounts to approximating $E_0\left[\ell\lef
271278
For the standard Monte Carlo estimate, we can set $p=g$ and $q=g$.
272279

273280
```{code-cell} ipython3
274-
key, subkey = jr.split(key)
275-
estimate(subkey, g_a, g_b, g_a, g_b, T=1, N=10000)
281+
estimate(jax.random.key(0), g_a, g_b, g_a, g_b,
282+
T=1, N=10000)
276283
```
277284

278285
For our importance sampling estimate, we set $q = h$.
279286

280287
```{code-cell} ipython3
281-
key, subkey = jr.split(key)
282-
estimate(subkey, g_a, g_b, h_a, h_b, T=1, N=10000)
288+
estimate(jax.random.key(1), g_a, g_b, h_a, h_b,
289+
T=1, N=10000)
283290
```
284291

285292
Evidently, even at $T=1$, our importance sampling estimate is closer to $1$ than is the Monte Carlo estimate.
@@ -290,13 +297,13 @@ Setting $T=10$, we find that the Monte Carlo method severely underestimates the
290297
still produces an estimate close to its theoretical value of unity.
291298

292299
```{code-cell} ipython3
293-
key, subkey = jr.split(key)
294-
estimate(subkey, g_a, g_b, g_a, g_b, T=10, N=10000)
300+
estimate(jax.random.key(2), g_a, g_b, g_a, g_b,
301+
T=10, N=10000)
295302
```
296303

297304
```{code-cell} ipython3
298-
key, subkey = jr.split(key)
299-
estimate(subkey, g_a, g_b, h_a, h_b, T=10, N=10000)
305+
estimate(jax.random.key(3), g_a, g_b, h_a, h_b,
306+
T=10, N=10000)
300307
```
301308

302309
The Monte Carlo method underestimates because the likelihood ratio $L(\omega^T) = \prod_{t=1}^T \frac{f(\omega_t)}{g(\omega_t)}$ has a highly skewed distribution under $g$.
@@ -318,9 +325,9 @@ The code below produces distributions of estimates using both Monte Carlo and i
318325
```{code-cell} ipython3
319326
@partial(jax.jit, static_argnames=['N_simu', 'N_samples'])
320327
def simulate(key, p_a, p_b, q_a, q_b, N_simu, T=1,
321-
N_samples=1000):
328+
N_samples=10000):
322329
"""Simulation for both Monte Carlo and importance sampling."""
323-
keys = jr.split(key, 2 * N_simu)
330+
keys = jax.random.split(key, 2 * N_simu)
324331
keys_p = keys[:N_simu]
325332
keys_q = keys[N_simu:]
326333
@@ -344,8 +351,8 @@ We simulate $1000$ times for each method.
344351

345352
```{code-cell} ipython3
346353
N_simu = 1000
347-
key, subkey = jr.split(key)
348-
μ_L_p, μ_L_q = simulate(subkey, g_a, g_b, h_a, h_b, N_simu)
354+
μ_L_p, μ_L_q = simulate(jax.random.key(4), g_a, g_b,
355+
h_a, h_b, N_simu)
349356
```
350357

351358
```{code-cell} ipython3
@@ -363,13 +370,11 @@ Although both methods tend to provide a mean estimate of ${E} \left[\ell\left(\o
363370
Next, we present distributions of estimates for $\hat{E} \left[L\left(\omega^t\right)\right]$, in cases for $T=1, 5, 10, 20$.
364371

365372
```{code-cell} ipython3
366-
T_values = [1, 5, 10, 20]
367-
368373
def simulate_multiple_T(key, p_a, p_b, q_a, q_b, N_simu,
369-
T_list, N_samples=1000):
374+
T_list, N_samples=10000):
370375
"""Simulation for multiple T values."""
371376
n_T = len(T_list)
372-
keys = jr.split(key, n_T)
377+
keys = jax.random.split(key, n_T)
373378
374379
results = []
375380
for i, T in enumerate(T_list):
@@ -383,13 +388,22 @@ def simulate_multiple_T(key, p_a, p_b, q_a, q_b, N_simu,
383388
μ_L_q_all = jnp.stack([r[1] for r in results])
384389
385390
return μ_L_p_all, μ_L_q_all
391+
```
392+
393+
```{code-cell} ipython3
394+
---
395+
mystnb:
396+
figure:
397+
caption: 'Monte Carlo and importance sampling estimates'
398+
name: fig_imp_estimates
399+
---
400+
T_values = [1, 5, 10, 20]
386401
387402
# Run all simulations at once
388-
key, subkey = jr.split(key)
389-
all_results = simulate_multiple_T(subkey,
403+
all_results = simulate_multiple_T(jax.random.key(5),
390404
g_a, g_b, h_a, h_b,
391405
N_simu, T_values,
392-
N_samples=1000)
406+
N_samples=10000)
393407
394408
# Extract results
395409
μ_L_p_all, μ_L_q_all = all_results
@@ -457,9 +471,8 @@ $$
457471
$$
458472

459473
```{code-cell} ipython3
460-
key, subkey = jr.split(key)
461-
μ_L_p, μ_L_q = simulate(subkey, g_a, g_b, params.F_a,
462-
params.F_b, N_simu)
474+
μ_L_p, μ_L_q = simulate(jax.random.key(6), g_a, g_b,
475+
params.F_a, params.F_b, N_simu)
463476
```
464477

465478
```{code-cell} ipython3
@@ -477,16 +490,22 @@ b_list = [0.5, 1.2, 5.]
477490
```
478491

479492
```{code-cell} ipython3
493+
---
494+
mystnb:
495+
figure:
496+
caption: 'Comparison of importance sampling distributions'
497+
name: fig_imp_sampling_distributions
498+
---
480499
w_range = jnp.linspace(1e-5, 1-1e-5, 1000)
481500
482501
plt.plot(w_range, g(w_range),
483-
label=f'g=Beta({g_a}, {g_b})')
502+
lw=2, label=f'g=Beta({g_a}, {g_b})')
484503
plt.plot(w_range, beta_pdf(w_range, a_list[0], b_list[0]),
485-
label=f'$h_1$=Beta({a_list[0]},{b_list[0]})')
504+
lw=2, label=f'$h_1$=Beta({a_list[0]},{b_list[0]})')
486505
plt.plot(w_range, beta_pdf(w_range, a_list[1], b_list[1]),
487-
label=f'$h_2$=Beta({a_list[1]},{b_list[1]})')
506+
lw=2, label=f'$h_2$=Beta({a_list[1]},{b_list[1]})')
488507
plt.plot(w_range, beta_pdf(w_range, a_list[2], b_list[2]),
489-
label=f'$h_3$=Beta({a_list[2]},{b_list[2]})')
508+
lw=2, label=f'$h_3$=Beta({a_list[2]},{b_list[2]})')
490509
plt.legend()
491510
plt.ylim([0., 3.])
492511
plt.show()
@@ -512,15 +531,20 @@ Our hunch is that $h_3$ will be a poor importance sampling distribution.
512531
We first simulate a plot the distribution of estimates for $\hat{E} \left[L\left(\omega^t\right)\right]$ using $h_2$ as the importance sampling distribution.
513532

514533
```{code-cell} ipython3
534+
---
535+
mystnb:
536+
figure:
537+
caption: 'Estimates using importance distribution $h_2$'
538+
name: fig_imp_estimates_h2
539+
---
515540
h_a = a_list[1]
516541
h_b = b_list[1]
517542
518543
T_values_h2 = [1, 20]
519-
key, subkey = jr.split(key)
520-
all_results_h2 = simulate_multiple_T(subkey,
544+
all_results_h2 = simulate_multiple_T(jax.random.key(7),
521545
g_a, g_b, h_a, h_b,
522546
N_simu, T_values_h2,
523-
N_samples=1000)
547+
N_samples=10000)
524548
μ_L_p_all_h2, μ_L_q_all_h2 = all_results_h2
525549
526550
fig, axs = plt.subplots(1, 2, figsize=(14, 10))
@@ -564,21 +588,28 @@ Our simulations suggest that indeed $h_2$ is a quite good importance sampling d
564588
Even at $T=20$, the mean is very close to $1$ and the variance is small.
565589

566590
```{code-cell} ipython3
591+
---
592+
mystnb:
593+
figure:
594+
caption: 'Estimates using importance distribution $h_3$'
595+
name: fig_imp_estimates_h3
596+
---
567597
h_a = a_list[2]
568598
h_b = b_list[2]
569599
570-
T_list = [1, 20]
571-
key, subkey = jr.split(key)
572-
results = simulate_multiple_T(subkey,
573-
g_a, g_b, h_a, h_b,
574-
N_simu, T_list,
575-
N_samples=1000)
600+
T_values_h3 = [1, 20]
601+
all_results_h3 = simulate_multiple_T(jax.random.key(8),
602+
g_a, g_b, h_a, h_b,
603+
N_simu, T_values_h3,
604+
N_samples=10000)
605+
μ_L_p_all_h3, μ_L_q_all_h3 = all_results_h3
576606
577607
fig, axs = plt.subplots(1, 2, figsize=(14, 10))
578608
μ_range = jnp.linspace(0, 2, 100)
579609
580-
for i, t in enumerate(T_list):
581-
μ_L_p, μ_L_q = results[i]
610+
for i, t in enumerate(T_values_h3):
611+
μ_L_p = μ_L_p_all_h3[i]
612+
μ_L_q = μ_L_q_all_h3[i]
582613
μ_hat_p = jnp.nanmean(μ_L_p)
583614
μ_hat_q = jnp.nanmean(μ_L_q)
584615
σ_hat_p = jnp.nanvar(μ_L_p)

0 commit comments

Comments
 (0)