-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
Copy pathtest_func_utils.py
122 lines (110 loc) · 3.94 KB
/
test_func_utils.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# Copyright 2024 - present The PyMC Developers
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import numpy as np
import pytest
import pymc as pm
@pytest.mark.parametrize(
"distribution, lower, upper, init_guess, fixed_params, mass_below_lower",
[
(pm.Gamma, 0.1, 0.4, {"alpha": 1, "beta": 10}, {}, None),
(pm.Normal, 155, 180, {"mu": 170, "sigma": 3}, {}, None),
(pm.StudentT, 0.1, 0.4, {"mu": 10, "sigma": 3}, {"nu": 7}, None),
(pm.StudentT, 0, 1, {"mu": 5, "sigma": 2, "nu": 7}, {}, None),
(pm.Exponential, 0, 1, {"lam": 1}, {}, 0),
(pm.HalfNormal, 0, 1, {"sigma": 1}, {}, 0),
(pm.Binomial, 0, 8, {"p": 0.5}, {"n": 10}, None),
(pm.Poisson, 1, 15, {"mu": 10}, {}, None),
(pm.Poisson, 19, 41, {"mu": 30}, {}, None),
],
)
@pytest.mark.parametrize("mass", [0.5, 0.75, 0.95])
def test_find_constrained_prior(
distribution, lower, upper, init_guess, fixed_params, mass, mass_below_lower
):
opt_params = pm.find_constrained_prior(
distribution,
lower=lower,
upper=upper,
mass=mass,
init_guess=init_guess,
fixed_params=fixed_params,
mass_below_lower=mass_below_lower,
)
opt_distribution = distribution.dist(**opt_params)
mass_in_interval = (
pm.math.exp(pm.logcdf(opt_distribution, upper))
- pm.math.exp(pm.logcdf(opt_distribution, lower))
).eval()
assert np.abs(mass_in_interval - mass) <= 1e-5
@pytest.mark.parametrize(
"distribution, lower, upper, init_guess, fixed_params",
[
(pm.Gamma, 0.1, 0.4, {"alpha": 1}, {"beta": 10}),
(pm.Exponential, 0.1, 1, {"lam": 1}, {}),
(pm.Binomial, 0, 2, {"p": 0.8}, {"n": 10}),
],
)
def test_find_constrained_prior_error_too_large(
distribution, lower, upper, init_guess, fixed_params
):
with pytest.raises(
ValueError, match="Optimization of parameters failed.\nOptimization termination details:\n"
):
pm.find_constrained_prior(
distribution,
lower=lower,
upper=upper,
mass=0.95,
init_guess=init_guess,
fixed_params=fixed_params,
)
def test_find_constrained_prior_input_errors():
# missing param
with pytest.raises(TypeError, match="required positional argument"):
pm.find_constrained_prior(
pm.StudentT,
lower=0.1,
upper=0.4,
mass=0.95,
init_guess={"mu": 170, "sigma": 3},
)
# mass too high
with pytest.raises(AssertionError, match="has to be between 0.01 and 0.99"):
pm.find_constrained_prior(
pm.StudentT,
lower=0.1,
upper=0.4,
mass=0.995,
init_guess={"mu": 170, "sigma": 3},
fixed_params={"nu": 7},
)
# mass too low
with pytest.raises(AssertionError, match="has to be between 0.01 and 0.99"):
pm.find_constrained_prior(
pm.StudentT,
lower=0.1,
upper=0.4,
mass=0.005,
init_guess={"mu": 170, "sigma": 3},
fixed_params={"nu": 7},
)
# non-scalar params
with pytest.raises(NotImplementedError, match="does not work with non-scalar parameters yet"):
pm.find_constrained_prior(
pm.MvNormal,
lower=0,
upper=1,
mass=0.95,
init_guess={"mu": 5, "cov": np.asarray([[1, 0.2], [0.2, 1]])},
)