-
Notifications
You must be signed in to change notification settings - Fork 284
/
hpd.py
64 lines (52 loc) · 1.8 KB
/
hpd.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
"""
This code was taken form the PyMC library https://github.com/pymc-devs/pymc
"""
import numpy as np
def calc_min_interval(x, alpha):
"""Internal method to determine the minimum interval of a given width
Assumes that x is sorted numpy array.
"""
n = len(x)
cred_mass = 1.0-alpha
interval_idx_inc = int(np.floor(cred_mass*n))
n_intervals = n - interval_idx_inc
interval_width = x[interval_idx_inc:] - x[:n_intervals]
if len(interval_width) == 0:
raise ValueError('Too few elements for interval calculation')
min_idx = np.argmin(interval_width)
hdi_min = x[min_idx]
hdi_max = x[min_idx+interval_idx_inc]
return hdi_min, hdi_max
def hpd(x, alpha=0.05):
"""Calculate highest posterior density (HPD) of array for given alpha.
The HPD is the minimum width Bayesian credible interval (BCI).
:Arguments:
x : Numpy array
An array containing MCMC samples
alpha : float
Desired probability of type I error (defaults to 0.05)
"""
# Make a copy of trace
x = x.copy()
# For multivariate node
if x.ndim > 1:
# Transpose first, then sort
tx = np.transpose(x, list(range(x.ndim))[1:]+[0])
dims = np.shape(tx)
# Container list for intervals
intervals = np.resize(0.0, dims[:-1]+(2,))
for index in make_indices(dims[:-1]):
try:
index = tuple(index)
except TypeError:
pass
# Sort trace
sx = np.sort(tx[index])
# Append to list
intervals[index] = calc_min_interval(sx, alpha)
# Transpose back before returning
return np.array(intervals)
else:
# Sort univariate node
sx = np.sort(x)
return np.array(calc_min_interval(sx, alpha))