pyANOVAapprox 0.1.0__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.
- pyANOVAapprox/__init__.py +87 -0
- pyANOVAapprox/analysis.py +175 -0
- pyANOVAapprox/approx.py +464 -0
- pyANOVAapprox/errors.py +191 -0
- pyANOVAapprox/fista.py +287 -0
- pyANOVAapprox/trafos.py +127 -0
- pyanovaapprox-0.1.0.dist-info/METADATA +69 -0
- pyanovaapprox-0.1.0.dist-info/RECORD +10 -0
- pyanovaapprox-0.1.0.dist-info/WHEEL +4 -0
- pyanovaapprox-0.1.0.dist-info/licenses/LICENSE +674 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import threading
|
|
2
|
+
from math import acos, isnan
|
|
3
|
+
import math
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
from pyGroupedTransforms import *
|
|
7
|
+
from scipy.sparse.linalg import lsqr
|
|
8
|
+
from scipy.special import erf
|
|
9
|
+
#from sklearn.metrics import roc_auc_score
|
|
10
|
+
|
|
11
|
+
def get_superposition_set(d, ds): #TODO: Später funktion aut GT verwenden
|
|
12
|
+
"""
|
|
13
|
+
get_superposition_set( d::Int, ds::Int )::Vector{Vector{Int}}
|
|
14
|
+
|
|
15
|
+
This function returns ``U^{(d,ds)} = \{ \pmb u \subset \{1,2,\dots,d\} : |\pmb u| \leq ds \}``.
|
|
16
|
+
"""
|
|
17
|
+
nset = [[j] for j in range(d)]
|
|
18
|
+
returnset = [[]] + nset
|
|
19
|
+
for i in range(ds - 1):
|
|
20
|
+
nextnset = []
|
|
21
|
+
for s in nset:
|
|
22
|
+
for j in range(d):
|
|
23
|
+
if s[-1] < j:
|
|
24
|
+
nextnset.append(s + [j])
|
|
25
|
+
returnset = returnset + nextnset
|
|
26
|
+
nset = nextnset
|
|
27
|
+
|
|
28
|
+
return [tuple(item) for item in returnset]
|
|
29
|
+
|
|
30
|
+
def bisection(l, r, fun, maxiter=1000):
|
|
31
|
+
lval = fun(l)
|
|
32
|
+
rval = fun(r)
|
|
33
|
+
|
|
34
|
+
if np.sign(lval) * np.sign(rval) == 1:
|
|
35
|
+
raise ValueError("bisection: root is not between l and r")
|
|
36
|
+
|
|
37
|
+
if lval > 0:
|
|
38
|
+
gun = fun
|
|
39
|
+
fun = lambda t: -gun(t)
|
|
40
|
+
|
|
41
|
+
m = 0.0
|
|
42
|
+
for _ in range(maxiter):
|
|
43
|
+
m = (l + r) / 2
|
|
44
|
+
mval = fun(m)
|
|
45
|
+
if abs(mval) < 1e-16:
|
|
46
|
+
break
|
|
47
|
+
if mval < 0:
|
|
48
|
+
l = m
|
|
49
|
+
lval = mval
|
|
50
|
+
else:
|
|
51
|
+
r = m
|
|
52
|
+
rval = mval
|
|
53
|
+
|
|
54
|
+
return m
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
from .analysis import *
|
|
58
|
+
from .approx import *
|
|
59
|
+
from .errors import *
|
|
60
|
+
from .fista import *
|
|
61
|
+
from .trafos import *
|
|
62
|
+
|
|
63
|
+
# Export functions and classes:
|
|
64
|
+
__all__ = [
|
|
65
|
+
# from Analysis.py:
|
|
66
|
+
"get_variances",
|
|
67
|
+
"get_GSI",
|
|
68
|
+
"get_AttributeRanking",
|
|
69
|
+
"get_ShapleyValues",
|
|
70
|
+
# from approx.py:
|
|
71
|
+
"approx",
|
|
72
|
+
# from Errors.py:
|
|
73
|
+
"get_l2_error",
|
|
74
|
+
"get_mse",
|
|
75
|
+
"get_mad",
|
|
76
|
+
"get_L2_error",
|
|
77
|
+
"get_acc",
|
|
78
|
+
# "get_auc",
|
|
79
|
+
# from trafo.py:
|
|
80
|
+
"transform_cube",
|
|
81
|
+
"transform_R",
|
|
82
|
+
# from fista.py:
|
|
83
|
+
"bisection",
|
|
84
|
+
"newton",
|
|
85
|
+
"λ2ξ",
|
|
86
|
+
"fista",
|
|
87
|
+
]
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
from pyANOVAapprox import *
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def get_variance(a, lam, Dict): # helpfunction for get_variances
|
|
5
|
+
|
|
6
|
+
if a.basis.startswith("chui"):
|
|
7
|
+
variances = a.fc[lam].norms(Dict=False, m=int(a.basis[-1]))
|
|
8
|
+
else:
|
|
9
|
+
variances = a.fc[lam].norms()
|
|
10
|
+
|
|
11
|
+
variances = variances[1:]
|
|
12
|
+
if Dict:
|
|
13
|
+
if a.basis.startswith("chui"):
|
|
14
|
+
variances = a.fc[lam].norms(Dict=True, m=int(a.basis[-1]))
|
|
15
|
+
else:
|
|
16
|
+
variances = a.fc[lam].norms(Dict=True)
|
|
17
|
+
|
|
18
|
+
return {u: variances[u] for u in list(variances)}
|
|
19
|
+
else:
|
|
20
|
+
return variances
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def get_variances(a, lam=None, Dict=False):
|
|
24
|
+
"""
|
|
25
|
+
This function returns the variances of the approximated ANOVA terms for all ``\lambda``, if lam == None. Otherwise for the provided lam. Depending on Dict, it returns the approximated ANOVA terms as a vector or as a dict.
|
|
26
|
+
"""
|
|
27
|
+
if isinstance(lam, float):
|
|
28
|
+
return get_variance(
|
|
29
|
+
a=a, lam=lam, Dict=Dict
|
|
30
|
+
) # get_variances(a::approx, λ::Float64; dict::Bool=false,)::Union{Vector{Float64},Dict{Vector{Int},Float64}}
|
|
31
|
+
|
|
32
|
+
elif (
|
|
33
|
+
lam == None
|
|
34
|
+
): # get_variances( a::approx; dict::Bool = false )::Dict{Float64,Union{Vector{Float64},Dict{Vector{Int},Float64}}}
|
|
35
|
+
return {l: get_variance(a=a, lam=l, Dict=Dict) for l in list(a.fc)}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _GSI(a, lam, Dict): # helpfunction for get_GSI
|
|
39
|
+
|
|
40
|
+
if a.basis.startswith("chui"):
|
|
41
|
+
variances = np.square(a.fc[lam].norms(Dict=False, m=int(a.basis[-1])))
|
|
42
|
+
else:
|
|
43
|
+
variances = np.square(a.fc[lam].norms())
|
|
44
|
+
|
|
45
|
+
variances = variances[1:]
|
|
46
|
+
variance_f = sum(variances)
|
|
47
|
+
|
|
48
|
+
if Dict:
|
|
49
|
+
if a.basis.startswith("chui"):
|
|
50
|
+
variances = np.square(a.fc[lam].norms(Dict=True, m=int(a.basis[-1])))
|
|
51
|
+
else:
|
|
52
|
+
variances = a.fc[lam].norms(Dict=True)
|
|
53
|
+
return {u: (variances[u] ** 2) / variance_f for u in list(variances)}
|
|
54
|
+
|
|
55
|
+
else:
|
|
56
|
+
return variances / variance_f
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def get_GSI(a, lam=None, Dict=False):
|
|
60
|
+
"""
|
|
61
|
+
This function returns the global sensitivity indices of the approximation for all ``\lambda``, if lam == None. Otherwise for the provided lam. Depending on Dict, it returns the approximated ANOVA terms as a vector or as a dict.
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
if (
|
|
65
|
+
lam is not None
|
|
66
|
+
): # get_GSI(a::approx, λ::Float64; dict::Bool = false,)::Union{Vector{Float64},Dict{Vector{Int},Float64}}
|
|
67
|
+
return _GSI(a=a, lam=lam, Dict=Dict)
|
|
68
|
+
else: # get_GSI( a::approx; dict::Bool = false )::Dict{Float64,Union{Vector{Float64},Dict{Vector{Int},Float64}}}
|
|
69
|
+
return {l: _GSI(a, l, Dict) for l in list(a.fc)}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def lam_AttributeRanking(a, lam): # helpfunction foor get_AttributeRanking
|
|
73
|
+
|
|
74
|
+
d = a.X.shape[1]
|
|
75
|
+
gsis = get_GSI(a, lam, Dict=True)
|
|
76
|
+
U = list(gsis)
|
|
77
|
+
lengths = [len(u) for u in U]
|
|
78
|
+
ds = max(lengths)
|
|
79
|
+
|
|
80
|
+
factors = np.zeros((d, ds), dtype=int)
|
|
81
|
+
|
|
82
|
+
for i in range(d):
|
|
83
|
+
for j in range(ds):
|
|
84
|
+
for v in U:
|
|
85
|
+
if (i in v) and (len(v) == j + 1):
|
|
86
|
+
factors[i, j] += 1
|
|
87
|
+
|
|
88
|
+
r = np.zeros(d, dtype=float)
|
|
89
|
+
nf = 0.0
|
|
90
|
+
|
|
91
|
+
for u in U:
|
|
92
|
+
weights = 0.0
|
|
93
|
+
for s in u:
|
|
94
|
+
contribution = gsis[u] * (1.0 / factors[s, len(u) - 1])
|
|
95
|
+
r[s] += contribution
|
|
96
|
+
weights += 1.0 / factors[s, len(u) - 1]
|
|
97
|
+
nf += weights * gsis[u]
|
|
98
|
+
|
|
99
|
+
return r / nf
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def get_AttributeRanking(a, lam=None):
|
|
103
|
+
"""
|
|
104
|
+
This function returns the attribute ranking of the approximation for all reg. parameters ``\lambda``, if lam == None, as a dictionary of vectors of length `a.d`. Otherwise for the provided lam as a vector of length `a.d`.
|
|
105
|
+
"""
|
|
106
|
+
if (
|
|
107
|
+
lam == None
|
|
108
|
+
): # get_AttributeRanking( a::approx, λ::Float64 )::Dict{Float64,Vector{Float64}}
|
|
109
|
+
return {l: get_AttributeRanking(a, l) for l in list(a.fc)}
|
|
110
|
+
else: # get_AttributeRanking( a::approx, λ::Float64 )::Vector{Float64}
|
|
111
|
+
return lam_AttributeRanking(a=a, lam=lam)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def lam_ActiveSet(a, eps, lam): # helpfunction for get_ActiveSet
|
|
115
|
+
|
|
116
|
+
U = a.U[1:]
|
|
117
|
+
lengths = [len(u) for u in U]
|
|
118
|
+
ds = max(lengths)
|
|
119
|
+
|
|
120
|
+
if len(eps) != ds:
|
|
121
|
+
raise ValueError("Entries in vector eps have to be ds.")
|
|
122
|
+
|
|
123
|
+
gsi = get_GSI(a, lam)
|
|
124
|
+
|
|
125
|
+
n = 0
|
|
126
|
+
|
|
127
|
+
for i in range(len(gsi)):
|
|
128
|
+
if gsi[i] > eps[len(U[i]) - 1]:
|
|
129
|
+
n += 1
|
|
130
|
+
|
|
131
|
+
U_active = [None] * (n + 1)
|
|
132
|
+
U_active[0] = []
|
|
133
|
+
|
|
134
|
+
idx = 1
|
|
135
|
+
for i in range(len(gsi)):
|
|
136
|
+
if gsi[i] > eps[len(U[i]) - 1]:
|
|
137
|
+
U_active[idx] = U[i]
|
|
138
|
+
idx += 1
|
|
139
|
+
|
|
140
|
+
return U_active
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def get_ActiveSet(a, eps, lam=None):
|
|
144
|
+
|
|
145
|
+
if (
|
|
146
|
+
lam == None
|
|
147
|
+
): # get_ActiveSet(a::approx, eps::Vector{Float64})::Dict{Float64,Vector{Vector{Int}}}
|
|
148
|
+
return {l: lam_ActiveSet(a=a, eps=eps, lam=l) for l in list(a.fc)}
|
|
149
|
+
else: # get_ActiveSet(a::approx, eps::Vector{Float64}, λ::Float64)::Vector{Vector{Int}}
|
|
150
|
+
return lam_ActiveSet(a=a, eps=eps, lam=lam)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def lam_ShapleyValues(a, lam): # helpfunction for get_ShapleyValues
|
|
154
|
+
|
|
155
|
+
d = a.X.shape[1]
|
|
156
|
+
vars_dict = get_variances(a, lam, Dict=True)
|
|
157
|
+
U = list(vars_dict)
|
|
158
|
+
r = np.zeros(d)
|
|
159
|
+
|
|
160
|
+
for i in range(d):
|
|
161
|
+
for v in U:
|
|
162
|
+
if i in v:
|
|
163
|
+
r[i] += (vars_dict[v] ** 2) / len(v)
|
|
164
|
+
|
|
165
|
+
return r
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def get_ShapleyValues(a, lam=None):
|
|
169
|
+
"""
|
|
170
|
+
This function returns the Shapley values of the approximation for all reg. parameters ``\lambda``, if lam == None, as a dictionary of vectors of length `a.d`. Otherwise for the provided lam as a vector of length `a.d`.
|
|
171
|
+
"""
|
|
172
|
+
if lam == None: # get_ShapleyValues(a::approx)::Dict{Float64,Vector{Float64}}
|
|
173
|
+
return {l: lam_ShapleyValues(a=a, lam=l) for l in list(a.fc)}
|
|
174
|
+
else: # get_ShapleyValues(a::approx, λ::Float64)::Vector{Float64}
|
|
175
|
+
return lam_ShapleyValues(a=a, lam=lam)
|