Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Computing unconditional probabilities at a children node #147

Closed
bernardokp opened this issue Aug 23, 2022 · 4 comments
Closed

Computing unconditional probabilities at a children node #147

bernardokp opened this issue Aug 23, 2022 · 4 comments

Comments

@bernardokp
Copy link

Hello,

I need to compute probabilities in a BN and for a bn = BayesNet() with 4 nodes (nodes 1 2 and 3 are parents of node 4, all Bernoulli r.v.) I was able to

  1. Compute the joint distribution:
    pdf(bn, :node1=>true, :node2=>true, :node3=>true, :node4=>true)

  2. Compute the conditional distribution at node 4:
    cpd4(:node1=>false, :node2=>true, :node3=>true)

What I could not do is to compute

Prob(:node4 = false)

I know that mathematically the answer is

\sum_{s\in S_4} Prob(s) Prob (node 4 = false | s) (1)

where S_4 is the set of states associated with node 4 (8 of them, TTT, TTF, TFF, etc).

Is there an automatic way of computing that without actually constructing equation (1)?

Thanks in advance!

Bernardo

@tawheeler
Copy link
Contributor

Hello Bernardo.

I believe that what you are looking for is the inference section of our documentation.

For example:

ϕ = infer(bn, :c, evidence=Assignment(:b=>1))

will give you the posterior distribution over c given that b is 1. Note that this means we marginalize over any variables that are not b or c.

As such, for your example, just run ϕ = infer(bn, :node4, evidence=Assignment()) and see what the resulting factor has for :node4 = False.

@bernardokp
Copy link
Author

Hello Tim,

thanks for the reply. I believe you are right, this is the function I need. However, I tried the command you suggested but it did not work. I went back to the tutorial and I understood the inference example.

Maybe it is because I am using StaticCPD? I don't know.
Here is my code (sorry to bother, and thanks in advance):

using DataFrames
using Random
Random.seed!(0) 
using BayesNets
using TikzGraphs 
using TikzPictures

bn = BayesNet()
d2 = StaticCPD(:node2, Bernoulli(0.8))
push!(bn, d2)
d1 = StaticCPD(:node1, Bernoulli(0.8))
push!(bn, d1)
d3 = StaticCPD(:node3, Bernoulli(0.8))
push!(bn, d3)

cpd4 = FunctionalCPD{Bernoulli}(:node4, [:node1, :node2, :node3], a->Bernoulli(
    if (a[:node1] == true  &&  a[:node2] == true && a[:node3] == true)
        1.0 
    elseif  (a[:node1] == true   &&  a[:node2] == true  && a[:node3] == false)
        2/3
    elseif  (a[:node1] == true   &&  a[:node2] == false && a[:node3] == true)
        2/3
    elseif  (a[:node1] == true   &&  a[:node2] == false && a[:node3] == false)
        1/3
    elseif  (a[:node1] == false  &&  a[:node2] == true  && a[:node3] == true)
        2/3
    elseif  (a[:node1] == false  &&  a[:node2] == true  && a[:node3] == false)
        1/3
    elseif  (a[:node1] == false  &&  a[:node2] == false && a[:node3] == true)
        1/3
    else 
        0.0
    end
    )
)
push!(bn, cpd4)
ϕ = infer(bn, :node4, evidence=Assignment())

I got this error:
MethodError: no method matching infer(::BayesNet{CPD}, ::Symbol; evidence=Dict{Symbol, Any}())

Best,
Bernardo

@tawheeler
Copy link
Contributor

Ah, yes, I think the inference methods require using a DiscreteBayesNet - otherwise users could have continuous variables, non-integer variables, etc.

Here is the equivalent approach:

bn = DiscreteBayesNet()
push!(bn, DiscreteCPD(:node2, [0.2,0.8])) # 1 -> false, 2 -> true
push!(bn, DiscreteCPD(:node1, [0.2,0.8])) # 1 -> false, 2 -> true
push!(bn, DiscreteCPD(:node3, [0.2,0.8])) # 1 -> false, 2 -> true
push!(bn, DiscreteCPD(:node4, [:node1, :node2, :node3], [2,2,2],
        [Categorical([1.0,0.0]), # node1, node2, node3 = FFF
         Categorical([2/3, 1/3]), # FFT
         Categorical([2/3,1/3]), # FTF
         Categorical([1/3,2/3]), # FTT
         Categorical([2/3,1/3]), # TFF
         Categorical([1/3,2/3]), # TFT
         Categorical([1/3,2/3]), # TTF
         Categorical([0.0,1.0]), # TTT
        ]))

julia> convert(DataFrame, infer(bn, :node4, evidence=Assignment()))
2×2 DataFrame
 Row  │ node4  potential 
          │ Int64  Float64   
────┼──────────────────
   1     │     1        0.2
   2     │     2        0.8

which tells us that P(:node4 = true) is 0.8

@bernardokp
Copy link
Author

Awesome Tim, thanks for saving me again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants