inference-tools 0.14.0__py3-none-any.whl → 0.14.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- inference/_version.py +2 -2
- inference/likelihoods.py +2 -2
- inference/mcmc/{hmc.py → hmc/__init__.py} +39 -89
- inference/mcmc/hmc/epsilon.py +68 -0
- inference/mcmc/hmc/mass.py +80 -0
- inference/plotting.py +3 -21
- {inference_tools-0.14.0.dist-info → inference_tools-0.14.1.dist-info}/METADATA +3 -2
- {inference_tools-0.14.0.dist-info → inference_tools-0.14.1.dist-info}/RECORD +11 -9
- {inference_tools-0.14.0.dist-info → inference_tools-0.14.1.dist-info}/WHEEL +1 -1
- {inference_tools-0.14.0.dist-info → inference_tools-0.14.1.dist-info/licenses}/LICENSE +0 -0
- {inference_tools-0.14.0.dist-info → inference_tools-0.14.1.dist-info}/top_level.txt +0 -0
inference/_version.py
CHANGED
inference/likelihoods.py
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
from abc import ABC, abstractmethod
|
|
6
|
-
from numpy import array, log, exp, pi, sqrt, ndarray
|
|
6
|
+
from numpy import array, log, exp, pi, sqrt, ndarray, logaddexp
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class Likelihood(ABC):
|
|
@@ -254,7 +254,7 @@ class LogisticLikelihood(Likelihood):
|
|
|
254
254
|
|
|
255
255
|
def _log_likelihood(self, predictions: ndarray) -> float:
|
|
256
256
|
z = (self.y - predictions) * self.inv_scale
|
|
257
|
-
return z.sum() - 2 *
|
|
257
|
+
return z.sum() - 2 * logaddexp(0.0, z).sum() + self.normalisation
|
|
258
258
|
|
|
259
259
|
def _log_likelihood_gradient(
|
|
260
260
|
self, predictions: ndarray, predictions_jacobian: ndarray
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
from copy import copy
|
|
2
1
|
import matplotlib.pyplot as plt
|
|
3
2
|
|
|
4
3
|
from numpy import ndarray, float64
|
|
5
4
|
from numpy import array, savez, savez_compressed, load, zeros
|
|
6
|
-
from numpy import
|
|
5
|
+
from numpy import var, isfinite, exp, mean, argmax, percentile, cov
|
|
7
6
|
from numpy.random import default_rng
|
|
8
7
|
|
|
9
8
|
from inference.mcmc.utilities import Bounds, ChainProgressPrinter, effective_sample_size
|
|
10
9
|
from inference.mcmc.base import MarkovChain
|
|
10
|
+
from inference.mcmc.hmc.epsilon import EpsilonSelector
|
|
11
|
+
from inference.mcmc.hmc.mass import get_particle_mass
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
class HamiltonianChain(MarkovChain):
|
|
@@ -51,10 +52,12 @@ class HamiltonianChain(MarkovChain):
|
|
|
51
52
|
in the form ``(lower_bounds, upper_bounds)``.
|
|
52
53
|
|
|
53
54
|
:param inverse_mass: \
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
The inverse-mass can be given as either a vector or matrix, and is used to
|
|
56
|
+
transform the momentum distribution so the chain can explore the posterior
|
|
57
|
+
efficiently. If given as a vector, the inverse mass should have values which
|
|
58
|
+
approximate the variance of the marginal distributions of each parameter.
|
|
59
|
+
If given as a matrix, the inverse mass should be a valid covariance matrix
|
|
60
|
+
for a multivariate normal distribution which approximates the posterior.
|
|
58
61
|
|
|
59
62
|
:param bool display_progress: \
|
|
60
63
|
If set as ``True``, a message is displayed during sampling
|
|
@@ -77,9 +80,6 @@ class HamiltonianChain(MarkovChain):
|
|
|
77
80
|
# if no gradient function is supplied, default to finite difference
|
|
78
81
|
self.grad = self.finite_diff if grad is None else grad
|
|
79
82
|
|
|
80
|
-
# set the inverse mass to 1 if none supplied
|
|
81
|
-
self.inv_mass = 1.0 if inverse_mass is None else inverse_mass
|
|
82
|
-
self.sqrt_mass = 1.0 / sqrt(self.inv_mass)
|
|
83
83
|
self.temperature = temperature
|
|
84
84
|
self.inv_temp = 1.0 / temperature
|
|
85
85
|
|
|
@@ -91,7 +91,12 @@ class HamiltonianChain(MarkovChain):
|
|
|
91
91
|
self.theta = [start]
|
|
92
92
|
self.probs = [self.posterior(start) * self.inv_temp]
|
|
93
93
|
self.leapfrog_steps = [0]
|
|
94
|
-
self.n_parameters =
|
|
94
|
+
self.n_parameters = start.size
|
|
95
|
+
self.mass = get_particle_mass(
|
|
96
|
+
inverse_mass=inverse_mass if inverse_mass is not None else 1.0,
|
|
97
|
+
n_parameters=self.n_parameters,
|
|
98
|
+
)
|
|
99
|
+
|
|
95
100
|
self.chain_length = 1
|
|
96
101
|
|
|
97
102
|
# set either the bounded or unbounded leapfrog update
|
|
@@ -125,16 +130,16 @@ class HamiltonianChain(MarkovChain):
|
|
|
125
130
|
"""
|
|
126
131
|
steps_taken = 0
|
|
127
132
|
for attempt in range(self.max_attempts):
|
|
128
|
-
r0 = self.
|
|
133
|
+
r0 = self.mass.sample_momentum(self.rng)
|
|
129
134
|
t0 = self.theta[-1]
|
|
130
|
-
H0 =
|
|
135
|
+
H0 = self.kinetic_energy(r0) - self.probs[-1]
|
|
131
136
|
|
|
132
137
|
n_steps = int(self.steps * (1 + (self.rng.random() - 0.5) * 0.2))
|
|
133
138
|
t, r = self.run_leapfrog(t0.copy(), r0.copy(), n_steps)
|
|
134
139
|
|
|
135
140
|
steps_taken += n_steps
|
|
136
141
|
p = self.posterior(t) * self.inv_temp
|
|
137
|
-
H =
|
|
142
|
+
H = self.kinetic_energy(r) - p
|
|
138
143
|
accept_prob = exp(H0 - H)
|
|
139
144
|
|
|
140
145
|
self.ES.add_probability(
|
|
@@ -159,38 +164,49 @@ class HamiltonianChain(MarkovChain):
|
|
|
159
164
|
def standard_leapfrog(
|
|
160
165
|
self, t: ndarray, r: ndarray, n_steps: int
|
|
161
166
|
) -> tuple[ndarray, ndarray]:
|
|
162
|
-
t_step = self.inv_mass * self.ES.epsilon
|
|
163
167
|
r_step = self.inv_temp * self.ES.epsilon
|
|
164
168
|
r += (0.5 * r_step) * self.grad(t)
|
|
169
|
+
|
|
165
170
|
for _ in range(n_steps - 1):
|
|
166
|
-
t +=
|
|
171
|
+
t += self.ES.epsilon * self.mass.get_velocity(r)
|
|
167
172
|
r += r_step * self.grad(t)
|
|
168
|
-
|
|
173
|
+
|
|
174
|
+
t += self.ES.epsilon * self.mass.get_velocity(r)
|
|
169
175
|
r += (0.5 * r_step) * self.grad(t)
|
|
170
176
|
return t, r
|
|
171
177
|
|
|
172
178
|
def bounded_leapfrog(
|
|
173
179
|
self, t: ndarray, r: ndarray, n_steps: int
|
|
174
180
|
) -> tuple[ndarray, ndarray]:
|
|
175
|
-
t_step = self.inv_mass * self.ES.epsilon
|
|
176
181
|
r_step = self.inv_temp * self.ES.epsilon
|
|
177
182
|
r += (0.5 * r_step) * self.grad(t)
|
|
183
|
+
|
|
178
184
|
for _ in range(n_steps - 1):
|
|
179
|
-
t +=
|
|
185
|
+
t += self.ES.epsilon * self.mass.get_velocity(r)
|
|
180
186
|
t, reflections = self.bounds.reflect_momenta(t)
|
|
181
187
|
r *= reflections
|
|
182
188
|
r += r_step * self.grad(t)
|
|
183
|
-
|
|
189
|
+
|
|
190
|
+
t += self.ES.epsilon * self.mass.get_velocity(r)
|
|
184
191
|
t, reflections = self.bounds.reflect_momenta(t)
|
|
185
192
|
r *= reflections
|
|
186
193
|
r += (0.5 * r_step) * self.grad(t)
|
|
187
194
|
return t, r
|
|
188
195
|
|
|
189
196
|
def hamiltonian(self, t: ndarray, r: ndarray) -> float:
|
|
190
|
-
return 0.5 *
|
|
197
|
+
return 0.5 * (r @ self.mass.get_velocity(r)) - self.posterior(t) * self.inv_temp
|
|
198
|
+
|
|
199
|
+
def kinetic_energy(self, r: ndarray) -> float:
|
|
200
|
+
return 0.5 * (r @ self.mass.get_velocity(r))
|
|
191
201
|
|
|
192
|
-
def estimate_mass(self, burn=1, thin=1):
|
|
193
|
-
|
|
202
|
+
def estimate_mass(self, burn=1, thin=1, diagonal=True):
|
|
203
|
+
if diagonal:
|
|
204
|
+
inverse_mass = var(array(self.theta[burn::thin]), axis=0)
|
|
205
|
+
else:
|
|
206
|
+
inverse_mass = cov(array(self.theta[burn::thin]).T)
|
|
207
|
+
self.mass = get_particle_mass(
|
|
208
|
+
inverse_mass=inverse_mass, n_parameters=self.n_parameters
|
|
209
|
+
)
|
|
194
210
|
|
|
195
211
|
def finite_diff(self, t: ndarray) -> ndarray:
|
|
196
212
|
p = self.posterior(t) * self.inv_temp
|
|
@@ -393,7 +409,7 @@ class HamiltonianChain(MarkovChain):
|
|
|
393
409
|
|
|
394
410
|
def save(self, filename, compressed=False):
|
|
395
411
|
items = {
|
|
396
|
-
"inv_mass": self.inv_mass,
|
|
412
|
+
"inv_mass": self.mass.inv_mass,
|
|
397
413
|
"inv_temp": self.inv_temp,
|
|
398
414
|
"theta": self.theta,
|
|
399
415
|
"probs": self.probs,
|
|
@@ -451,69 +467,3 @@ class HamiltonianChain(MarkovChain):
|
|
|
451
467
|
# build the epsilon selector
|
|
452
468
|
chain.ES.load_items(D)
|
|
453
469
|
return chain
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
class EpsilonSelector:
|
|
457
|
-
def __init__(self, epsilon: float):
|
|
458
|
-
# storage
|
|
459
|
-
self.epsilon = epsilon
|
|
460
|
-
self.epsilon_values = [copy(epsilon)] # sigma values after each assessment
|
|
461
|
-
self.epsilon_checks = [0.0] # chain locations at which sigma was assessed
|
|
462
|
-
|
|
463
|
-
# tracking variables
|
|
464
|
-
self.avg = 0
|
|
465
|
-
self.var = 0
|
|
466
|
-
self.num = 0
|
|
467
|
-
|
|
468
|
-
# settings for epsilon adjustment algorithm
|
|
469
|
-
self.accept_rate = 0.65
|
|
470
|
-
self.chk_int = 15 # interval of steps at which proposal widths are adjusted
|
|
471
|
-
self.growth_factor = 1.4 # growth factor for self.chk_int
|
|
472
|
-
|
|
473
|
-
def add_probability(self, p: float):
|
|
474
|
-
self.num += 1
|
|
475
|
-
self.avg += p
|
|
476
|
-
self.var += max(p * (1 - p), 0.03)
|
|
477
|
-
|
|
478
|
-
if self.num >= self.chk_int:
|
|
479
|
-
self.update_epsilon()
|
|
480
|
-
|
|
481
|
-
def update_epsilon(self):
|
|
482
|
-
"""
|
|
483
|
-
looks at average tries over recent steps, and adjusts proposal
|
|
484
|
-
widths self.sigma to bring the average towards self.target_tries.
|
|
485
|
-
"""
|
|
486
|
-
# normal approximation of poisson binomial distribution
|
|
487
|
-
mu = self.avg / self.num
|
|
488
|
-
std = sqrt(self.var) / self.num
|
|
489
|
-
|
|
490
|
-
# now check if the desired success rate is within 2-sigma
|
|
491
|
-
if ~(mu - 2 * std < self.accept_rate < mu + 2 * std):
|
|
492
|
-
adj = (log(self.accept_rate) / log(mu)) ** 0.15
|
|
493
|
-
adj = min(adj, 2.0)
|
|
494
|
-
adj = max(adj, 0.5)
|
|
495
|
-
self.adjust_epsilon(adj)
|
|
496
|
-
else: # increase the check interval
|
|
497
|
-
self.chk_int = int((self.growth_factor * self.chk_int) * 0.1) * 10
|
|
498
|
-
|
|
499
|
-
def adjust_epsilon(self, ratio: float):
|
|
500
|
-
self.epsilon *= ratio
|
|
501
|
-
self.epsilon_values.append(copy(self.epsilon))
|
|
502
|
-
self.epsilon_checks.append(self.epsilon_checks[-1] + self.num)
|
|
503
|
-
self.avg = 0
|
|
504
|
-
self.var = 0
|
|
505
|
-
self.num = 0
|
|
506
|
-
|
|
507
|
-
def get_items(self):
|
|
508
|
-
return self.__dict__
|
|
509
|
-
|
|
510
|
-
def load_items(self, dictionary: dict):
|
|
511
|
-
self.epsilon = float(dictionary["epsilon"])
|
|
512
|
-
self.epsilon_values = list(dictionary["epsilon_values"])
|
|
513
|
-
self.epsilon_checks = list(dictionary["epsilon_checks"])
|
|
514
|
-
self.avg = float(dictionary["avg"])
|
|
515
|
-
self.var = float(dictionary["var"])
|
|
516
|
-
self.num = float(dictionary["num"])
|
|
517
|
-
self.accept_rate = float(dictionary["accept_rate"])
|
|
518
|
-
self.chk_int = int(dictionary["chk_int"])
|
|
519
|
-
self.growth_factor = float(dictionary["growth_factor"])
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
from copy import copy
|
|
2
|
+
from numpy import sqrt, log
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class EpsilonSelector:
|
|
6
|
+
def __init__(self, epsilon: float):
|
|
7
|
+
# storage
|
|
8
|
+
self.epsilon = epsilon
|
|
9
|
+
self.epsilon_values = [copy(epsilon)] # sigma values after each assessment
|
|
10
|
+
self.epsilon_checks = [0.0] # chain locations at which sigma was assessed
|
|
11
|
+
|
|
12
|
+
# tracking variables
|
|
13
|
+
self.avg = 0
|
|
14
|
+
self.var = 0
|
|
15
|
+
self.num = 0
|
|
16
|
+
|
|
17
|
+
# settings for epsilon adjustment algorithm
|
|
18
|
+
self.accept_rate = 0.65
|
|
19
|
+
self.chk_int = 15 # interval of steps at which proposal widths are adjusted
|
|
20
|
+
self.growth_factor = 1.4 # growth factor for self.chk_int
|
|
21
|
+
|
|
22
|
+
def add_probability(self, p: float):
|
|
23
|
+
self.num += 1
|
|
24
|
+
self.avg += p
|
|
25
|
+
self.var += max(p * (1 - p), 0.03)
|
|
26
|
+
|
|
27
|
+
if self.num >= self.chk_int:
|
|
28
|
+
self.update_epsilon()
|
|
29
|
+
|
|
30
|
+
def update_epsilon(self):
|
|
31
|
+
"""
|
|
32
|
+
looks at the acceptance rate of proposed steps and adjusts the epsilon
|
|
33
|
+
value to bring the acceptance rate toward its target value.
|
|
34
|
+
"""
|
|
35
|
+
# normal approximation of poisson binomial distribution
|
|
36
|
+
mu = self.avg / self.num
|
|
37
|
+
std = sqrt(self.var) / self.num
|
|
38
|
+
|
|
39
|
+
# now check if the desired success rate is within 2-sigma
|
|
40
|
+
if ~(mu - 2 * std < self.accept_rate < mu + 2 * std):
|
|
41
|
+
adj = (log(self.accept_rate) / log(mu)) ** 0.15
|
|
42
|
+
adj = min(adj, 2.0)
|
|
43
|
+
adj = max(adj, 0.5)
|
|
44
|
+
self.adjust_epsilon(adj)
|
|
45
|
+
else: # increase the check interval
|
|
46
|
+
self.chk_int = int((self.growth_factor * self.chk_int) * 0.1) * 10
|
|
47
|
+
|
|
48
|
+
def adjust_epsilon(self, ratio: float):
|
|
49
|
+
self.epsilon *= ratio
|
|
50
|
+
self.epsilon_values.append(copy(self.epsilon))
|
|
51
|
+
self.epsilon_checks.append(self.epsilon_checks[-1] + self.num)
|
|
52
|
+
self.avg = 0
|
|
53
|
+
self.var = 0
|
|
54
|
+
self.num = 0
|
|
55
|
+
|
|
56
|
+
def get_items(self):
|
|
57
|
+
return self.__dict__
|
|
58
|
+
|
|
59
|
+
def load_items(self, dictionary: dict):
|
|
60
|
+
self.epsilon = float(dictionary["epsilon"])
|
|
61
|
+
self.epsilon_values = list(dictionary["epsilon_values"])
|
|
62
|
+
self.epsilon_checks = list(dictionary["epsilon_checks"])
|
|
63
|
+
self.avg = float(dictionary["avg"])
|
|
64
|
+
self.var = float(dictionary["var"])
|
|
65
|
+
self.num = float(dictionary["num"])
|
|
66
|
+
self.accept_rate = float(dictionary["accept_rate"])
|
|
67
|
+
self.chk_int = int(dictionary["chk_int"])
|
|
68
|
+
self.growth_factor = float(dictionary["growth_factor"])
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Union
|
|
3
|
+
from numpy import ndarray, sqrt, eye, isscalar
|
|
4
|
+
from numpy.random import Generator
|
|
5
|
+
from numpy.linalg import cholesky
|
|
6
|
+
from scipy.linalg import solve_triangular
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ParticleMass(ABC):
|
|
10
|
+
inv_mass: Union[float, ndarray]
|
|
11
|
+
|
|
12
|
+
@abstractmethod
|
|
13
|
+
def get_velocity(self, r: ndarray) -> ndarray:
|
|
14
|
+
pass
|
|
15
|
+
|
|
16
|
+
@abstractmethod
|
|
17
|
+
def sample_momentum(self, rng: Generator) -> ndarray:
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ScalarMass(ParticleMass):
|
|
22
|
+
def __init__(self, inv_mass: float, n_parameters: int):
|
|
23
|
+
self.inv_mass = inv_mass
|
|
24
|
+
self.sqrt_mass = 1 / sqrt(self.inv_mass)
|
|
25
|
+
self.n_parameters = n_parameters
|
|
26
|
+
|
|
27
|
+
def get_velocity(self, r: ndarray) -> ndarray:
|
|
28
|
+
return r * self.inv_mass
|
|
29
|
+
|
|
30
|
+
def sample_momentum(self, rng: Generator) -> ndarray:
|
|
31
|
+
return rng.normal(size=self.n_parameters, scale=self.sqrt_mass)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class VectorMass(ScalarMass):
|
|
35
|
+
def __init__(self, inv_mass: ndarray, n_parameters: int):
|
|
36
|
+
super().__init__(inv_mass, n_parameters)
|
|
37
|
+
assert inv_mass.ndim == 1
|
|
38
|
+
assert inv_mass.size == n_parameters
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class MatrixMass(ParticleMass):
|
|
42
|
+
def __init__(self, inv_mass: ndarray, n_parameters: int):
|
|
43
|
+
assert inv_mass.ndim == 2
|
|
44
|
+
assert inv_mass.shape[0] == inv_mass.shape[1] == n_parameters
|
|
45
|
+
assert (inv_mass == inv_mass.T).all()
|
|
46
|
+
|
|
47
|
+
self.inv_mass = inv_mass
|
|
48
|
+
self.n_parameters = n_parameters
|
|
49
|
+
# find the cholesky decomp of the mass matrix
|
|
50
|
+
iL = cholesky(inv_mass)
|
|
51
|
+
self.L = solve_triangular(iL, eye(self.n_parameters), lower=True).T
|
|
52
|
+
|
|
53
|
+
def get_velocity(self, r: ndarray) -> ndarray:
|
|
54
|
+
return self.inv_mass @ r
|
|
55
|
+
|
|
56
|
+
def sample_momentum(self, rng: Generator) -> ndarray:
|
|
57
|
+
return self.L @ rng.normal(size=self.n_parameters)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def get_particle_mass(
|
|
61
|
+
inverse_mass: Union[float, ndarray], n_parameters: int
|
|
62
|
+
) -> ParticleMass:
|
|
63
|
+
if isscalar(inverse_mass):
|
|
64
|
+
return ScalarMass(inverse_mass, n_parameters)
|
|
65
|
+
|
|
66
|
+
if not isinstance(inverse_mass, ndarray):
|
|
67
|
+
raise TypeError(
|
|
68
|
+
f"""\n
|
|
69
|
+
\r[ HamiltonianChain error ]
|
|
70
|
+
\r>> The value given to the 'inverse_mass' keyword argument must be either
|
|
71
|
+
\r>> a scalar type (e.g. int or float), or a numpy.ndarray.
|
|
72
|
+
\r>> Instead, the given value has type:
|
|
73
|
+
\r>> {type(inverse_mass)}
|
|
74
|
+
"""
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
if inverse_mass.ndim == 1:
|
|
78
|
+
return VectorMass(inverse_mass, n_parameters)
|
|
79
|
+
else:
|
|
80
|
+
return MatrixMass(inverse_mass, n_parameters)
|
inference/plotting.py
CHANGED
|
@@ -445,29 +445,11 @@ def hdi_plot(
|
|
|
445
445
|
if axis is None:
|
|
446
446
|
_, axis = plt.subplots()
|
|
447
447
|
|
|
448
|
-
from numpy import take_along_axis, expand_dims
|
|
449
|
-
|
|
450
448
|
# iterate over the intervals and plot each
|
|
451
449
|
for frac, col in zip(intervals, colors):
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
if n > L:
|
|
456
|
-
# find the optimal single HDI
|
|
457
|
-
widths = s[L:, :] - s[: n - L, :]
|
|
458
|
-
i = expand_dims(widths.argmin(axis=0), axis=0)
|
|
459
|
-
lwr = take_along_axis(s, i, 0).squeeze()
|
|
460
|
-
upr = take_along_axis(s, i + L, 0).squeeze()
|
|
461
|
-
else:
|
|
462
|
-
lwr = s[0, :]
|
|
463
|
-
upr = s[-1, :]
|
|
464
|
-
|
|
465
|
-
if label_intervals:
|
|
466
|
-
axis.fill_between(
|
|
467
|
-
x, lwr, upr, color=col, label="{}% HDI".format(int(100 * frac))
|
|
468
|
-
)
|
|
469
|
-
else:
|
|
470
|
-
axis.fill_between(x, lwr, upr, color=col)
|
|
450
|
+
lwr, upr = sample_hdi(s, fraction=frac)
|
|
451
|
+
lab = f"{int(100 * frac)}% HDI" if label_intervals else None
|
|
452
|
+
axis.fill_between(x, lwr, upr, color=col, label=lab)
|
|
471
453
|
|
|
472
454
|
return axis
|
|
473
455
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: inference-tools
|
|
3
|
-
Version: 0.14.
|
|
3
|
+
Version: 0.14.1
|
|
4
4
|
Summary: A collection of python tools for Bayesian data analysis
|
|
5
5
|
Author-email: Chris Bowman <chris.bowman.physics@gmail.com>
|
|
6
6
|
License: MIT License
|
|
@@ -42,6 +42,7 @@ Requires-Dist: pytest-cov>=3.0.0; extra == "tests"
|
|
|
42
42
|
Requires-Dist: pyqt5>=5.15; extra == "tests"
|
|
43
43
|
Requires-Dist: hypothesis>=6.24; extra == "tests"
|
|
44
44
|
Requires-Dist: freezegun>=1.1.0; extra == "tests"
|
|
45
|
+
Dynamic: license-file
|
|
45
46
|
|
|
46
47
|
# inference-tools
|
|
47
48
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
inference/__init__.py,sha256=Wheq9bSUF5Y_jAc_w_Avi4WW2kphDK0qHGM6FsIKSxY,275
|
|
2
|
-
inference/_version.py,sha256=
|
|
3
|
-
inference/likelihoods.py,sha256=
|
|
4
|
-
inference/plotting.py,sha256=
|
|
2
|
+
inference/_version.py,sha256=9-B5HerO_wiKUcm3zqJZazE8kjqwU6_WcIM1m-vWIoQ,513
|
|
3
|
+
inference/likelihoods.py,sha256=0mRn9S7CaX6hNv1fKVeaAFYk50bALvVbyX7E2aH3Bn8,10021
|
|
4
|
+
inference/plotting.py,sha256=vMpRGiZMMlVgAcVaKC2wtvjzVlBmOkC2BM90A3wSwJ8,19194
|
|
5
5
|
inference/posterior.py,sha256=ptPZgzT--ehbpu57nW9GmFuyovFOSmw56HWfuC-8GGA,3584
|
|
6
6
|
inference/priors.py,sha256=zDuIgJTZrqEqkp8rE-aBRlAuqBacR9aC_QNm8jNIYl8,19368
|
|
7
7
|
inference/approx/__init__.py,sha256=b8xCdshVeGHyao6-P0038QB71WOMLrcYXCOYiYjK7Tk,132
|
|
@@ -17,17 +17,19 @@ inference/mcmc/__init__.py,sha256=IsEhVSIpZCDNIqgSq_21M6DH6x8F1jJbYWM0e3S3QG4,44
|
|
|
17
17
|
inference/mcmc/base.py,sha256=cEh1LPmKd6JMop8EcuH3dvAeJYei88pcPTw1xe7tGKY,10496
|
|
18
18
|
inference/mcmc/ensemble.py,sha256=JRXu7SBYXN4Y9RzgA6kGUHpZNw4q4A9wf0KOAQdlz0E,15585
|
|
19
19
|
inference/mcmc/gibbs.py,sha256=f-eccDBILfaZercZii3vuJ29V505VUsCHoxhD9gZ7xA,24288
|
|
20
|
-
inference/mcmc/hmc.py,sha256=7SDjiwzVCqme1g8v65XldQpW5dnt7O3p1IG2AYGBb4o,19484
|
|
21
20
|
inference/mcmc/parallel.py,sha256=SKLzMP4aqIj1xsxKuByA1lr1GdgIu5pPzVw7hlfXZEQ,14053
|
|
22
21
|
inference/mcmc/pca.py,sha256=NxC81NghGlBQslFVOk2HzpsnCjlEdDnv_w8es4Qe7PU,10695
|
|
23
22
|
inference/mcmc/utilities.py,sha256=YjpK3FvV0Q98jLusrZrvGck-bjm6uZZ1U7HHH3aly8g,6048
|
|
23
|
+
inference/mcmc/hmc/__init__.py,sha256=R2ZjKca1CjWwzAHRKetZOAbiJKo2YZVmX4jrz2EAyL4,17661
|
|
24
|
+
inference/mcmc/hmc/epsilon.py,sha256=t2kNi10MSVFXjmAx5zRUARDuPu_yWbwoK2McMuaaAUs,2467
|
|
25
|
+
inference/mcmc/hmc/mass.py,sha256=qnxsbkogZFeqGbssZ2w4tsaUGytEXL-I0Gqs4UZzcAg,2545
|
|
24
26
|
inference/pdf/__init__.py,sha256=gVmQ1HLTab6_oWMQN26A1r7PkqbApaJmBK-c7TIFxjY,270
|
|
25
27
|
inference/pdf/base.py,sha256=Zj5mfFmDqTe5cFz0biBxcvEaxdOUC-SsOUjebUEX7HM,5442
|
|
26
28
|
inference/pdf/hdi.py,sha256=soFw3fKQdzxbGNhU9BvFHdt0uGKfhus3E3vM6L47yhY,4638
|
|
27
29
|
inference/pdf/kde.py,sha256=KSl8y---602MlxoSVH8VknNQYZ2KAOTky50QU3jRw28,12999
|
|
28
30
|
inference/pdf/unimodal.py,sha256=9S05c0hq_rF-MLoDJgUmaJKRdcP8F9_Idj7Ncb6m9q0,6218
|
|
29
|
-
inference_tools-0.14.
|
|
30
|
-
inference_tools-0.14.
|
|
31
|
-
inference_tools-0.14.
|
|
32
|
-
inference_tools-0.14.
|
|
33
|
-
inference_tools-0.14.
|
|
31
|
+
inference_tools-0.14.1.dist-info/licenses/LICENSE,sha256=Y0-EfO5pdxf6d0J6Er13ZSWiPZ2o6kHvM37eRgnJdww,1069
|
|
32
|
+
inference_tools-0.14.1.dist-info/METADATA,sha256=flIdPaL3VFTzogPS-k2CwjIu_kbww--4libVTB9zegY,5400
|
|
33
|
+
inference_tools-0.14.1.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
|
34
|
+
inference_tools-0.14.1.dist-info/top_level.txt,sha256=I7bsb71rLtH3yvVH_HSLXUosY2AwCxEG3vctNsEhbEM,10
|
|
35
|
+
inference_tools-0.14.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|