Sensitivity analysis for Bayesian networks using credal networks

Creative Commons License

aGrUM

interactive online version

There are several sensitivity analysis frameworks for Bayesian networks. A fairly efficient method is certainly to use credal networks to do this analysis.

Creating a Bayesian network

In [1]:
import pyagrum as gum
import pyagrum.lib.notebook as gnb
In [2]:
bn = gum.fastBN("A->B->C<-D->E->F<-B")
gnb.flow.row(bn, gnb.getInference(bn))
G C C A A B B A->B F F E E E->F B->C B->F D D D->C D->E
structs Inference in   2.24ms A 2025-03-24T09:05:49.091573 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ B 2025-03-24T09:05:49.109260 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ A->B C 2025-03-24T09:05:49.137225 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ B->C F 2025-03-24T09:05:49.231053 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ B->F D 2025-03-24T09:05:49.161230 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ D->C E 2025-03-24T09:05:49.186634 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ D->E E->F

Building a credal network from a BN

It is easy to build a credal network from a Bayesian network by indicating the ‘noise’ on each parameter.

In [3]:
cr = gum.CredalNet(bn, bn)
gnb.show(cr)
../_images/notebooks_14-Examples_SensitivityAnalysisUsingCredalNetworks_6_0.svg
In [4]:
cr.bnToCredal(1e-10, False, False)
In [5]:
cr.computeBinaryCPTMinMax()
In [6]:
print(cr)

A:Range([0,1])
<> : [[0.388748 , 0.611252] , [0.388226 , 0.611774]]

B:Range([0,1])
<A:0> : [[0.313659 , 0.686341] , [0.311745 , 0.688255]]
<A:1> : [[0.420476 , 0.579524] , [0.420166 , 0.579834]]

C:Range([0,1])
<B:0|D:0> : [[0.191514 , 0.808486] , [0.163758 , 0.836242]]
<B:1|D:0> : [[0.82499 , 0.175009]]
<B:0|D:1> : [[0.397873 , 0.602127] , [0.397424 , 0.602576]]
<B:1|D:1> : [[0.484422 , 0.515578] , [0.48431 , 0.51569]]

D:Range([0,1])
<> : [[0.800244 , 0.199756] , [0.800242 , 0.199758]]

E:Range([0,1])
<D:0> : [[0.616013 , 0.383987] , [0.615997 , 0.384003]]
<D:1> : [[0.181977 , 0.818023] , [0.124217 , 0.875783]]

F:Range([0,1])
<E:0|B:0> : [[0.723521 , 0.276479] , [0.723517 , 0.276483]]
<E:1|B:0> : [[0.794577 , 0.205423] , [0.794576 , 0.205424]]
<E:0|B:1> : [[0.701076 , 0.298924] , [0.701071 , 0.298929]]
<E:1|B:1> : [[0.572622 , 0.427378] , [0.572593 , 0.427407]]


Testing difference hypothesis about the global precision on the parameters

We can therefore easily conduct a sensitivity analysis based on an assumption of error on all the parameters of the network.

In [7]:
def showNoisy(bn, beta):
  cr = gum.CredalNet(bn, bn)
  cr.bnToCredal(beta, False, False)
  cr.computeBinaryCPTMinMax()
  ielbp = gum.CNLoopyPropagation(cr)
  return gnb.getInference(cr, engine=ielbp)
In [8]:
for eps in [1, 1e-1, 1e-2, 1e-3, 1e-10]:
  gnb.flow.add(showNoisy(bn, eps), caption=f"noise={eps}")
gnb.flow.display()
structs Inference in   0.28ms A 2025-03-24T09:05:49.630679 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ B 2025-03-24T09:05:49.647976 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ A->B C 2025-03-24T09:05:49.663929 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ B->C F 2025-03-24T09:05:49.709235 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ B->F D 2025-03-24T09:05:49.679218 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ D->C E 2025-03-24T09:05:49.694249 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ D->E E->F
noise=1
structs Inference in   0.18ms A 2025-03-24T09:05:49.861116 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ B 2025-03-24T09:05:49.877784 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ A->B C 2025-03-24T09:05:49.894666 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ B->C F 2025-03-24T09:05:49.945028 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ B->F D 2025-03-24T09:05:49.912785 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ D->C E 2025-03-24T09:05:49.928778 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ D->E E->F
noise=0.1
structs Inference in   0.21ms A 2025-03-24T09:05:50.102933 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ B 2025-03-24T09:05:50.119738 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ A->B C 2025-03-24T09:05:50.137239 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ B->C F 2025-03-24T09:05:50.184503 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ B->F D 2025-03-24T09:05:50.153445 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ D->C E 2025-03-24T09:05:50.169283 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ D->E E->F
noise=0.01
structs Inference in   0.20ms A 2025-03-24T09:05:50.325221 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ B 2025-03-24T09:05:50.340438 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ A->B C 2025-03-24T09:05:50.355279 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ B->C F 2025-03-24T09:05:50.401553 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ B->F D 2025-03-24T09:05:50.371953 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ D->C E 2025-03-24T09:05:50.386785 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ D->E E->F
noise=0.001
structs Inference in   0.19ms A 2025-03-24T09:05:50.579397 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ B 2025-03-24T09:05:50.594028 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ A->B C 2025-03-24T09:05:50.608317 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ B->C F 2025-03-24T09:05:50.651253 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ B->F D 2025-03-24T09:05:50.622669 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ D->C E 2025-03-24T09:05:50.636767 image/svg+xml Matplotlib v3.10.1, https://matplotlib.org/ D->E E->F
noise=1e-10
In [ ]: