import pymc as pm
import numpy as np
import arviz as az
from pymc.math import switch, ge, exp
%load_ext lab_black
3. Revisiting UK Coal Mining Disasters*#
Adapted from Unit 10: disasters.odc.
Data can be found here.
Change Point Analysis, discussed previously in this Unit 5 example about Gibbs sampling.
The 112 data points represent the numbers of coal-mining disasters involving 10 or more men killed per year between 1851 and 1962.
Based on the observation that the there was a significant decrease around 1900, it is suitable to apply a change-point model to divide the whole dataset into two periods; each period with its own distribution of number of disasters.
The data set was compiled by Maguire, Pearson and Wynn in 1952 and updated by Jarrett (1978). This data have been used by a number of authors to illustrate various techniques that can be applied to point processes
Maguire, B. A., Pearson, E. S. and Wynn, A. H. A. (1952). The time intervals between industrial accidents. Biometrika, 39, 168†180.
Jarrett, R.G. (1979). A note on the intervals between coal-mining disasters. Biometrika, 66, 191-193.
Carlin, Gelfand, and Smith (1992) Heirarchical Bayesian Analysis of Changepoint Problems. Applied Statistics, 41, 389-405.
# X is the number of coal mine disasters per year
# fmt: off
X = np.array([4, 5, 4, 1, 0, 4, 3, 4, 0, 6, 3, 3, 4, 0, 2, 6, 3, 3, 5, 4, 5, 3, 1,
4, 4, 1, 5, 5, 3, 4, 2, 5, 2, 2, 3, 4, 2, 1, 3, 2, 2, 1, 1, 1, 1, 3,
0, 0, 1, 0, 1, 1, 0, 0, 3, 1, 0, 3, 2, 2, 0, 1, 1, 1, 0, 1, 0, 1, 0,
0, 0, 2, 1, 0, 0, 0, 1, 1, 0, 2, 3, 3, 1, 1, 2, 1, 1, 1, 1, 2, 4, 2,
0, 0, 0, 1, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1])
# fmt: on
y = np.array([y for y in range(1851, 1963)])
Model 1#
α = 4
β = 1
γ = 0.5
δ = 1
with pm.Model() as m:
year = pm.Uniform("year", 1851, 1963)
λ = pm.Gamma("λ", α, β)
μ = pm.Gamma("μ", γ, δ)
diff = pm.Deterministic("diff", μ - λ)
rate = λ + switch(ge(y - year, 0), 1, 0) * diff
pm.Poisson("lik", mu=rate, observed=X)
trace = pm.sample(2000)
Show code cell output
Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (4 chains in 4 jobs)
NUTS: [year, λ, μ]
Sampling 4 chains for 1_000 tune and 2_000 draw iterations (4_000 + 8_000 draws total) took 206 seconds.
Chain 0 reached the maximum tree depth. Increase `max_treedepth`, increase `target_accept` or reparameterize.
Chain 1 reached the maximum tree depth. Increase `max_treedepth`, increase `target_accept` or reparameterize.
Chain 2 reached the maximum tree depth. Increase `max_treedepth`, increase `target_accept` or reparameterize.
Chain 3 reached the maximum tree depth. Increase `max_treedepth`, increase `target_accept` or reparameterize.
az.summary(trace)
mean | sd | hdi_3% | hdi_97% | mcse_mean | mcse_sd | ess_bulk | ess_tail | r_hat | |
---|---|---|---|---|---|---|---|---|---|
year | 1890.405 | 2.405 | 1886.000 | 1894.461 | 0.108 | 0.076 | 537.0 | 500.0 | 1.0 |
λ | 3.153 | 0.284 | 2.655 | 3.698 | 0.011 | 0.008 | 658.0 | 1025.0 | 1.0 |
μ | 0.916 | 0.115 | 0.698 | 1.137 | 0.004 | 0.003 | 645.0 | 826.0 | 1.0 |
diff | -2.237 | 0.301 | -2.805 | -1.681 | 0.012 | 0.008 | 670.0 | 1185.0 | 1.0 |
Model 2#
with pm.Model() as m:
year = pm.Uniform("year", 1851, 1963)
z0 = pm.Normal("z0", 0, tau=0.00001)
z1 = pm.Normal("z1", 0, tau=0.00001)
λ = pm.Deterministic("λ", exp(z0))
μ = pm.Deterministic("μ", exp(z0 + z1))
diff = pm.Deterministic("diff", μ - λ)
rate = pm.math.exp(z0 + switch(ge(y - year, 0), 1, 0) * z1)
pm.Poisson("lik", mu=rate, observed=X)
trace = pm.sample(2000)
Show code cell output
Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (4 chains in 4 jobs)
NUTS: [year, z0, z1]
Sampling 4 chains for 1_000 tune and 2_000 draw iterations (4_000 + 8_000 draws total) took 302 seconds.
The rhat statistic is larger than 1.01 for some parameters. This indicates problems during sampling. See https://arxiv.org/abs/1903.08008 for details
The effective sample size per chain is smaller than 100 for some parameters. A higher number is needed for reliable rhat and ess computation. See https://arxiv.org/abs/1903.08008 for details
Chain 0 reached the maximum tree depth. Increase `max_treedepth`, increase `target_accept` or reparameterize.
Chain 1 reached the maximum tree depth. Increase `max_treedepth`, increase `target_accept` or reparameterize.
Chain 2 reached the maximum tree depth. Increase `max_treedepth`, increase `target_accept` or reparameterize.
Chain 3 reached the maximum tree depth. Increase `max_treedepth`, increase `target_accept` or reparameterize.
az.summary(trace)
mean | sd | hdi_3% | hdi_97% | mcse_mean | mcse_sd | ess_bulk | ess_tail | r_hat | |
---|---|---|---|---|---|---|---|---|---|
z0 | 1.143 | 0.089 | 0.971 | 1.306 | 0.005 | 0.003 | 378.0 | 748.0 | 1.01 |
z1 | -1.233 | 0.145 | -1.519 | -0.972 | 0.006 | 0.004 | 529.0 | 1039.0 | 1.01 |
year | 1890.258 | 2.311 | 1886.003 | 1893.954 | 0.117 | 0.083 | 409.0 | 478.0 | 1.01 |
λ | 3.147 | 0.279 | 2.620 | 3.662 | 0.014 | 0.010 | 378.0 | 748.0 | 1.01 |
μ | 0.921 | 0.116 | 0.703 | 1.141 | 0.004 | 0.003 | 946.0 | 1579.0 | 1.00 |
diff | -2.227 | 0.289 | -2.766 | -1.689 | 0.015 | 0.011 | 368.0 | 683.0 | 1.01 |
%load_ext watermark
%watermark -n -u -v -iv -p pytensor
Last updated: Wed Mar 22 2023
Python implementation: CPython
Python version : 3.11.0
IPython version : 8.9.0
pytensor: 2.10.1
pymc : 5.1.2
arviz: 0.15.1
numpy: 1.24.2