Bayesian Networks and Probabilistic Inference
How a graph and a few small tables stand in for a joint distribution with thousands of entries, how to answer a query against it exactly by enumeration and variable elimination, and what to do when exact inference is out of reach: rejection sampling, likelihood weighting, and Gibbs sampling, each worked through on the same two networks.
Prerequisites: Bayes' Theorem and Belief Updating
Bayes' theorem tells you how to update one belief on one piece of evidence. A real agent holds beliefs about dozens of variables at once, and the joint distribution over them - the object that answers every question - has entries for Boolean variables. Nobody can write it down. This article is about the representation that makes the joint usable, and the algorithms that query it.
A. The network is the joint
A Bayesian network is a directed acyclic graph. Each node is a random variable; an arrow from to makes a parent of ; and each node carries a conditional probability table giving , one row per combination of parent values. A Boolean node with Boolean parents needs numbers.
Russell and Norvig's example is an alarm. It responds to burglary and, less reliably, to earthquakes; two neighbours, John and Mary, call when they hear it, John sometimes confusing the phone for the alarm and Mary sometimes missing it behind loud music. Arrows , , , , and ten numbers:
The meaning of the picture is one equation. For any complete assignment,
So the probability that the alarm sounds with no burglary and no earthquake, and both neighbours call, is
Every one of the 32 joint entries is available this way, from ten numbers rather than 31. The saving is not a trick: it is the claim, made by the missing arrows, that each variable is conditionally independent of its non-descendants given its parents. Stronger still, every node is independent of all other nodes given its Markov blanket - parents, children, and children's other parents. Given the alarm and the earthquake, the phone calls say nothing further about a burglary.
B. Exact inference
A query asks for . Since every joint entry is a product of CPT entries, the query is a normalised sum of products over the hidden variables. Both neighbours have called; is it a burglary?
Four terms for , four for , each a product of five numbers:
Two independent reports lift a one-in-a-thousand prior to 28 percent, and no further, because the no-burglary mass arrives by three comparable routes: a causeless alarm then both calls, ; no alarm but both calls anyway, ; and an earthquake alarm then both calls, . Together they outweigh the burglary route, , by 2.5 to one.
Enumeration evaluates this as a depth-first tree, and the tree repeats itself: the product is computed once under and again under . On Boolean variables the cost is - better than the of building each joint entry separately, but most of it recomputation. Variable elimination stores each piece as a factor - a table over the variables it still depends on - and combines factors by pointwise product and by summing out. Summing out gives a factor over :
Summing out against leaves , and multiplying by and normalising returns with every leaf product done once.
Whether this is fast depends on the shape of the graph. On a polytree - at most one undirected path between any two nodes, as here - variable elimination is linear in the size of the network. Add a second path and the intermediate factors can grow exponentially in the worst case. The general problem is #P-hard: as hard as counting the satisfying assignments of a propositional formula. That is the reason the rest of this article exists.
The network below is this one, and every number in it is exact - the posteriors come from summing all 32 assignments, not from sampling. Click a node to say what you know. Start with both neighbours calling: a burglary goes to 28.4%, which is already worth sitting with, since the calls are excellent evidence about the alarm and the alarm is a poor witness to burglary. Then add the earthquake. It makes the calls more likely, and it sends the burglary back towards nothing.
Interactive: say what you know, watch what follows
Click a node to cycle it: unknown, happened, did not happen.
- P(burglary)
- 0.1%
- P(earthquake)
- 0.2%
- P(alarm)
- 0.3%
- P(evidence)
- 1.000000
Nothing is known yet, so every node sits at its prior: a burglary at 0.1%, an earthquake at 0.2%. Click a neighbour and watch the influence travel up the arrows to the alarm and then down to the other neighbour, even though no arrow joins the two neighbours at all.
C. Sampling when exact is impossible
The sprinkler network has four Boolean variables and two paths from to , one through the sprinkler and one through rain:
Prior sampling draws each variable from its CPT in parent-first order. The probability of producing an event is the product of the entries consulted, which is the joint itself: comes out with probability . Frequencies therefore converge to probabilities, and the estimate is consistent.
Rejection sampling answers a conditional query by discarding every sample that disagrees with the evidence. For , exact value , a seeded run of 1,000 prior samples rejected 703 and kept 79 with rain against 218 without, for an estimate of . Seventy percent of the effort went nowhere, and that is the benign case: the survival rate is , which falls exponentially with the number of evidence variables. Ask the burglary network for and about 21 samples in 10,000 survive.
Runs in your browser. The first run downloads the Python runtime (~10 MB), then it is cached.
Likelihood weighting fixes the evidence variables instead of sampling them, so every event is consistent, and weights each event by the probability of the evidence given the parents the sampler chose. For with ordering : the weight starts at , is evidence so ; is sampled from , say false; from , say true; is evidence so . The event is tallied under rain with weight . Nothing is discarded, and because sampling probability times weight equals the joint, the weighted tally is consistent: a thousand samples on the same seed give against an exact . The method degrades when the evidence is improbable under the sampled values, because a few heavy weights then dominate everything.
Gibbs sampling is Markov chain Monte Carlo. Fix the evidence, start from any state, and repeatedly resample one non-evidence variable conditioned on its Markov blanket. That conditional is a product of a handful of CPT entries:
For from the state , resampling uses , which gives ; say it comes out false. Resampling then uses , which gives . Every state visited is a sample. A thousand steps on a fixed seed estimate against the exact .
The reason this works is that the chain has a stationary distribution and the Gibbs step satisfies detailed balance with respect to the posterior, which forces the two to coincide: the long-run fraction of time in each state is . No sample is rejected and no weight collapses. The cost is correlation between consecutive states, so the chain needs time to forget where it started.
Consistency is a claim about a limit, so the figure below puts the limit on the screen: the dashed line is the exact posterior, obtained by enumerating the joint and sharing no code with either sampler. Drag the sample size and watch the two estimates walk toward it. Then switch to the burglary query, where rejection sampling keeps 21 samples in 10,000 and likelihood weighting keeps all of them and still struggles, because fixing the evidence removes the waste rather than the variance.
Interactive: two samplers against the exact answer
The exact value comes from enumerating the joint, not from either sampler.
- Exact
- 0.3000
- Rejection sampling
- 0.3045
- Likelihood weighting
- 0.3029
- Kept by rejection
- 289
Rejection sampling reads 0.3045 from the 289 samples it kept of 1,000; likelihood weighting reads 0.3029 from all of them; the exact answer is 0.3000. Both estimators are consistent, which is a claim about a limit rather than about any one run, so the useful thing to do is drag the sample size and watch the two numbers walk toward the third. The discarded share is not noise in the procedure - it is 70.00% of the work, and it grows exponentially with the number of evidence variables.
Where this leaves you
A Bayesian network is a joint distribution you can actually write down. Exact inference is a sum of products that variable elimination performs without repetition, cheap on polytrees and intractable in general. When the graph is too tangled, sampling gives consistent estimates at a cost that depends on how the evidence is handled: rejection wastes, weighting concentrates, and Gibbs wanders - each of which is the right choice somewhere. The training path Probabilistic Reasoning with Bayesian Networks works every one of these computations by hand and by code.
References & further reading
- Stuart Russell, Peter Norvig, Artificial Intelligence: A Modern Approach, Pearson (3rd edition), 2010· Kudos AI reference library
Copyrighted works are cited for reference only and are not hosted here; please consult the publisher for access.