pyAgrum-nightly 2.2.1.9.dev202510271761405498__cp310-abi3-win_amd64.whl → 2.3.0.9.dev202510291761586496__cp310-abi3-win_amd64.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.
Potentially problematic release.
This version of pyAgrum-nightly might be problematic. Click here for more details.
- pyagrum/_pyagrum.pyd +0 -0
- pyagrum/common.py +1 -1
- pyagrum/config.py +1 -0
- pyagrum/explain/_ComputationCausal.py +75 -0
- pyagrum/explain/_ComputationConditional.py +48 -0
- pyagrum/explain/_ComputationMarginal.py +48 -0
- pyagrum/explain/_CustomShapleyCache.py +110 -0
- pyagrum/explain/_Explainer.py +176 -0
- pyagrum/explain/_Explanation.py +70 -0
- pyagrum/explain/_FIFOCache.py +54 -0
- pyagrum/explain/_ShallCausalValues.py +204 -0
- pyagrum/explain/_ShallConditionalValues.py +155 -0
- pyagrum/explain/_ShallMarginalValues.py +155 -0
- pyagrum/explain/_ShallValues.py +296 -0
- pyagrum/explain/_ShapCausalValues.py +208 -0
- pyagrum/explain/_ShapConditionalValues.py +126 -0
- pyagrum/explain/_ShapMarginalValues.py +191 -0
- pyagrum/explain/_ShapleyValues.py +298 -0
- pyagrum/explain/__init__.py +81 -0
- pyagrum/explain/_explGeneralizedMarkovBlanket.py +152 -0
- pyagrum/explain/_explIndependenceListForPairs.py +146 -0
- pyagrum/explain/_explInformationGraph.py +264 -0
- pyagrum/explain/notebook/__init__.py +54 -0
- pyagrum/explain/notebook/_bar.py +142 -0
- pyagrum/explain/notebook/_beeswarm.py +174 -0
- pyagrum/explain/notebook/_showShapValues.py +97 -0
- pyagrum/explain/notebook/_waterfall.py +220 -0
- pyagrum/explain/shapley.py +225 -0
- pyagrum/lib/explain.py +11 -490
- pyagrum/pyagrum.py +17 -10
- {pyagrum_nightly-2.2.1.9.dev202510271761405498.dist-info → pyagrum_nightly-2.3.0.9.dev202510291761586496.dist-info}/METADATA +1 -1
- {pyagrum_nightly-2.2.1.9.dev202510271761405498.dist-info → pyagrum_nightly-2.3.0.9.dev202510291761586496.dist-info}/RECORD +36 -12
- pyagrum/lib/shapley.py +0 -661
- {pyagrum_nightly-2.2.1.9.dev202510271761405498.dist-info → pyagrum_nightly-2.3.0.9.dev202510291761586496.dist-info}/LICENSE.md +0 -0
- {pyagrum_nightly-2.2.1.9.dev202510271761405498.dist-info → pyagrum_nightly-2.3.0.9.dev202510291761586496.dist-info}/LICENSES/LGPL-3.0-or-later.txt +0 -0
- {pyagrum_nightly-2.2.1.9.dev202510271761405498.dist-info → pyagrum_nightly-2.3.0.9.dev202510291761586496.dist-info}/LICENSES/MIT.txt +0 -0
- {pyagrum_nightly-2.2.1.9.dev202510271761405498.dist-info → pyagrum_nightly-2.3.0.9.dev202510291761586496.dist-info}/WHEEL +0 -0
pyagrum/lib/explain.py
CHANGED
|
@@ -42,495 +42,16 @@
|
|
|
42
42
|
tools for BN qualitative analysis and explainability
|
|
43
43
|
"""
|
|
44
44
|
|
|
45
|
-
import itertools
|
|
46
45
|
import warnings
|
|
47
|
-
from typing import Union
|
|
48
46
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
from pyagrum.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
# ruff: noqa: F401
|
|
61
|
-
from pyagrum.lib.shapley import ShapValues
|
|
62
|
-
|
|
63
|
-
_cdict = {
|
|
64
|
-
"red": ((0.0, 0.1, 0.3), (1.0, 0.6, 1.0)),
|
|
65
|
-
"green": ((0.0, 0.0, 0.0), (1.0, 0.6, 0.8)),
|
|
66
|
-
"blue": ((0.0, 0.0, 0.0), (1.0, 1, 0.8)),
|
|
67
|
-
}
|
|
68
|
-
_INFOcmap = mpl.colors.LinearSegmentedColormap("my_colormap", _cdict, 256)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
def _independenceListForPairs(bn, target=None):
|
|
72
|
-
"""
|
|
73
|
-
returns a list of triples `(i,j,k)` for each non arc `(i,j)` such that `i` is independent of `j` given `k`.
|
|
74
|
-
|
|
75
|
-
Parameters
|
|
76
|
-
----------
|
|
77
|
-
bn: gum.BayesNet
|
|
78
|
-
the Bayesian Network
|
|
79
|
-
|
|
80
|
-
target: (optional) str or int
|
|
81
|
-
the name or id of the target variable. If a target is given, only the independence given a subset of the markov blanket of the target are tested.
|
|
82
|
-
|
|
83
|
-
Returns
|
|
84
|
-
-------
|
|
85
|
-
List[(str,str,List[str])]
|
|
86
|
-
A list of independence found in the structure of BN.
|
|
87
|
-
"""
|
|
88
|
-
|
|
89
|
-
def powerset(iterable):
|
|
90
|
-
xs = list(iterable)
|
|
91
|
-
# note we return an iterator rather than a list
|
|
92
|
-
return itertools.chain.from_iterable(itertools.combinations(xs, n) for n in range(len(xs) + 1))
|
|
93
|
-
|
|
94
|
-
# testing every d-separation
|
|
95
|
-
l = []
|
|
96
|
-
nams = sorted(bn.names())
|
|
97
|
-
if target is None:
|
|
98
|
-
firstnams = nams.copy()
|
|
99
|
-
indepnodes = bn.names()
|
|
100
|
-
else:
|
|
101
|
-
indepnodes = {bn.variable(i).name() for i in gum.MarkovBlanket(bn, target).nodes()}
|
|
102
|
-
if isinstance(target, str):
|
|
103
|
-
firstnams = [target]
|
|
104
|
-
else:
|
|
105
|
-
firstnams = [bn.variable(target).name()]
|
|
106
|
-
|
|
107
|
-
for i in firstnams:
|
|
108
|
-
nams.remove(i)
|
|
109
|
-
for j in nams:
|
|
110
|
-
if not (bn.existsArc(i, j) or bn.existsArc(j, i)):
|
|
111
|
-
for k in powerset(sorted(indepnodes - {i, j})):
|
|
112
|
-
if bn.isIndependent(i, j, k):
|
|
113
|
-
l.append((i, j, tuple(k)))
|
|
114
|
-
break
|
|
115
|
-
return l
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
def independenceListForPairs(bn, filename, target=None, plot=True, alphabetic=False):
|
|
119
|
-
"""
|
|
120
|
-
get the p-values of the chi2 test of a (as simple as possible) independence proposition for every non arc.
|
|
121
|
-
|
|
122
|
-
Parameters
|
|
123
|
-
----------
|
|
124
|
-
bn : gum.BayesNet
|
|
125
|
-
the Bayesian network
|
|
126
|
-
|
|
127
|
-
filename : str
|
|
128
|
-
the name of the csv database
|
|
129
|
-
|
|
130
|
-
alphabetic : bool
|
|
131
|
-
if True, the list is alphabetically sorted else it is sorted by the p-value
|
|
132
|
-
|
|
133
|
-
target: (optional) str or int
|
|
134
|
-
the name or id of the target variable
|
|
135
|
-
|
|
136
|
-
plot : bool
|
|
137
|
-
if True, plot the result
|
|
138
|
-
|
|
139
|
-
Returns
|
|
140
|
-
-------
|
|
141
|
-
the list
|
|
142
|
-
"""
|
|
143
|
-
|
|
144
|
-
learner = gum.BNLearner(filename, bn)
|
|
145
|
-
vals = {}
|
|
146
|
-
for indep in _independenceListForPairs(bn, target):
|
|
147
|
-
vals[indep] = learner.chi2(*indep)[1]
|
|
148
|
-
|
|
149
|
-
if plot:
|
|
150
|
-
plotvals = dict()
|
|
151
|
-
for indep in vals:
|
|
152
|
-
key = "$" + indep[0] + " \\perp " + indep[1]
|
|
153
|
-
if len(indep[2]) > 0:
|
|
154
|
-
key += " \\mid " + ",".join(indep[2])
|
|
155
|
-
key += "$"
|
|
156
|
-
plotvals[key] = vals[indep]
|
|
157
|
-
|
|
158
|
-
if not alphabetic:
|
|
159
|
-
sortedkeys = sorted(plotvals, key=plotvals.__getitem__, reverse=False)
|
|
160
|
-
else:
|
|
161
|
-
sortedkeys = list(plotvals.keys())
|
|
162
|
-
|
|
163
|
-
fig = pylab.figure(figsize=(10, 1 + 0.25 * len(plotvals)))
|
|
164
|
-
ax = fig.add_subplot(1, 1, 1)
|
|
165
|
-
ax.plot([plotvals[k] for k in sortedkeys], sortedkeys, "o")
|
|
166
|
-
ax.grid(True)
|
|
167
|
-
ax.vlines(x=0.05, ymin=-0.5, ymax=len(vals) - 0.5, colors="purple")
|
|
168
|
-
ax.add_patch(mpl.patches.Rectangle((0, -0.5), 0.05, len(vals), color="yellow"))
|
|
169
|
-
|
|
170
|
-
return vals
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
def _normalizeVals(vals, hilightExtrema=False):
|
|
174
|
-
"""
|
|
175
|
-
normalisation if vals is not a proba (max>1)
|
|
176
|
-
"""
|
|
177
|
-
ma = float(max(vals.values()))
|
|
178
|
-
mi = float(min(vals.values()))
|
|
179
|
-
if ma == mi:
|
|
180
|
-
return None
|
|
181
|
-
|
|
182
|
-
if not hilightExtrema:
|
|
183
|
-
vmi = 0.01
|
|
184
|
-
vma = 0.99
|
|
185
|
-
else:
|
|
186
|
-
vmi = 0
|
|
187
|
-
vma = 1
|
|
188
|
-
|
|
189
|
-
res = {name: vmi + (val - mi) * (vma - vmi) / (ma - mi) for name, val in vals.items()}
|
|
190
|
-
return res
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
def getInformationGraph(bn, evs=None, size=None, cmap=_INFOcmap, withMinMax=False):
|
|
194
|
-
"""
|
|
195
|
-
Create a dot representation of the information graph for this BN
|
|
196
|
-
|
|
197
|
-
Parameters
|
|
198
|
-
----------
|
|
199
|
-
bn: gum.BayesNet
|
|
200
|
-
the BN
|
|
201
|
-
evs : Dict[str,str|int|List[float]]
|
|
202
|
-
map of evidence
|
|
203
|
-
size: str|int
|
|
204
|
-
size of the graph
|
|
205
|
-
cmap: matplotlib.colors.Colormap
|
|
206
|
-
color map
|
|
207
|
-
withMinMax: bool
|
|
208
|
-
min and max in the return values ?
|
|
209
|
-
|
|
210
|
-
Returns
|
|
211
|
-
-------
|
|
212
|
-
dot.Dot | Tuple[dot.Dot,float,float,float,float]
|
|
213
|
-
graph as a dot representation and if asked, min_information_value, max_information_value, min_mutual_information_value, max_mutual_information_value
|
|
214
|
-
"""
|
|
215
|
-
if size is None:
|
|
216
|
-
size = gum.config["notebook", "default_graph_size"]
|
|
217
|
-
|
|
218
|
-
if evs is None:
|
|
219
|
-
evs = {}
|
|
220
|
-
|
|
221
|
-
ie = gum.LazyPropagation(bn)
|
|
222
|
-
ie.setEvidence(evs)
|
|
223
|
-
ie.makeInference()
|
|
224
|
-
|
|
225
|
-
idEvs = ie.hardEvidenceNodes() | ie.softEvidenceNodes()
|
|
226
|
-
|
|
227
|
-
nodevals = dict()
|
|
228
|
-
for n in bn.nodes():
|
|
229
|
-
if n not in idEvs:
|
|
230
|
-
v = ie.H(n)
|
|
231
|
-
if v != v: # is NaN
|
|
232
|
-
warnings.warn(f"For {bn.variable(n).name()}, entropy is NaN.")
|
|
233
|
-
v = 0
|
|
234
|
-
nodevals[bn.variable(n).name()] = v
|
|
235
|
-
|
|
236
|
-
arcvals = dict()
|
|
237
|
-
for x, y in bn.arcs():
|
|
238
|
-
v = ie.jointMutualInformation({x, y})
|
|
239
|
-
if v != v: # is NaN
|
|
240
|
-
warnings.warn(f"For {bn.variable(x).name()}->{bn.variable(y).name()}, mutual information is Nan.")
|
|
241
|
-
v = 0
|
|
242
|
-
arcvals[(x, y)] = v
|
|
243
|
-
|
|
244
|
-
gr = BN2dot(
|
|
245
|
-
bn,
|
|
246
|
-
size,
|
|
247
|
-
nodeColor=_normalizeVals(nodevals, hilightExtrema=False),
|
|
248
|
-
arcWidth=arcvals,
|
|
249
|
-
cmapNode=cmap,
|
|
250
|
-
cmapArc=cmap,
|
|
251
|
-
showMsg=nodevals,
|
|
252
|
-
)
|
|
253
|
-
|
|
254
|
-
if withMinMax:
|
|
255
|
-
mi_node = min(nodevals.values())
|
|
256
|
-
ma_node = max(nodevals.values())
|
|
257
|
-
mi_arc = min(arcvals.values())
|
|
258
|
-
ma_arc = max(arcvals.values())
|
|
259
|
-
return gr, mi_node, ma_node, mi_arc, ma_arc
|
|
260
|
-
else:
|
|
261
|
-
return gr
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
def _reprInformation(bn, evs=None, size=None, cmap=_INFOcmap, asString=False):
|
|
265
|
-
"""
|
|
266
|
-
repr a bn annotated with results from inference : Information and mutual information
|
|
267
|
-
|
|
268
|
-
Parameters
|
|
269
|
-
----------
|
|
270
|
-
bn: pyagrum.BayesNet
|
|
271
|
-
the model
|
|
272
|
-
evs: Dict[str|int,str|int|List[float]]
|
|
273
|
-
the observations
|
|
274
|
-
size: int|str
|
|
275
|
-
size of the rendered graph
|
|
276
|
-
cmap: matplotlib.colours.Colormap
|
|
277
|
-
the cmap
|
|
278
|
-
asString: bool
|
|
279
|
-
returns the string or display the HTML
|
|
280
|
-
|
|
281
|
-
Returns
|
|
282
|
-
-------
|
|
283
|
-
str|None
|
|
284
|
-
return the HTML string or directly display it.
|
|
285
|
-
"""
|
|
286
|
-
import IPython.display
|
|
287
|
-
import IPython.core.pylabtools
|
|
288
|
-
from base64 import encodebytes
|
|
289
|
-
from matplotlib.backends.backend_agg import FigureCanvasAgg as fc
|
|
290
|
-
|
|
291
|
-
if size is None:
|
|
292
|
-
size = gum.config["notebook", "default_graph_size"]
|
|
293
|
-
|
|
294
|
-
if evs is None:
|
|
295
|
-
evs = {}
|
|
296
|
-
|
|
297
|
-
gr, mi, ma, _, _ = getInformationGraph(bn, evs, size, cmap, withMinMax=True)
|
|
298
|
-
gumcols.prepareDot(gr, size=size)
|
|
299
|
-
|
|
300
|
-
# dynamic member makes pylink unhappy
|
|
301
|
-
# pylint: disable=no-member
|
|
302
|
-
gsvg = IPython.display.SVG(gr.create_svg(encoding="utf-8"))
|
|
303
|
-
width = (
|
|
304
|
-
int(gsvg.data.split("width=")[1].split('"')[1].split("pt")[0]) / mpl.pyplot.rcParams["figure.dpi"]
|
|
305
|
-
) # pixel in inches
|
|
306
|
-
if width < 5:
|
|
307
|
-
width = 5
|
|
308
|
-
|
|
309
|
-
fig = mpl.figure.Figure(figsize=(width, 1))
|
|
310
|
-
fig.patch.set_alpha(0)
|
|
311
|
-
canvas = fc(fig)
|
|
312
|
-
ax1 = fig.add_axes([0.05, 0.80, 0.9, 0.15])
|
|
313
|
-
norm = mpl.colors.Normalize(vmin=mi, vmax=ma)
|
|
314
|
-
cb1 = mpl.colorbar.ColorbarBase(ax1, cmap=cmap, norm=norm, orientation="horizontal")
|
|
315
|
-
cb1.set_label("Entropy")
|
|
316
|
-
cb1.ax.text(mi, -2, f"{mi:.4f}", ha="left", va="top", color=gumcols.proba2bgcolor(0.01, cmap))
|
|
317
|
-
cb1.ax.text(ma, -2, f"{ma:.4f}", ha="right", va="top", color=gumcols.proba2bgcolor(0.99, cmap))
|
|
318
|
-
png = IPython.core.pylabtools.print_figure(canvas.figure, "png") # from IPython.core.pylabtools
|
|
319
|
-
png_legend = f"<img style='vertical-align:middle' src='data:image/png;base64,{encodebytes(png).decode('ascii')}'>"
|
|
320
|
-
|
|
321
|
-
sss = f"<div align='center'>{gsvg.data}<br/>{png_legend}</div>"
|
|
322
|
-
|
|
323
|
-
if asString:
|
|
324
|
-
return sss
|
|
325
|
-
|
|
326
|
-
return IPython.display.display(IPython.display.HTML(sss))
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
def getInformation(bn, evs=None, size=None, cmap=_INFOcmap) -> str:
|
|
330
|
-
"""
|
|
331
|
-
get a HTML string for a bn annotated with results from inference : entropy and mutual information
|
|
332
|
-
|
|
333
|
-
Parameters
|
|
334
|
-
----------
|
|
335
|
-
bn: pyagrum.BayesNet
|
|
336
|
-
the model
|
|
337
|
-
evs: Dict[str|int,str|int|List[float]]
|
|
338
|
-
the observations
|
|
339
|
-
size: int|str
|
|
340
|
-
size of the rendered graph
|
|
341
|
-
cmap: matplotlib.colours.Colormap
|
|
342
|
-
the cmap
|
|
343
|
-
|
|
344
|
-
Returns
|
|
345
|
-
-------
|
|
346
|
-
str
|
|
347
|
-
return the HTML string
|
|
348
|
-
"""
|
|
349
|
-
if size is None:
|
|
350
|
-
size = gum.config["notebook", "default_graph_size"]
|
|
351
|
-
|
|
352
|
-
if evs is None:
|
|
353
|
-
evs = {}
|
|
354
|
-
|
|
355
|
-
return _reprInformation(bn, evs, size, cmap, asString=True)
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
def showInformation(bn, evs=None, size=None, cmap=_INFOcmap):
|
|
359
|
-
"""
|
|
360
|
-
diplay a bn annotated with results from inference : entropy and mutual information
|
|
361
|
-
|
|
362
|
-
Parameters
|
|
363
|
-
----------
|
|
364
|
-
bn: pyagrum.BayesNet
|
|
365
|
-
the model
|
|
366
|
-
evs: Dict[str|int,str|int|List[float]]
|
|
367
|
-
the observations
|
|
368
|
-
size: int|str
|
|
369
|
-
size of the rendered graph
|
|
370
|
-
cmap: matplotlib.colours.Colormap
|
|
371
|
-
the cmap
|
|
372
|
-
"""
|
|
373
|
-
if evs is None:
|
|
374
|
-
evs = {}
|
|
375
|
-
|
|
376
|
-
if size is None:
|
|
377
|
-
size = gum.config["notebook", "default_graph_size"]
|
|
378
|
-
return _reprInformation(bn, evs, size, cmap, asString=False)
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
########################## MB(k) #####################################
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
def _buildMB(model, x: int, k: int = 1):
|
|
385
|
-
"""
|
|
386
|
-
Build the nodes and arcs of Markov Blanket (of order k) of node x
|
|
387
|
-
|
|
388
|
-
Parameters
|
|
389
|
-
----------
|
|
390
|
-
model: pyagrum.DirectedGraphicalModel
|
|
391
|
-
i.e. a class with methods parents, children, variable(i), idFromName(name)
|
|
392
|
-
x : int
|
|
393
|
-
the nodeId of the node for the Markov blanket
|
|
394
|
-
k: int
|
|
395
|
-
the order of the Markov blanket. If k=2, build the MarkovBlanket(MarkovBlanket())
|
|
396
|
-
|
|
397
|
-
Returns
|
|
398
|
-
-------
|
|
399
|
-
(nodes,arcs,depth) : the set of nodes, the set of arcs of the Markov Blanket and a dict[Str,int] that gives the MB-depth of each node in nodes.
|
|
400
|
-
"""
|
|
401
|
-
nodes = {x}
|
|
402
|
-
arcs = set()
|
|
403
|
-
depth = dict()
|
|
404
|
-
|
|
405
|
-
def _internal_build_markov_blanket(bn, x: int, k: int):
|
|
406
|
-
nodes.add(x)
|
|
407
|
-
depth[x] = k
|
|
408
|
-
if k == 0:
|
|
409
|
-
return
|
|
410
|
-
for y in bn.parents(x):
|
|
411
|
-
visit(y, k - 1)
|
|
412
|
-
arcs.add((y, x))
|
|
413
|
-
for y in bn.children(x):
|
|
414
|
-
visit(y, k - 1)
|
|
415
|
-
arcs.add((x, y))
|
|
416
|
-
for z in bn.parents(y):
|
|
417
|
-
visit(z, k - 1)
|
|
418
|
-
arcs.add((z, y))
|
|
419
|
-
|
|
420
|
-
def visit(x, k):
|
|
421
|
-
if x in nodes and depth[x] >= k:
|
|
422
|
-
return
|
|
423
|
-
_internal_build_markov_blanket(model, x, k)
|
|
424
|
-
|
|
425
|
-
_internal_build_markov_blanket(model, x, k)
|
|
426
|
-
return nodes, arcs, depth
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
def generalizedMarkovBlanket(bn, var: Union[int, str], k: int = 1, cmapNode=None):
|
|
430
|
-
"""
|
|
431
|
-
Build a pydot.Dot representation of the nested Markov Blankets (of order k) of node x
|
|
432
|
-
|
|
433
|
-
Warnings
|
|
434
|
-
--------
|
|
435
|
-
It is assumed that k<=8. If not, every thing is fine except that the colorscale will change in order to accept more colors.
|
|
436
|
-
|
|
437
|
-
Parameters
|
|
438
|
-
----------
|
|
439
|
-
bn: pyagrum.DirectedGraphicalModel
|
|
440
|
-
i.e. a class with methods parents, children, variable(i), idFromName(name)
|
|
441
|
-
var : str|int
|
|
442
|
-
the name or nodeId of the node for the Markov blanket
|
|
443
|
-
k: int
|
|
444
|
-
the order of the Markov blanket. If k=1, build the MarkovBlanket(MarkovBlanket())
|
|
445
|
-
cmap: maplotlib.ColorMap
|
|
446
|
-
the colormap used (if not, inferno is used)
|
|
447
|
-
|
|
448
|
-
Returns
|
|
449
|
-
-------
|
|
450
|
-
pydotplus.Dot object
|
|
451
|
-
"""
|
|
452
|
-
if cmapNode is None:
|
|
453
|
-
cmapNode = plt.get_cmap("inferno") # gum.config["notebook", "default_arc_cmap"])
|
|
454
|
-
|
|
455
|
-
maxcols = max(
|
|
456
|
-
8, k
|
|
457
|
-
) # It is assumed that k<=8. If not, every thing is fine except that the colorscale will change in order to accept more colors.
|
|
458
|
-
|
|
459
|
-
mb = dot.Dot(f"MB({var},{k}", graph_type="digraph", bgcolor="transparent")
|
|
460
|
-
|
|
461
|
-
if isinstance(var, str):
|
|
462
|
-
nx = bn.idFromName(var)
|
|
463
|
-
else:
|
|
464
|
-
nx = var
|
|
465
|
-
nodes, arcs, visited = _buildMB(bn, nx, k)
|
|
466
|
-
names = dict()
|
|
467
|
-
|
|
468
|
-
for n in nodes:
|
|
469
|
-
protected_name = f'"{bn.variable(n).name()}"'
|
|
470
|
-
pnode = dot.Node(protected_name, style="filled")
|
|
471
|
-
if n == var:
|
|
472
|
-
bgcol = "#99FF99"
|
|
473
|
-
fgcol = "black"
|
|
474
|
-
else:
|
|
475
|
-
bgcol = gumcols.proba2bgcolor(1 - (k - visited[n]) / maxcols, cmapNode)
|
|
476
|
-
fgcol = gumcols.proba2fgcolor(1 - (k - visited[n]) / maxcols, cmapNode)
|
|
477
|
-
pnode.set_fillcolor(bgcol)
|
|
478
|
-
pnode.set_fontcolor(fgcol)
|
|
479
|
-
mb.add_node(pnode)
|
|
480
|
-
names[n] = protected_name
|
|
481
|
-
for n in nodes:
|
|
482
|
-
for u in bn.parents(n).intersection(nodes):
|
|
483
|
-
edge = dot.Edge(names[u], names[n])
|
|
484
|
-
if (u, n) in arcs:
|
|
485
|
-
edge.set_color("black")
|
|
486
|
-
else:
|
|
487
|
-
edge.set_color("#DDDDDD")
|
|
488
|
-
mb.add_edge(edge)
|
|
489
|
-
|
|
490
|
-
return mb
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
def generalizedMarkovBlanketNames(bn, var: Union[int, str], depth: int = 1):
|
|
494
|
-
"""
|
|
495
|
-
List the name of all nodes in the nested Markov Blankets (of order k) in association with their depth
|
|
496
|
-
|
|
497
|
-
Parameters
|
|
498
|
-
----------
|
|
499
|
-
bn: pyagrum.DirectedGraphicalModel
|
|
500
|
-
i.e. a class with methods parents, children, variable(i), idFromName(name)
|
|
501
|
-
var : str|int
|
|
502
|
-
the name or nodeId of the node for the Markov blanket
|
|
503
|
-
depth: int
|
|
504
|
-
the order of the Markov blanket. If k=1, build the MarkovBlanket(MarkovBlanket()
|
|
505
|
-
|
|
506
|
-
Returns
|
|
507
|
-
-------
|
|
508
|
-
Dict[str,int]
|
|
509
|
-
the list of names and their depth.
|
|
510
|
-
"""
|
|
511
|
-
if isinstance(var, str):
|
|
512
|
-
nx = bn.idFromName(var)
|
|
513
|
-
else:
|
|
514
|
-
nx = var
|
|
515
|
-
nodes, _, visited = _buildMB(bn, nx, depth)
|
|
516
|
-
return {bn.variable(node).name(): depth - visited[node] for node in nodes}
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
def showShapValues(bn, shaps, cmap="plasma") -> None:
|
|
520
|
-
"""
|
|
521
|
-
Show the Shap values in the DAG of the BN
|
|
522
|
-
|
|
523
|
-
Parameters
|
|
524
|
-
----------
|
|
525
|
-
bn : pyagrum.BayesNet
|
|
526
|
-
The Bayesian network
|
|
527
|
-
shaps: dict[str,float]
|
|
528
|
-
The (Shap) values to each variable
|
|
529
|
-
cmap: Matplotlib.ColorMap
|
|
530
|
-
The colormap used for coloring the nodes
|
|
531
|
-
"""
|
|
532
|
-
import pyagrum.lib.shapley as shapley
|
|
533
|
-
import pyagrum.lib.notebook as gnb
|
|
534
|
-
|
|
535
|
-
g = shapley.getShapValues(bn, shaps, cmap)
|
|
536
|
-
gnb.showGraph(g)
|
|
47
|
+
warnings.warn(
|
|
48
|
+
"The module 'pyagrum.lib.explain' has been deprecated since version 2.2.2. "
|
|
49
|
+
"Please use the 'pyagrum.explain' module instead.",
|
|
50
|
+
DeprecationWarning,
|
|
51
|
+
stacklevel=2,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
from pyagrum.explain.shapley import ShapValues # noqa: E402
|
|
55
|
+
from pyagrum.explain.notebook import showShapValues # noqa: E402
|
|
56
|
+
from pyagrum.explain import independenceListForPairs # noqa: E402
|
|
57
|
+
from pyagrum.explain import showInformation, getInformation, getInformationGraph # noqa: E402
|
pyagrum/pyagrum.py
CHANGED
|
@@ -4068,6 +4068,9 @@ class DAG(DiGraph):
|
|
|
4068
4068
|
def moralGraph(self) -> "pyagrum.UndiGraph":
|
|
4069
4069
|
return _pyagrum.DAG_moralGraph(self)
|
|
4070
4070
|
|
|
4071
|
+
def minimalCondSet(self, *args) -> List[int]:
|
|
4072
|
+
return _pyagrum.DAG_minimalCondSet(self, *args)
|
|
4073
|
+
|
|
4071
4074
|
def __repr__(self) -> str:
|
|
4072
4075
|
return _pyagrum.DAG___repr__(self)
|
|
4073
4076
|
|
|
@@ -6648,6 +6651,9 @@ class DAGmodel(GraphicalModel):
|
|
|
6648
6651
|
"""
|
|
6649
6652
|
return _pyagrum.DAGmodel_hasSameStructure(self, other)
|
|
6650
6653
|
|
|
6654
|
+
def minimalCondSet(self, *args) -> List[int]:
|
|
6655
|
+
return _pyagrum.DAGmodel_minimalCondSet(self, *args)
|
|
6656
|
+
|
|
6651
6657
|
# Register DAGmodel in _pyagrum:
|
|
6652
6658
|
_pyagrum.DAGmodel_swigregister(DAGmodel)
|
|
6653
6659
|
class UGmodel(GraphicalModel):
|
|
@@ -11792,19 +11798,20 @@ class BayesNet(IBayesNet):
|
|
|
11792
11798
|
- the structure 'a->b->c;b->d<-e;'.
|
|
11793
11799
|
- the type of the variables with different syntax:
|
|
11794
11800
|
|
|
11795
|
-
- by default, a variable is a pyagrum.RangeVariable using the default domain size ([2])
|
|
11796
|
-
- with 'a[10]', the variable is a pyagrum.RangeVariable using 10 as domain size (from 0 to 9)
|
|
11797
|
-
- with 'a[3,7]', the variable is a pyagrum.RangeVariable using a domainSize from 3 to 7
|
|
11798
|
-
- with 'a[1,3.14,5,6.2]', the variable is a pyagrum.DiscretizedVariable using the given ticks (at least 3 values)
|
|
11799
|
-
- with 'a
|
|
11800
|
-
- with 'a{
|
|
11801
|
-
- with 'a{-
|
|
11801
|
+
- by default, a variable is a binary `pyagrum.RangeVariable` using the default domain size ([2])
|
|
11802
|
+
- with 'a[10]', the variable is a `pyagrum.RangeVariable` using 10 as domain size (from 0 to 9)
|
|
11803
|
+
- with 'a[3,7]', the variable is a `pyagrum.RangeVariable` using a domainSize from 3 to 7
|
|
11804
|
+
- with 'a[1,3.14,5,6.2]', the variable is a `pyagrum.DiscretizedVariable` using the given ticks (at least 3 values)
|
|
11805
|
+
- with 'a[0.0:3.14:10]', the variable is a `pyagrum.DiscretizedVariable` of 10 intervals of same width from 0 to 3.14 (including both)
|
|
11806
|
+
- with 'a{top|middle|bottom}', the variable is a `pyagrum.LabelizedVariable` using the given labels.
|
|
11807
|
+
- with 'a{-1|5|0|3}', the variable is a `pyagrum.IntegerVariable` using the sorted given values.
|
|
11808
|
+
- with 'a{-0.5|5.01|0|3.1415}', the variable is a `pyagrum.NumericalDiscreteVariable` using the sorted given values.
|
|
11802
11809
|
|
|
11803
11810
|
Note
|
|
11804
11811
|
----
|
|
11805
11812
|
- If the dot-like string contains such a specification more than once for a variable, the first specification will be used.
|
|
11806
11813
|
- the CPTs are randomly generated.
|
|
11807
|
-
- see also pyagrum.fastBN.
|
|
11814
|
+
- see also the function pyagrum.fastBN.
|
|
11808
11815
|
|
|
11809
11816
|
Examples
|
|
11810
11817
|
--------
|
|
@@ -29542,7 +29549,7 @@ class ShaferShenoyLIMIDInference(object):
|
|
|
29542
29549
|
|
|
29543
29550
|
# Register ShaferShenoyLIMIDInference in _pyagrum:
|
|
29544
29551
|
_pyagrum.ShaferShenoyLIMIDInference_swigregister(ShaferShenoyLIMIDInference)
|
|
29545
|
-
__version__ = '2.
|
|
29552
|
+
__version__ = '2.3.0'
|
|
29546
29553
|
__license__ = __doc__
|
|
29547
29554
|
__project_url__ = 'https://agrum.org'
|
|
29548
29555
|
__project_name__ = 'pyAgrum'
|
|
@@ -31424,7 +31431,7 @@ def getPosterior(model, *, target, evs=None):
|
|
|
31424
31431
|
# creating a new Tensor from posterior(will disappear with ie)
|
|
31425
31432
|
return pyagrum.Tensor(inf.posterior(target))
|
|
31426
31433
|
|
|
31427
|
-
__version__ = '2.
|
|
31434
|
+
__version__ = '2.3.0'
|
|
31428
31435
|
__license__ = __doc__
|
|
31429
31436
|
__project_url__ = 'https://agrum.org'
|
|
31430
31437
|
__project_name__ = 'pyAgrum'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyAgrum-nightly
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.0.9.dev202510291761586496
|
|
4
4
|
Summary: Bayesian networks and other Probabilistic Graphical Models.
|
|
5
5
|
Home-page: https://agrum.gitlab.io/
|
|
6
6
|
Author: Pierre-Henri Wuillemin and Christophe Gonzales
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
pyagrum\common.py,sha256=
|
|
2
|
-
pyagrum\config.py,sha256=
|
|
1
|
+
pyagrum\common.py,sha256=fWLpPWw9DSxdAOjxw7yB_MRXAS-YL_EXR-1wAF7DKO8,3623
|
|
2
|
+
pyagrum\config.py,sha256=xim-XXSnMlo-X1d1YLfo8wbsgwGQH9XM8svvn_10FCw,11615
|
|
3
3
|
pyagrum\defaults.ini,sha256=p8tCMx_ia7ubdRkmgavnvG2E5ButIFltCb2YwHlPutM,4867
|
|
4
4
|
pyagrum\deprecated.py,sha256=RSuwt9wZHozh_zmSucyPDU3rCicvTI35kjsc46VSQi4,4265
|
|
5
|
-
pyagrum\pyagrum.py,sha256=
|
|
6
|
-
pyagrum\_pyagrum.pyd,sha256=
|
|
5
|
+
pyagrum\pyagrum.py,sha256=J_b22PTU4uFq7XZqCXyPesCtx-f2Xtf5fUwEx_Bg5MY,868562
|
|
6
|
+
pyagrum\_pyagrum.pyd,sha256=tkIqP46PZW4WSS5zhOu8hCHm8sbYDzqtCFzBzoXc9vw,8098816
|
|
7
7
|
pyagrum\__init__.py,sha256=3N9lwsUXWNuHmccgAfSsOZPPsv2S7kdh3NsnSetmeXk,7623
|
|
8
8
|
pyagrum\bnmixture\BNMInference.py,sha256=r1n7-JWk_uelIaFIwyylRWsepktayrqQVmpJBNM8GoI,9819
|
|
9
9
|
pyagrum\bnmixture\BNMixture.py,sha256=eCMdkga2oPai8v3kz2XU2hQubb4oAGb_DZ7pEAB2R5Y,15084
|
|
@@ -50,6 +50,31 @@ pyagrum\ctbn\notebook.py,sha256=Hv6fQhxYVdIE57mobLyG8R92LvYjcwmkcqHOJlF2uHE,9517
|
|
|
50
50
|
pyagrum\ctbn\SamplesStats.py,sha256=n1dKFoKzVPyAs7_vjgnKoP-YMdZSfPp5OuhsOz_Gvpc,21496
|
|
51
51
|
pyagrum\ctbn\StatsIndepTest.py,sha256=YU98U4QDjRdt9EiQ88k5TzXAbTVxD007ENaRAhyrcmM,11451
|
|
52
52
|
pyagrum\ctbn\__init__.py,sha256=GLLB2lLBztBN3QjxsttXk21PBpWRG9b1FKnjGJFwS_8,3880
|
|
53
|
+
pyagrum\explain\shapley.py,sha256=hdStTCea5o5eXpVkj8CE6on8abWuMkUVOiSbEhEPmvI,10073
|
|
54
|
+
pyagrum\explain\_ComputationCausal.py,sha256=ZxkQdpRoKpyzMmVMQ71CWpmrkqIuPkYWWYgKgGt8Kxo,4362
|
|
55
|
+
pyagrum\explain\_ComputationConditional.py,sha256=PeZp9l1c5cFk2UKyyQYYJPFx1WSMJ5RDL3XGM-TMGjw,3262
|
|
56
|
+
pyagrum\explain\_ComputationMarginal.py,sha256=GrdPN3lZ_S4GlXxsvevZ0toUuLxufIYb2B3UQm6aguw,3259
|
|
57
|
+
pyagrum\explain\_CustomShapleyCache.py,sha256=YObaI33mzP9iBMx1cknGXotPPBRQXMbqDOh8U5fgPb0,5766
|
|
58
|
+
pyagrum\explain\_Explainer.py,sha256=cqCulkV7ANgZHCT5dxo0ailTBZLHNwMbrlPpS7_a_D4,7597
|
|
59
|
+
pyagrum\explain\_Explanation.py,sha256=OXUYFbJdlvMSkMQspBltVVeht6iwDS-rhwr7HQdr7kU,3822
|
|
60
|
+
pyagrum\explain\_explGeneralizedMarkovBlanket.py,sha256=kY8nVqdHzjIECSTB8LePc1itxoFPCMnseMCjCNdiAj4,6402
|
|
61
|
+
pyagrum\explain\_explIndependenceListForPairs.py,sha256=gpbwyqrGQsU-Q-4CbIYbkSAcuB-bcCUFgO9I4fYg2C4,6073
|
|
62
|
+
pyagrum\explain\_explInformationGraph.py,sha256=akzarNqhRfXk3tGLzQ_doEVSNDvLdXvsp-Wp9XMiE3Y,9126
|
|
63
|
+
pyagrum\explain\_FIFOCache.py,sha256=K96JQGRDCP-LK3f1Vfzs7csbtKPoM6PNQXF3sQmA_yQ,3472
|
|
64
|
+
pyagrum\explain\_ShallCausalValues.py,sha256=4lxAeKJUuRaxh644EzcjfEHL5WhjdvUQHiAeSan6VJ4,9421
|
|
65
|
+
pyagrum\explain\_ShallConditionalValues.py,sha256=4bocn0SQ2jFxGv4E9sar7HD2ElJXBflzi3cOg_dU60U,8009
|
|
66
|
+
pyagrum\explain\_ShallMarginalValues.py,sha256=_1UaQDBzrqdV_5AoOuLM6xXU1UwMpgGF2vDnkCgcSEQ,7312
|
|
67
|
+
pyagrum\explain\_ShallValues.py,sha256=nhOVfcqCKW9zXmTjxztcfzrWCphI0UDYvRQZz63UuWc,14322
|
|
68
|
+
pyagrum\explain\_ShapCausalValues.py,sha256=yAiE23TxXJbkr0ThHUI7SMpswuZcmOBTusS-aULwt98,10633
|
|
69
|
+
pyagrum\explain\_ShapConditionalValues.py,sha256=mHwWnvX_2KcfaXSq0-f4Qq3-MdS2CGAUrYl1ErazA6g,7049
|
|
70
|
+
pyagrum\explain\_ShapleyValues.py,sha256=E4OjaA11zw4LFecYCRdZQcAVKpWwzL31906PYG9Ea_U,12932
|
|
71
|
+
pyagrum\explain\_ShapMarginalValues.py,sha256=M_xmNKOmb6E3I_uEbbeQck2UVHAsgsBtvQJD644AZsU,9718
|
|
72
|
+
pyagrum\explain\__init__.py,sha256=hHirwOok0t-nlYn7orJCs0p6y9xH8jQN7W-X2d_XomY,4300
|
|
73
|
+
pyagrum\explain\notebook\_bar.py,sha256=hd5cBW2kTzZ42Lt4rwbiXXkYOEnjtIrx3SDbJpIpw9U,7482
|
|
74
|
+
pyagrum\explain\notebook\_beeswarm.py,sha256=fMkAKOioGM89egVUasrT4qWxsWPo4-mjpsxD4KLccG0,8101
|
|
75
|
+
pyagrum\explain\notebook\_showShapValues.py,sha256=pce2LC9Hg1abEKJs0CZnqXFb6TjXF24JAxwzIzfo14M,4981
|
|
76
|
+
pyagrum\explain\notebook\_waterfall.py,sha256=-0uf1OcmuBAyVxiV-9IV6UPSf3B4vQAoij5hdxwVHWU,9144
|
|
77
|
+
pyagrum\explain\notebook\__init__.py,sha256=3L5HBhMFzcQoLd0yjASspnDWQZuk3xmBswJXwtzAl7M,3340
|
|
53
78
|
pyagrum\lib\bn2graph.py,sha256=-V07EIvETDht94qtP3PQJGcSesdZoGUGip9Ad913hBg,11029
|
|
54
79
|
pyagrum\lib\bn2roc.py,sha256=JiZLOvdHaCXvdbCiGDtBQiBNzEWCZhq3YNGCmcjB4D8,28199
|
|
55
80
|
pyagrum\lib\bn2scores.py,sha256=DT7g_64RZ6xa4W3CsTDVJCrXRhqkCJAz-wytQ3eSwAE,7546
|
|
@@ -58,7 +83,7 @@ pyagrum\lib\cn2graph.py,sha256=LnxTXEP6Xo5ltWkM4mgblXa6v9Tg7vTefMlHrRufDF8,11301
|
|
|
58
83
|
pyagrum\lib\discreteTypeProcessor.py,sha256=Zn7CAb7jrp4oHKk2NE1CsIJHo8OrULCOWJ44Yf7AXXY,48278
|
|
59
84
|
pyagrum\lib\discretizer.py,sha256=zMkVqQwT8WuinaQi4Nb6nHet77JMQ10cvDK_8ip-skE,3626
|
|
60
85
|
pyagrum\lib\dynamicBN.py,sha256=oAjy2VHn-TNarUG9OA_HVmnLVNg7WsNdVtuEXRJumlY,13037
|
|
61
|
-
pyagrum\lib\explain.py,sha256=
|
|
86
|
+
pyagrum\lib\explain.py,sha256=emtdA0hDFnRIaxrRLX1I6Ync3lcdkKNk8VuB34PP6pA,3618
|
|
62
87
|
pyagrum\lib\export.py,sha256=xuMdMZjXohWPweypfukPP32Ae9vbqvQ4cZkWHxWQUxA,4430
|
|
63
88
|
pyagrum\lib\id2graph.py,sha256=hicMhnLLMowOIRNRvSsu8I7c0XEMvtU_Yi33A6Jaiqk,10764
|
|
64
89
|
pyagrum\lib\image.py,sha256=eIje4OGDy_cpZeK-KB5Zoni2OvyqI5P85hOee44GLCU,14343
|
|
@@ -66,7 +91,6 @@ pyagrum\lib\ipython.py,sha256=QbRYT1siHGD2Ax5finbwp5wBoBiDl4dYSfyyKuP7QzY,10526
|
|
|
66
91
|
pyagrum\lib\mrf2graph.py,sha256=ChIZreKSMwhf4JbRMzB3YjjnjEq5CAc9FeK8_ebrjEU,17430
|
|
67
92
|
pyagrum\lib\notebook.py,sha256=Q390z3uXFmYZW11aFhJGyZdcC3Z60DaCxK5EA7O2dsA,54676
|
|
68
93
|
pyagrum\lib\proba_histogram.py,sha256=2mKmwlNCIxobygkmV0JlScoItS3sciE8pcXrLGDMreI,17279
|
|
69
|
-
pyagrum\lib\shapley.py,sha256=UDYnorUGJfje1kOdffRy6DnnfG1TuTJbfoxOP0hN0Yo,24001
|
|
70
94
|
pyagrum\lib\utils.py,sha256=CmPOAATibFNePxE5d9JzQ0xtn3ZO_0ZGboi3H4_qqv0,5888
|
|
71
95
|
pyagrum\lib\_colors.py,sha256=xC5cvJICgD6Q9B2WYnmVltZhiWa7aY0m7Z8uYJgV6sU,11520
|
|
72
96
|
pyagrum\lib\__init__.py,sha256=z3RZAhZeLCH-PSsHBZWx3j5xDK0LAAxVZ2nDn1nHlL8,3185
|
|
@@ -75,9 +99,9 @@ pyagrum\skbn\_learningMethods.py,sha256=-HwD-CkeAlPXZqv6sIW2fsyOuGpAh--S7U9CYRsX
|
|
|
75
99
|
pyagrum\skbn\_MBCalcul.py,sha256=WkpcqMDJly8ZQ-9Rv87lTKqPTHCs_aG3gdeVXrR3z90,8787
|
|
76
100
|
pyagrum\skbn\_utils.py,sha256=7WXq6KWuUprIq3Z8synATBXJsU8DqD4pkIyTgEXUAwU,12123
|
|
77
101
|
pyagrum\skbn\__init__.py,sha256=YTC15qB4RxE7H8LkOmT3OmIRSSH-2KMdPnd8Isn8KCw,3308
|
|
78
|
-
pyagrum_nightly-2.
|
|
79
|
-
pyagrum_nightly-2.
|
|
80
|
-
pyagrum_nightly-2.
|
|
81
|
-
pyagrum_nightly-2.
|
|
82
|
-
pyagrum_nightly-2.
|
|
83
|
-
pyagrum_nightly-2.
|
|
102
|
+
pyagrum_nightly-2.3.0.9.dev202510291761586496.dist-info\LICENSE.md,sha256=zvFCSsrNpfhTKpqJGbBV_y-fFppADiyAE21RiUYgm60,923
|
|
103
|
+
pyagrum_nightly-2.3.0.9.dev202510291761586496.dist-info\METADATA,sha256=pTf-f9EAFjcLDAjU75o4HI_wcoujDd8u_Ss4wCRuN-I,5503
|
|
104
|
+
pyagrum_nightly-2.3.0.9.dev202510291761586496.dist-info\WHEEL,sha256=mYVCLrnPV21BIOR4ZrW0iE0D0EcqcaBksAamM25wqOw,93
|
|
105
|
+
pyagrum_nightly-2.3.0.9.dev202510291761586496.dist-info\LICENSES\LGPL-3.0-or-later.txt,sha256=nUeUYpsPD58HjDfHv-sti_MT71zWdBgDij3e3a1JGyE,42402
|
|
106
|
+
pyagrum_nightly-2.3.0.9.dev202510291761586496.dist-info\LICENSES\MIT.txt,sha256=MjA6uIe4yQtub-SeLwMcoBsjtRkOI2RH2U4ZRGhNx2k,1096
|
|
107
|
+
pyagrum_nightly-2.3.0.9.dev202510291761586496.dist-info\RECORD,,
|