GitHub

@@ -43,13 +43,13 @@ logger.setLevel(logging.CRITICAL)

43434444

```

454546-

This lecture. uses Bayesian methods offered by [pymc](https://www.pymc.io/projects/docs/en/stable/) and [numpyro](https://num.pyro.ai/en/stable/) to make statistical inferences about two parameters of a univariate first-order autoregression.

46+

This lecture uses Bayesian methods offered by [pymc](https://www.pymc.io/projects/docs/en/stable/) and [numpyro](https://num.pyro.ai/en/stable/) to make statistical inferences about two parameters of a univariate first-order autoregression.

474748484949

The model is a good laboratory for illustrating

5050

consequences of alternative ways of modeling the distribution of the initial $y_0$:

515152-

- As a fixed number.

52+

- As a fixed number

53535454

- As a random variable drawn from the stationary distribution of the $\{y_t\}$ stochastic process

5555

@@ -65,8 +65,6 @@ $\{\epsilon_{t+1}\}$ is a sequence of i.i.d. normal random variables with mean $

65656666

The second component of the statistical model is

676768-

and

69-7068

$$

7169

y_0 \sim {\cal N}(\mu_0, \sigma_0^2)

7270

$$ (eq:themodel_2)

@@ -172,7 +170,7 @@ Now we shall use Bayes' law to construct a posterior distribution, conditioning

172170173171

First we'll use **pymc4**.

174172175-

## `PyMC` Implementation

173+

## PyMC Implementation

176174177175

For a normal distribution in `pymc`,

178176

$var = 1/\tau = \sigma^{2}$.

@@ -183,15 +181,15 @@ AR1_model = pmc.Model()

183181184182

with AR1_model:

185183186-

#start with priors

187-

rho = pmc.Uniform('rho',lower=-1.,upper=1.) #assume stable rho

184+

# Start with priors

185+

rho = pmc.Uniform('rho', lower=-1., upper=1.) # Assume stable rho

188186

sigma = pmc.HalfNormal('sigma', sigma = np.sqrt(10))

189187190188

# Expected value of y at the next period (rho * y)

191-

yhat = rho*y[:-1]

189+

yhat = rho * y[:-1]

192190193-

# Likelihood of the actual realization.

194-

y_like = pmc.Normal('y_obs', mu = yhat, sigma=sigma, observed=y[1:])

191+

# Likelihood of the actual realization

192+

y_like = pmc.Normal('y_obs', mu=yhat, sigma=sigma, observed=y[1:])

195193

```

196194197195

```{code-cell} ipython3

@@ -213,13 +211,12 @@ This is is a symptom of the classic **Hurwicz bias** for first order autorgress

213211

The Hurwicz bias is worse the smaller is the sample (see {cite}`Orcutt_Winokur_69`.)

214212215213216-

Be that as it may, here is more information about the posterior

214+

Be that as it may, here is more information about the posterior.

217215218216

```{code-cell} ipython3

219217

with AR1_model:

220218

summary = az.summary(trace, round_to=4)

221219222-

# print

223220

summary

224221

```

225222

@@ -238,17 +235,17 @@ AR1_model_y0 = pmc.Model()

238235239236

with AR1_model_y0:

240237241-

#start with priors

242-

rho = pmc.Uniform('rho',lower=-1.,upper=1.) #assume stable rho

238+

# Start with priors

239+

rho = pmc.Uniform('rho', lower=-1., upper=1.) # Assume stable rho

243240

sigma = pmc.HalfNormal('sigma', sigma=np.sqrt(10))

244241245-

#standard deviation of ergodic y

246-

y_sd = sigma/np.sqrt(1-rho**2)

242+

# Standard deviation of ergodic y

243+

y_sd = sigma / np.sqrt(1 - rho**2)

247244248-

#yhat

249-

yhat = rho*y[:-1]

250-

y_data = pmc.Normal('y_obs', mu = yhat, sigma=sigma, observed=y[1:])

251-

y0_data = pmc.Normal('y0_obs', mu = 0., sigma=y_sd, observed=y[0])

245+

# yhat

246+

yhat = rho * y[:-1]

247+

y_data = pmc.Normal('y_obs', mu=yhat, sigma=sigma, observed=y[1:])

248+

y0_data = pmc.Normal('y0_obs', mu=0., sigma=y_sd, observed=y[0])

252249

```

253250254251

```{code-cell} ipython3

@@ -257,7 +254,7 @@ with AR1_model_y0:

257254

with AR1_model_y0:

258255

trace_y0 = pmc.sample(50000, tune=10000, return_inferencedata=True)

259256260-

# grey vertical lines are the cases of divergence

257+

# Grey vertical lines are the cases of divergence

261258

```

262259263260

```{code-cell} ipython3

@@ -269,7 +266,6 @@ with AR1_model_y0:

269266

with AR1_model:

270267

summary_y0 = az.summary(trace_y0, round_to=4)

271268272-

# print

273269

summary_y0

274270

```

275271

@@ -284,7 +280,7 @@ We'll return to this issue after we use `numpyro` to compute posteriors under ou

284280285281

We'll now repeat the calculations using `numpyro`.

286282287-

## `Numpyro` Implementation

283+

## Numpyro Implementation

288284289285

```{code-cell} ipython3

290286

@@ -293,25 +289,25 @@ def plot_posterior(sample):

293289

"""

294290

Plot trace and histogram

295291

"""

296-

# to np array

292+

# To np array

297293

rhos = sample['rho']

298294

sigmas = sample['sigma']

299295

rhos, sigmas, = np.array(rhos), np.array(sigmas)

300296301-

fig, axs = plt.subplots(2,2, figsize=(17,6))

302-

# plot trace

303-

axs[0,0].plot(rhos) # rho

304-

axs[1,0].plot(sigmas) # sigma

297+

fig, axs = plt.subplots(2, 2, figsize=(17, 6))

298+

# Plot trace

299+

axs[0, 0].plot(rhos) # rho

300+

axs[1, 0].plot(sigmas) # sigma

305301306-

# plot posterior

307-

axs[0,1].hist(rhos, bins=50, density=True, alpha=0.7)

308-

axs[0,1].set_xlim([0,1])

309-

axs[1,1].hist(sigmas, bins=50, density=True, alpha=0.7)

302+

# Plot posterior

303+

axs[0, 1].hist(rhos, bins=50, density=True, alpha=0.7)

304+

axs[0, 1].set_xlim([0, 1])

305+

axs[1, 1].hist(sigmas, bins=50, density=True, alpha=0.7)

310306311-

axs[0,0].set_title("rho")

312-

axs[0,1].set_title("rho")

313-

axs[1,0].set_title("sigma")

314-

axs[1,1].set_title("sigma")

307+

axs[0, 0].set_title("rho")

308+

axs[0, 1].set_title("rho")

309+

axs[1, 0].set_title("sigma")

310+

axs[1, 1].set_title("sigma")

315311

plt.show()

316312

```

317313

@@ -322,7 +318,7 @@ def AR1_model(data):

322318

sigma = numpyro.sample('sigma', dist.HalfNormal(scale=np.sqrt(10)))

323319324320

# Expected value of y at the next period (rho * y)

325-

yhat = rho*data[:-1]

321+

yhat = rho * data[:-1]

326322327323

# Likelihood of the actual realization.

328324

y_data = numpyro.sample('y_obs', dist.Normal(loc=yhat, scale=sigma), obs=data[1:])

@@ -332,13 +328,13 @@ def AR1_model(data):

332328

```{code-cell} ipython3

333329

:tag: [hide-output]

334330335-

# make jnp array

331+

# Make jnp array

336332

y = jnp.array(y)

337333338-

# set NUTS kernal

334+

# Set NUTS kernal

339335

NUTS_kernel = numpyro.infer.NUTS(AR1_model)

340336341-

# run MCMC

337+

# Run MCMC

342338

mcmc = numpyro.infer.MCMC(NUTS_kernel, num_samples=50000, num_warmup=10000, progress_bar=False)

343339

mcmc.run(rng_key=random.PRNGKey(1), data=y)

344340

```

@@ -361,15 +357,15 @@ Here's the new code to achieve this.

361357362358

```{code-cell} ipython3

363359

def AR1_model_y0(data):

364-

# set prior

360+

# Set prior

365361

rho = numpyro.sample('rho', dist.Uniform(low=-1., high=1.))

366362

sigma = numpyro.sample('sigma', dist.HalfNormal(scale=np.sqrt(10)))

367363368-

#standard deviation of ergodic y

369-

y_sd = sigma/jnp.sqrt(1-rho**2)

364+

# Standard deviation of ergodic y

365+

y_sd = sigma / jnp.sqrt(1 - rho**2)

370366371367

# Expected value of y at the next period (rho * y)

372-

yhat = rho*data[:-1]

368+

yhat = rho * data[:-1]

373369374370

# Likelihood of the actual realization.

375371

y_data = numpyro.sample('y_obs', dist.Normal(loc=yhat, scale=sigma), obs=data[1:])

@@ -379,15 +375,13 @@ def AR1_model_y0(data):

379375

```{code-cell} ipython3

380376

:tag: [hide-output]

381377382-

# make jnp array

378+

# Make jnp array

383379

y = jnp.array(y)

384380385-

# set NUTS kernal

381+

# Set NUTS kernal

386382

NUTS_kernel = numpyro.infer.NUTS(AR1_model_y0)

387383388-

# run MCMC

389-390-384+

# Run MCMC

391385

mcmc2 = numpyro.infer.MCMC(NUTS_kernel, num_samples=50000, num_warmup=10000, progress_bar=False)

392386

mcmc2.run(rng_key=random.PRNGKey(1), data=y)

393387

```

@@ -402,10 +396,10 @@ mcmc2.print_summary()

402396403397

Look what happened to the posterior!

404398405-

It has moved far from the true values of the parameters used to generate the data because of how Bayes Law (i.e., conditional probability)

406-

is telling `numpyro` to explain what it interprets as "explosive" observations early in the sample

399+

It has moved far from the true values of the parameters used to generate the data because of how Bayes' Law (i.e., conditional probability)

400+

is telling `numpyro` to explain what it interprets as "explosive" observations early in the sample.

407401408-

Bayes Law is able to generates a plausible likelihood for the first observation is by driving $\rho \rightarrow 1$ and $\sigma \uparrow$ in order to raise the variance of the stationary distribution.

402+

Bayes' Law is able to generate a plausible likelihood for the first observation by driving $\rho \rightarrow 1$ and $\sigma \uparrow$ in order to raise the variance of the stationary distribution.

409403410-

Our example illustrates the importance of what you assume about the distribution of initial conditions.

404+

Our example illustrates the importance of what you assume about the distribution of initial conditions.

411405

Read the original on github.com ↗