Comparing BNs¶
In [1]:
def dict2html(di1,di2=None):
res= "<br/>".join([f"<b>{k:15}</b>:{v}" for k,v in di1.items()])
if di2 is not None:
res+="<br/><br/>"
res+= "<br/>".join([f"<b>{k:15}</b>:{v}" for k,v in di2.items()])
return res
In [2]:
import pyAgrum as gum
import pyAgrum.lib.notebook as gnb
import pyAgrum.lib.bn_vs_bn as gcm
How to compare two BNs¶
PyAgrum allows you to compare BNs in several ways. This notebook show you some of them: - a graphical diff between the 2 BNs - some scores form recal and precision - distance measures (for more, see notebook 26-klForBNs
for more)
Between two different structures¶
In [3]:
bn1=gum.fastBN("A->B->C->D->E<-A->F")
bn2=gum.fastBN("A->B<-C->D->E<-A;F->E")
cmp=gcm.GraphicalBNComparator(bn1,bn2)
kl=gum.ExactBNdistance(bn1,bn2) # bruteForce is possible car the BNs are small
gnb.sideBySide(bn1,bn2,gnb.getBNDiff(bn1,bn2),dict2html(cmp.scores(),cmp.hamming()),cmp.equivalentBNs(),dict2html(kl.compute()),
captions=['bn1','bn2','graphical diff','Scores','equivalent ?','distances'],valign="bottom")
The logic for the arcs of the graphical diff is the following. When comparaing bn1 with bn2 (in that order) : - full black line: the arc is common for both - full red line: the arc is common but inverted in bn2 - dotted black line: the arc is added in bn2 - dotted red line: the arc is removed in bn2
For the scores : - precision and recall are computed considering BN1 as the reference - \(Fscore=\frac{2\cdot recall\cdot precision}{recall+precision}\) is the weighted average of Precision and Recall. - \(dist2opt=\sqrt{(1-precision)^2+(1-recall)^2}\) represents the euclidian distance to the ideal(precision=1,recall=1)
EquivalentBN
return “OK” if equivalent or a reason for non equivalence
Finally, BruteForceKL
compute in the same time several distances : I-projection, M-projection, Hellinger and Bhattacharya. For more complex BNs, there exists a GibbsKL
to approximate those distances. Of course, the computation are much slower.
Same structure, different parameters¶
In [4]:
bn1=gum.fastBN("A->B->C->D->E<-A->F")
bn2=gum.fastBN("A->B->C->D->E<-A->F")
cmp=gcm.GraphicalBNComparator(bn1,bn2)
kl=gum.ExactBNdistance(bn1,bn2) # bruteForce is possible car the BNs are small
gnb.sideBySide(bn1,bn2,gnb.getBNDiff(bn1,bn2),dict2html(cmp.scores(),cmp.hamming()),cmp.equivalentBNs(),dict2html(kl.compute()),
captions=['bn1','bn2','graphical diff','Scores','equivalent ?','distances'],valign="bottom")
identical BNs¶
In [5]:
bn1=gum.fastBN("A->B->C->D->E<-A->F")
bn2=bn1
cmp=gcm.GraphicalBNComparator(bn1,bn2)
kl=gum.ExactBNdistance(bn1,bn2) # bruteForce is possible car the BNs are small
gnb.sideBySide(bn1,bn2,gnb.getBNDiff(bn1,bn2),dict2html(cmp.scores(),cmp.hamming()),cmp.equivalentBNs(),dict2html(kl.compute()),
captions=['bn1','bn2','graphical diff','Scores','equivalent ?','distances'],valign="bottom")
In the notebook Learning_DirichletPriorAndWeightedDatabase
, you can find an interresting discussion on how can change those scores and distance.
In [ ]:
In [ ]: