Let's consider a dumb spam filter BN (see figure below) for which I've already calculated the a posteriori parameter distributions (see normalized table values).
I want to predict if next email without the "book" word (Y1=F) and with the "free" word (Y2=T) is spam (X=T) or not spam (X=F).
I guess the question can be written as P(X=T | Y1=F, Y2=T) ... you may confirm ...
Here Y1 and Y2 are independant, I've been playing around with Bayes and Chain rules to get the right formulae for computation, without success.
P(X|Y1,Y2) = P(Y1,Y2|X) P(X) / P(Y1, Y2) = P(Y1|X) P(Y2|Y1,X) P(X) / P(Y1|Y2)P(Y2) = P(Y1|X) P(Y2|X) P(X) / P(Y1)P(Y2)
The R script below says that this probability is 0.3034. Is this P(X=T | Y1=F, Y2=T) even though the function parameter "type=marginal" is used ?.
Note: displayed conditional probability tables are not normalized (sum is not 1).
library(gRain) X <- cptable(~ isSpam, values=c(0.33, 0.67), levels=c("true", "false")) Y1 <- cptable(~ hasBook|isSpam, values=c(0.335, 0.165, 0.25, 0.25), levels=c("true", "false")) Y2 <- cptable(~ hasFree|isSpam, values=c(0.335, 0.165, 0.25, 0.25), levels=c("true", "false")) plist <- compileCPT(list(X, Y1, Y2)) pn <- grain(plist) pn[["cptlist"]] #$isSpam #isSpam # true false # 0.33 0.67 #$hasBook # isSpam #hasBook true false # true 0.67 0.5 # false 0.33 0.5 #$hasFree isSpam #hasFree true false # true 0.67 0.5 # false 0.33 0.5 pn1 <- setEvidence(pn, evidence = list(hasBook = "false", hasFree = "true")) # type = "marginal": marginal distribution for each node in nodes; (marginal.isSpam <- querygrain(pn1, nodes = "isSpam", type = "marginal")) # isSpam # true false # 0.3034271 0.6965729