There are several sensitivity analysis frameworks for Bayesian networks. A fairly efficient method is certainly to use credal networks to do this analysis.
import pyagrum.lib.notebook as gnb
bn = gum.fastBN( "A->B->C<-D->E->F<-B" )
gnb.flow.row(bn, gnb.getInference(bn))
G
E
E
F
F
E->F
D
D
D->E
C
C
D->C
A
A
B
B
A->B
B->F
B->C
structs
Inference in 0.64ms
A
2026-08-18T12:00:01.761540
image/svg+xml
Matplotlib v3.11.1,
B
2026-08-18T12:00:01.832106
image/svg+xml
Matplotlib v3.11.1,
A->B
C
2026-08-18T12:00:01.869907
image/svg+xml
Matplotlib v3.11.1,
B->C
F
2026-08-18T12:00:01.946014
image/svg+xml
Matplotlib v3.11.1,
B->F
D
2026-08-18T12:00:01.891816
image/svg+xml
Matplotlib v3.11.1,
D->C
E
2026-08-18T12:00:01.920061
image/svg+xml
Matplotlib v3.11.1,
D->E
E->F
It is easy to build a credal network from a Bayesian network by indicating the ‘noise’ on each parameter.
cr = gum.CredalNet(bn, bn)
cr.bnToCredal( 1e-10 , False , False )
cr.computeBinaryCPTMinMax()
<> : [[0.55286 , 0.44714] , [0.552821 , 0.447179]]
<A:0> : [[0.403363 , 0.596637] , [0.402953 , 0.597047]]
<A:1> : [[0.55775 , 0.44225] , [0.557714 , 0.442286]]
<B:0|D:0> : [[0.189192 , 0.810808] , [0.102062 , 0.897938]]
<B:1|D:0> : [[0.481363 , 0.518637] , [0.0182525 , 0.981748]]
<B:0|D:1> : [[0.526098 , 0.473902] , [0.526039 , 0.473961]]
<B:1|D:1> : [[0.37199 , 0.62801] , [0.371297 , 0.628703]]
<> : [[0.185717 , 0.814283] , [0.149711 , 0.850289]]
<D:0> : [[0.699161 , 0.300839] , [0.699156 , 0.300844]]
<D:1> : [[0.710072 , 0.289928] , [0.00449306 , 0.995507]]
<E:0|B:0> : [[0.659403 , 0.340597] , [0.659394 , 0.340606]]
<E:1|B:0> : [[0.490903 , 0.509097] , [0.490801 , 0.509199]]
<E:0|B:1> : [[0.237246 , 0.762754] , [0.228863 , 0.771137]]
<E:1|B:1> : [[0.36149 , 0.63851] , [0.360662 , 0.639338]]
We can therefore easily conduct a sensitivity analysis based on an assumption of error on all the parameters of the network.
cr = gum.CredalNet(bn, bn)
cr.bnToCredal(beta, False , False )
cr.computeBinaryCPTMinMax()
ielbp = gum.CNLoopyPropagation(cr)
return gnb.getInference(cr, engine = ielbp)
for eps in [ 1 , 1e-1 , 1e-2 , 1e-3 , 1e-10 ]:
gnb.flow.add(showNoisy(bn, eps), caption = f "noise= { eps } " )
G
E
E
F
F
E->F
D
D
D->E
C
C
D->C
A
A
B
B
A->B
B->F
B->C
structs
Inference in 0.64ms
A
2026-08-18T12:00:01.761540
image/svg+xml
Matplotlib v3.11.1,
B
2026-08-18T12:00:01.832106
image/svg+xml
Matplotlib v3.11.1,
A->B
C
2026-08-18T12:00:01.869907
image/svg+xml
Matplotlib v3.11.1,
B->C
F
2026-08-18T12:00:01.946014
image/svg+xml
Matplotlib v3.11.1,
B->F
D
2026-08-18T12:00:01.891816
image/svg+xml
Matplotlib v3.11.1,
D->C
E
2026-08-18T12:00:01.920061
image/svg+xml
Matplotlib v3.11.1,
D->E
E->F
structs
Inference in 0.61ms
A
2026-08-18T12:00:02.868751
image/svg+xml
Matplotlib v3.11.1,
B
2026-08-18T12:00:02.894629
image/svg+xml
Matplotlib v3.11.1,
A->B
C
2026-08-18T12:00:02.930559
image/svg+xml
Matplotlib v3.11.1,
B->C
F
2026-08-18T12:00:03.011769
image/svg+xml
Matplotlib v3.11.1,
B->F
D
2026-08-18T12:00:02.954184
image/svg+xml
Matplotlib v3.11.1,
D->C
E
2026-08-18T12:00:02.976329
image/svg+xml
Matplotlib v3.11.1,
D->E
E->F
noise=1
structs
Inference in 0.24ms
A
2026-08-18T12:00:03.304714
image/svg+xml
Matplotlib v3.11.1,
B
2026-08-18T12:00:03.342344
image/svg+xml
Matplotlib v3.11.1,
A->B
C
2026-08-18T12:00:03.375207
image/svg+xml
Matplotlib v3.11.1,
B->C
F
2026-08-18T12:00:03.463705
image/svg+xml
Matplotlib v3.11.1,
B->F
D
2026-08-18T12:00:03.407527
image/svg+xml
Matplotlib v3.11.1,
D->C
E
2026-08-18T12:00:03.429766
image/svg+xml
Matplotlib v3.11.1,
D->E
E->F
noise=0.1
structs
Inference in 0.87ms
A
2026-08-18T12:00:03.714151
image/svg+xml
Matplotlib v3.11.1,
B
2026-08-18T12:00:03.750912
image/svg+xml
Matplotlib v3.11.1,
A->B
C
2026-08-18T12:00:03.779536
image/svg+xml
Matplotlib v3.11.1,
B->C
F
2026-08-18T12:00:03.888411
image/svg+xml
Matplotlib v3.11.1,
B->F
D
2026-08-18T12:00:03.812959
image/svg+xml
Matplotlib v3.11.1,
D->C
E
2026-08-18T12:00:03.851139
image/svg+xml
Matplotlib v3.11.1,
D->E
E->F
noise=0.01
structs
Inference in 0.27ms
A
2026-08-18T12:00:04.193980
image/svg+xml
Matplotlib v3.11.1,
B
2026-08-18T12:00:04.229010
image/svg+xml
Matplotlib v3.11.1,
A->B
C
2026-08-18T12:00:04.251502
image/svg+xml
Matplotlib v3.11.1,
B->C
F
2026-08-18T12:00:04.358747
image/svg+xml
Matplotlib v3.11.1,
B->F
D
2026-08-18T12:00:04.290394
image/svg+xml
Matplotlib v3.11.1,
D->C
E
2026-08-18T12:00:04.321995
image/svg+xml
Matplotlib v3.11.1,
D->E
E->F
noise=0.001
structs
Inference in 0.82ms
A
2026-08-18T12:00:04.676006
image/svg+xml
Matplotlib v3.11.1,
B
2026-08-18T12:00:04.697593
image/svg+xml
Matplotlib v3.11.1,
A->B
C
2026-08-18T12:00:04.724719
image/svg+xml
Matplotlib v3.11.1,
B->C
F
2026-08-18T12:00:04.818069
image/svg+xml
Matplotlib v3.11.1,
B->F
D
2026-08-18T12:00:04.754439
image/svg+xml
Matplotlib v3.11.1,
D->C
E
2026-08-18T12:00:04.777704
image/svg+xml
Matplotlib v3.11.1,
D->E
E->F
noise=1e-10