Conditional Entropy for nodes of BNLearn Bayesian Network
getEntropy <- function(probDist, base=exp(1)){
#Calculates entropy given a numeric corresponding to probabilities in a discrete distribution
-sum(log(probDist, base=base) * probDist)
}
getConditionalEntropyGivenParents <- function(bn.model, node, base){
#Calculates the conditional entropy of a node given its parents in a fitted bayesian network object from BNLearn package.
#Only works for discrete valued distributions fitted on data where variables are non-ordered factors.
#Uses gRain package to convert to independence graph and apply junction tree algo for BN queries.
#bn.model is a fitted bn.object
#node is a character name of the node for which to find conditional entropy.
#base is the desired base of the logarithm in the entropy calculate. By setting base equal to the number of levels
# of the node variable, maximum entropy will be 1. Set to 2 for entropy units in bits.
require(bnlearn)
require(gRain)
nodeParents <- bnlearn::parents(bn.model, node)
levelList <- lapply(nodeParents, function(parent) unique(rownames(bn.model[[parent]]$prob)))
parentsCombinations <- expand.grid(levelList, stringsAsFactors = FALSE)
jtree <- compile(as.grain(bn.model))
conditionalEntropy <- sum(apply(parentsCombinations, 1, function(row){
evidence.grain <- setFinding(jtree, nodes = nodeParents, states = row)
conditionalDist <- querygrain(evidence.grain, nodes = node)[[node]]
comboProb <- pEvidence(evidence.grain)
getEntropy(conditionalDist, base = base) * comboProb
}))
conditionalEntropy
}