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