@@ -32,7 +32,6 @@ We start by importing some Python packages.
3232``` {code-cell} ipython3
3333import jax
3434import jax.numpy as jnp
35- import jax.random as jr
3635import matplotlib.pyplot as plt
3736from jax.scipy.special import gammaln
3837from 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+ ---
108113w_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')
112117plt.xlabel(r'$\omega$')
113118plt.legend()
114- plt.title('density functions $f$ and $g$')
115119plt.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)
129138plt.xlabel(r'$\omega$')
130139plt.show()
131140```
@@ -183,23 +192,21 @@ The plots compare $g$ and $h$.
183192``` {code-cell} ipython3
184193g_a, g_b = params.G_a, params.G_b
185194h_a, h_b = 0.5, 0.5
186-
187- key = jr.PRNGKey(0)
188195```
189196
190197``` {code-cell} ipython3
191198---
192199mystnb:
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---
197204w_range = jnp.linspace(1e-5, 1-1e-5, 1000)
198205
199206plt.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})')
201208plt.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})')
203210plt.legend()
204211plt.ylim([0., 3.])
205212plt.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'])
256263def 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
271278For 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
278285For 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
285292Evidently, 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
290297still 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
302309The 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'])
320327def 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
346353N_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
363370Next, 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-
368373def 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
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+ ---
480499w_range = jnp.linspace(1e-5, 1-1e-5, 1000)
481500
482501plt.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})')
484503plt.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]})')
486505plt.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]})')
488507plt.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]})')
490509plt.legend()
491510plt.ylim([0., 3.])
492511plt.show()
@@ -512,15 +531,20 @@ Our hunch is that $h_3$ will be a poor importance sampling distribution.
512531We 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+ ---
515540h_a = a_list[1]
516541h_b = b_list[1]
517542
518543T_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
526550fig, 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
564588Even 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+ ---
567597h_a = a_list[2]
568598h_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
577607fig, 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