Gilbert Gilbert - 1 month ago 11
R Question

R some conditional probability distributions of node do not sum to one

I'm building a Bayesian Network with the

bnlearn
packages in R. After building the tree I'm trying to query some probabilities and is returning the following error....
Error in check.fit.dnode.spec(dist[[node]], node = node) :
some conditional probability distributions of node Sprinkler do not sum to one.
. When I go and check the
Sprinkler
it does add to one. Here is the outcome of
Sprinkler
...

Rain
Slippery_Road true false
true 0.7 0.3
false 0.0 1.0


Here is my entire code...

require(bnlearn)

vname <- c('Winter', 'Sprinkler', 'Rain', 'Wet_Grass', 'Slippery_Road')
e <- empty.graph(vname)
arc.set <- matrix(c('Winter', 'Winter', 'Sprinkler', 'Rain', 'Rain',
'Sprinkler', 'Rain', 'Wet_Grass', 'Wet_Grass', 'Slippery_Road'),
ncol = 2, dimnames = list(NULL, c('from', 'to')))
arcs(e) <- arc.set

# Winter
cptW <- matrix(c(0.6, 0.4), ncol = 2, dimnames = list(NULL, c('true', 'false')))
cptW

# Sprinkler
cptS <- c(0.2, 0.75, 0.8, 0.25)
dim(cptS) <- c(2, 2)
dimnames(cptS) <- list('Sprinkler' = c('true', 'false'),
'Winter' = c('true', 'false'))
cptS

# Rain
cptR <- c(0.8, 0.1, 0.2, 0.9)
dim(cptR) <- c(2, 2)
dimnames(cptR) <- list('Rain' = c('true', 'false'),
'Winter' = c('true', 'false'))
cptR

# Wet Grass
cptG <- c(0.95, 0.9, 0.05, 0.1, 0.8, 0, 0.02, 1)
dim(cptG) <- c(2, 2, 2)
dimnames(cptG) <- list('Wet_Grass' = c('true', 'false'),
'Rain' = c('true', 'false'),
'Sprinkler' = c('true', 'false'))
cptG

# Slippery Road
cptSR <- c(0.7, 0, 0.3, 1)
dim(cptSR) <- c(2, 2)
dimnames(cptSR) <- list('Slippery_Road' = c('true', 'false'),
'Rain' = c('true', 'false'))
cptSR

dfit <- custom.fit(e, dist = list(Winter = cptW, Sprinkler = cptS,
Rain = cptR, Wet_Grass = cptG,
Slippery_Road = cptSR))

# Calculating probabilities
cpquery(dfit, event = (Slippery_Road == 'false'), evidence = (Winter == 'true'))

Answer

Couple of points:

  1. Wet Grass CPT is wrong (0.02 should be 0.2, a typo)?
  2. Seems each CPT should be column stochastic, not row stochastic.

The following works:

require(bnlearn)

vname <- c('Winter', 'Sprinkler', 'Rain', 'Wet_Grass', 'Slippery_Road')
e <- empty.graph(vname)
arc.set <- matrix(c('Winter', 'Winter', 'Sprinkler', 'Rain', 'Rain', 
                    'Sprinkler', 'Rain', 'Wet_Grass', 'Wet_Grass', 'Slippery_Road'),
                  ncol = 2, dimnames = list(NULL, c('from', 'to')))
arcs(e) <- arc.set

The following is your Bayesian Network (DAG):

library(Rgraphviz)
plot(e)

enter image description here

# Winter
cptW <- matrix(c(0.6, 0.4), ncol = 2, dimnames = list(NULL, c('true', 'false')))
cptW

     true false
[1,]  0.6   0.4

# Sprinkler:  P(S|W) since the direction of the edge is W -> S
cptS <- c(0.2, 0.8, 0.75, 0.25)
dim(cptS) <- c(2, 2)
dimnames(cptS) <- list('Sprinkler' = c('true', 'false'),
                       'Winter' = c('true', 'false'))
cptS

          Winter
Sprinkler true false
    true   0.2  0.75
    false  0.8  0.25

# Rain: P(R|W)
cptR <- c(0.8, 0.2, 0.1, 0.9)
dim(cptR) <- c(2, 2)
dimnames(cptR) <- list('Rain' = c('true', 'false'),
                       'Winter' = c('true', 'false'))
cptR   

        Winter
Rain    true false
  true   0.8   0.1
  false  0.2   0.9

# Wet Grass P(WG|S,R)
cptG <- c(0.95, 0.05, 0.9, 0.1, 0.8, 0.2, 0, 1)
dim(cptG) <- c(2, 2, 2)
dimnames(cptG) <- list('Wet_Grass' = c('true', 'false'),
                       'Rain' = c('true', 'false'),
                       'Sprinkler' = c('true', 'false'))
cptG

, , Sprinkler = true

         Rain
Wet_Grass true false
    true  0.95   0.9
    false 0.05   0.1

, , Sprinkler = false

         Rain
Wet_Grass true false
    true   0.8     0
    false  0.2     1

# Slippery Road P(SR|R)
cptSR <- c(0.7, 0.3, 0, 1)
dim(cptSR) <- c(2, 2)
dimnames(cptSR) <- list('Slippery_Road' = c('true', 'false'),
                        'Rain' = c('true', 'false'))
cptSR

              Rain
Slippery_Road true false
        true   0.7     0
        false  0.3     1

dfit <- custom.fit(e, dist = list(Winter = cptW, Sprinkler = cptS,
                                  Rain = cptR, Wet_Grass = cptG,
                                  Slippery_Road = cptSR))

# Calculating probabilities
cpquery(dfit, event = (Slippery_Road == 'false'), evidence = (Winter == 'true'))
# [1] 0.4342105