GitHub

@@ -52,7 +52,7 @@ We'll begin by loading some Python modules.

52525353

import matplotlib.pyplot as plt

5454

import numpy as np

55-

from numba import vectorize, jit, prange

55+

from numba import vectorize, jit

5656

from math import gamma

5757

import pandas as pd

5858

from scipy.integrate import quad

@@ -61,10 +61,7 @@ from scipy.integrate import quad

6161

import seaborn as sns

6262

colors = sns.color_palette()

636364-

@jit

65-

def set_seed():

66-

np.random.seed(142857)

67-

set_seed()

64+

rng = np.random.default_rng(142857)

6865

```

69667067

## The setting

@@ -162,7 +159,7 @@ g = jit(lambda x: p(x, G_a, G_b))

162159163160

```{code-cell} ipython3

164161

@jit

165-

def simulate(a, b, T=50, N=500):

162+

def simulate(a, b, rng, T=50, N=500):

166163

'''

167164

Generate N sets of T observations of the likelihood ratio,

168165

return as N x T matrix.

@@ -173,7 +170,7 @@ def simulate(a, b, T=50, N=500):

173170

for i in range(N):

174171175172

for j in range(T):

176-

w = np.random.beta(a, b)

173+

w = rng.beta(a, b)

177174

l_arr[i, j] = f(w) / g(w)

178175179176

return l_arr

@@ -182,12 +179,12 @@ def simulate(a, b, T=50, N=500):

182179

We'll also use the following Python code to prepare some informative simulations

183180184181

```{code-cell} ipython3

185-

l_arr_g = simulate(G_a, G_b, N=50000)

182+

l_arr_g = simulate(G_a, G_b, rng, N=50000)

186183

l_seq_g = np.cumprod(l_arr_g, axis=1)

187184

```

188185189186

```{code-cell} ipython3

190-

l_arr_f = simulate(F_a, F_b, N=50000)

187+

l_arr_f = simulate(F_a, F_b, rng, N=50000)

191188

l_seq_f = np.cumprod(l_arr_f, axis=1)

192189

```

193190

@@ -492,16 +489,16 @@ First, let's create a function to simulate data under the mixture timing protoco

492489493490

```{code-cell} ipython3

494491

@jit

495-

def simulate_mixture_path(x_true, T):

492+

def simulate_mixture_path(x_true, T, rng):

496493

"""

497494

Simulate T observations under mixture timing protocol.

498495

"""

499496

w = np.empty(T)

500497

for t in range(T):

501-

if np.random.rand() < x_true:

502-

w[t] = np.random.beta(F_a, F_b)

498+

if rng.random() < x_true:

499+

w[t] = rng.beta(F_a, F_b)

503500

else:

504-

w[t] = np.random.beta(G_a, G_b)

501+

w[t] = rng.beta(G_a, G_b)

505502

return w

506503

```

507504

@@ -522,8 +519,8 @@ prior_params = [(1, 3), (1, 1), (3, 1)]

522519

prior_means = [a/(a+b) for a, b in prior_params]

523520524521

# Generate one path of observations from the mixture

525-

set_seed()

526-

w_mix = simulate_mixture_path(x_true, T_mix)

522+

rng = np.random.default_rng(142857)

523+

w_mix = simulate_mixture_path(x_true, T_mix, rng)

527524

```

528525529526

### Behavior of $\pi_t$ under wrong model

@@ -830,7 +827,7 @@ We'll plot a large sample of paths.

830827831828

```{code-cell} ipython3

832829

@jit

833-

def martingale_simulate(π0, N=5000, T=200):

830+

def martingale_simulate(π0, rng, N=5000, T=200):

834831835832

π_path = np.empty((N,T+1))

836833

w_path = np.empty((N,T))

@@ -840,29 +837,27 @@ def martingale_simulate(π0, N=5000, T=200):

840837

π = π0

841838

for t in range(T):

842839

# draw w

843-

if np.random.rand() <= π:

844-

w = np.random.beta(F_a, F_b)

840+

if rng.random() <= π:

841+

w = rng.beta(F_a, F_b)

845842

else:

846-

w = np.random.beta(G_a, G_b)

843+

w = rng.beta(G_a, G_b)

847844

π = π*f(w)/g(w)/(π*f(w)/g(w) + 1 - π)

848845

π_path[n,t+1] = π

849846

w_path[n,t] = w

850847851848

return π_path, w_path

852849853-

def fraction_0_1(π0, N, T, decimals):

850+

def fraction_0_1(π0, rng, N, T, decimals):

854851855-

π_path, w_path = martingale_simulate(π0, N=N, T=T)

856-

values, counts = np.unique(

857-

np.round(π_path[:,-1], decimals=decimals),

858-

return_counts=True)

852+

π_path, w_path = martingale_simulate(π0, rng, N=N, T=T)

853+

values, counts = np.unique(np.round(π_path[:,-1], decimals=decimals), return_counts=True)

859854

return values, counts

860855861-

def create_table(π0s, N=10000, T=500, decimals=2):

856+

def create_table(π0s, rng, N=10000, T=500, decimals=2):

862857863858

outcomes = []

864859

for π0 in π0s:

865-

values, counts = fraction_0_1(π0, N=N, T=T, decimals=decimals)

860+

values, counts = fraction_0_1(π0, rng, N=N, T=T, decimals=decimals)

866861

freq = counts/N

867862

outcomes.append(dict(zip(values, freq)))

868863

table = pd.DataFrame(outcomes).sort_index(axis=1).fillna(0)

@@ -873,7 +868,7 @@ def create_table(π0s, N=10000, T=500, decimals=2):

873868

T = 200

874869

π0 = .5

875870876-

π_path, w_path = martingale_simulate(π0=π0, T=T, N=10000)

871+

π_path, w_path = martingale_simulate(π0=π0, rng=rng, T=T, N=10000)

877872

```

878873879874

```{code-cell} ipython3

@@ -928,7 +923,7 @@ $\pi_t$'s for various $t$'s.

928923

T = 200

929924

π0 = .3

930925931-

π_path3, w_path3 = martingale_simulate(π0=π0, T=T, N=10000)

926+

π_path3, w_path3 = martingale_simulate(π0=π0, rng=rng, T=T, N=10000)

932927

```

933928934929

```{code-cell} ipython3

@@ -982,8 +977,8 @@ The second column reports the fraction of $N = 10000$ simulations for which $\pi

982977

The third column reports the fraction of $N = 10000$ simulations for which $\pi_{t}$ had converged to $1$ at the terminal date $T=500$ for each simulation.

983978984979

```{code-cell} ipython3

985-

# Create table

986-

table = create_table(list(np.linspace(0,1,11)), N=10000, T=500)

980+

# create table

981+

table = create_table(list(np.linspace(0,1,11)), rng, N=10000, T=500)

987982

table

988983

```

989984

@@ -1009,15 +1004,15 @@ Then we'll plot it.

1009100410101005

```{code-cell} ipython3

10111006

@jit

1012-

def compute_cond_var(π, mc_size=int(1e6)):

1007+

def compute_cond_var(π, rng, mc_size=int(1e6)):

10131008

# Create Monte Carlo draws

10141009

mc_draws = np.zeros(mc_size)

101510101016-

for i in prange(mc_size):

1017-

if np.random.rand() <= π:

1018-

mc_draws[i] = np.random.beta(F_a, F_b)

1011+

for i in range(mc_size):

1012+

if rng.random() <= π:

1013+

mc_draws[i] = rng.beta(F_a, F_b)

10191014

else:

1020-

mc_draws[i] = np.random.beta(G_a, G_b)

1015+

mc_draws[i] = rng.beta(G_a, G_b)

1021101610221017

dev = π*f(mc_draws)/(π*f(mc_draws) + (1-π)*g(mc_draws)) - π

10231018

return np.mean(dev**2)

@@ -1026,7 +1021,7 @@ def compute_cond_var(π, mc_size=int(1e6)):

10261021

cond_var_array = []

1027102210281023

for π in π_array:

1029-

cond_var_array.append(compute_cond_var(π))

1024+

cond_var_array.append(compute_cond_var(π, rng))

1030102510311026

fig, ax = plt.subplots()

10321027

ax.plot(π_array, cond_var_array, lw=2)

Read the original on github.com ↗