Skip to content

Sensitivity analysis for Bayesian networks using credal networks

Creative Commons LicenseaGrUMinteractive 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.

import pyagrum.credal_net as gum
import pyagrum.lib.notebook as gnb
bn = gum.fastBN("A->B->C<-D->E->F<-B")
gnb.flow.row(bn, gnb.getInference(bn))
G F F E E E->F B B B->F C C B->C A A A->B D D D->E D->C
structs Inference in   1.20ms A 2026-10-09T08:52:23.128023 image/svg+xml Matplotlib v3.11.2, B 2026-10-09T08:52:23.150670 image/svg+xml Matplotlib v3.11.2, A->B C 2026-10-09T08:52:23.173668 image/svg+xml Matplotlib v3.11.2, B->C F 2026-10-09T08:52:23.250997 image/svg+xml Matplotlib v3.11.2, B->F D 2026-10-09T08:52:23.204043 image/svg+xml Matplotlib v3.11.2, D->C E 2026-10-09T08:52:23.226108 image/svg+xml Matplotlib v3.11.2, 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)
gnb.show(cr)

svg

cr.bnToCredal(1e-10, False, False)
cr.computeBinaryCPTMinMax()
print(cr)
A:Range([0,1])
<> : [[0.55409 , 0.44591] , [0.554051 , 0.445949]]
B:Range([0,1])

<A:0> : [[0.805177 , 0.194823] , [0.805175 , 0.194825]] <A:1> : [[0.228426 , 0.771574] , [0.218254 , 0.781746]]

C:Range([0,1])

<B:0|D:0> : [[0.515819 , 0.484181] , [0.515749 , 0.484251]] <B:1|D:0> : [[0.446477 , 0.553523] , [0.446273 , 0.553727]] <B:0|D:1> : [[0.764305 , 0.235695] , [0.764303 , 0.235697]] <B:1|D:1> : [[0.636461 , 0.363539] , [0.636449 , 0.363551]]

D:Range([0,1])
<> : [[0.792033 , 0.207967] , [0.792032 , 0.207968]]
E:Range([0,1])

<D:0> : [[0.448349 , 0.551651] , [0.448151 , 0.551849]] <D:1> : [[0.379635 , 0.620365] , [0.379027 , 0.620973]]

F:Range([0,1])

<E:0|B:0> : [[0.440777 , 0.559223] , [0.440554 , 0.559446]] <E:1|B:0> : [[0.577948 , 0.422052] , [0.577921 , 0.422079]] <E:0|B:1> : [[0.558909 , 0.441091] , [0.558873 , 0.441127]] <E:1|B:1> : [[0.675147 , 0.324853] , [0.67514 , 0.32486]]

Testing difference hypothesis about the global precision on the parameters

Section titled “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.

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)
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()
G F F E E E->F B B B->F C C B->C A A A->B D D D->E D->C
structs Inference in   1.20ms A 2026-10-09T08:52:23.128023 image/svg+xml Matplotlib v3.11.2, B 2026-10-09T08:52:23.150670 image/svg+xml Matplotlib v3.11.2, A->B C 2026-10-09T08:52:23.173668 image/svg+xml Matplotlib v3.11.2, B->C F 2026-10-09T08:52:23.250997 image/svg+xml Matplotlib v3.11.2, B->F D 2026-10-09T08:52:23.204043 image/svg+xml Matplotlib v3.11.2, D->C E 2026-10-09T08:52:23.226108 image/svg+xml Matplotlib v3.11.2, D->E E->F
structs Inference in   0.79ms A 2026-10-09T08:52:24.418625 image/svg+xml Matplotlib v3.11.2, B 2026-10-09T08:52:24.452736 image/svg+xml Matplotlib v3.11.2, A->B C 2026-10-09T08:52:24.485038 image/svg+xml Matplotlib v3.11.2, B->C F 2026-10-09T08:52:24.572393 image/svg+xml Matplotlib v3.11.2, B->F D 2026-10-09T08:52:24.513663 image/svg+xml Matplotlib v3.11.2, D->C E 2026-10-09T08:52:24.543894 image/svg+xml Matplotlib v3.11.2, D->E E->F
noise=1
structs Inference in   0.18ms A 2026-10-09T08:52:24.870830 image/svg+xml Matplotlib v3.11.2, B 2026-10-09T08:52:24.902527 image/svg+xml Matplotlib v3.11.2, A->B C 2026-10-09T08:52:24.922807 image/svg+xml Matplotlib v3.11.2, B->C F 2026-10-09T08:52:24.982671 image/svg+xml Matplotlib v3.11.2, B->F D 2026-10-09T08:52:24.940132 image/svg+xml Matplotlib v3.11.2, D->C E 2026-10-09T08:52:24.957783 image/svg+xml Matplotlib v3.11.2, D->E E->F
noise=0.1
structs Inference in   0.85ms A 2026-10-09T08:52:25.267521 image/svg+xml Matplotlib v3.11.2, B 2026-10-09T08:52:25.307153 image/svg+xml Matplotlib v3.11.2, A->B C 2026-10-09T08:52:25.330600 image/svg+xml Matplotlib v3.11.2, B->C F 2026-10-09T08:52:25.433310 image/svg+xml Matplotlib v3.11.2, B->F D 2026-10-09T08:52:25.358939 image/svg+xml Matplotlib v3.11.2, D->C E 2026-10-09T08:52:25.400389 image/svg+xml Matplotlib v3.11.2, D->E E->F
noise=0.01
structs Inference in   1.25ms A 2026-10-09T08:52:25.713199 image/svg+xml Matplotlib v3.11.2, B 2026-10-09T08:52:25.739892 image/svg+xml Matplotlib v3.11.2, A->B C 2026-10-09T08:52:25.773165 image/svg+xml Matplotlib v3.11.2, B->C F 2026-10-09T08:52:25.884853 image/svg+xml Matplotlib v3.11.2, B->F D 2026-10-09T08:52:25.818467 image/svg+xml Matplotlib v3.11.2, D->C E 2026-10-09T08:52:25.850468 image/svg+xml Matplotlib v3.11.2, D->E E->F
noise=0.001
structs Inference in   2.42ms A 2026-10-09T08:52:26.331369 image/svg+xml Matplotlib v3.11.2, B 2026-10-09T08:52:26.366177 image/svg+xml Matplotlib v3.11.2, A->B C 2026-10-09T08:52:26.391904 image/svg+xml Matplotlib v3.11.2, B->C F 2026-10-09T08:52:26.510323 image/svg+xml Matplotlib v3.11.2, B->F D 2026-10-09T08:52:26.442320 image/svg+xml Matplotlib v3.11.2, D->C E 2026-10-09T08:52:26.478292 image/svg+xml Matplotlib v3.11.2, D->E E->F
noise=1e-10