# Bayesian networks - prediction question

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


## 1 Answer

The joint distribution of the network is given by

$$P(X) P(Y1 \mid X) P(Y2 \mid X)$$

We want

$$P(X \mid Y1=false, Y2=true)$$

This is equal to

$$\frac{P(X) P(Y1 = false \mid X) P(Y2 = true \mid X)} {P(Y1 = false, Y2=true)}$$

We actually do not need to calculate the denominator in the expression above, as we can normalise the values that are returned in the numerator.

So now we can just plug in the values from your CPT's in to the numerator

For P(X = true): $$P(X=true) P(Y1 = false \mid X=true) P(Y2 = true \mid X=true)$$

  0.33* 0.33* 0.67
0.072963


And for For P(X = false): $$P(X=false) P(Y1 = false \mid X=false) P(Y2 = true \mid X=false)$$

0.67* 0.5* 0.5
0.1675


We convert these to actual probabilities by normalising

So for P(X=true)

0.072963 / (0.072963 + 0.1675)
0.3034271


and similarly for P(x=false).

So these agree with the results from your gRain query