I'm reading Building Intelligent Interactive Tutors (Woolf, 2009) on student models for ITSs. On page 261, the author presents an example for a simple Bayesian network ($S \rightarrow E$), where $S$ is the unobserved skill variable (with states: $0$ = knows; $1$ = doesn't know) and $E$ is the observed evidence variable (with states: $0$ = incorrect; $1$ = correct).

The author goes on to compute the posterior probability $P(S|E)$ for $S=1$ through Bayes' rule, assuming the following probabilities:

  • Prior probability $P(S=1)=0.5$
  • $P(E=1|S=1)=0.8$
  • $P(E=0|S=0)=0.95$

He reaches the following answers:

  • $P(S=1|E=1)=0.94$
  • $P(S=1|E=0)=0.17$

Then, he claims the revised posterior probability for $S=1$ is approximately $0.78$ for the first case and approximately $0.06$ for the second case. Where do these posterior probability values come from? What do they represent?

I've coded the example in Python (using the pgmpy library) and got the same values for $P(S=1|E=1)$ and $P(S=1|E=0)$. Here's the code and its output (NewtonsLaw is $S$ and Problem023 is $E$):

import numpy as np
from pgmpy.models import BayesianModel
from pgmpy.estimators import BayesianEstimator
from pgmpy.inference import VariableElimination
from pgmpy.factors.discrete import TabularCPD

# Bayesian network structure
model = BayesianModel([('NewtonsLaw', 'Problem023')])

# CPDs
cpd_problem_023 = TabularCPD('Problem023', 2, [[0.95, 0.2],
                                          [0.05, 0.8]],
                        evidence=['NewtonsLaw'], evidence_card=[2])
cpd_newtons_law = TabularCPD('NewtonsLaw', 2, [[0.5, 0.5]])

# Add probabilities to model
model.add_cpds(cpd_problem_023, cpd_newtons_law)

# Query
inference = VariableElimination(model)

posterior_newtons_law_right = inference.query(['NewtonsLaw'], evidence={'Problem023': 1})

posterior_newtons_law_wrong = inference.query(['NewtonsLaw'], evidence={'Problem023': 0})


| NewtonsLaw   |   phi(NewtonsLaw) |
| NewtonsLaw_0 |            0.0588 |
| NewtonsLaw_1 |            0.9412 |
| NewtonsLaw   |   phi(NewtonsLaw) |
| NewtonsLaw_0 |            0.8261 |
| NewtonsLaw_1 |            0.1739 |

2 Answers 2


The posterior probabilities come from Bayes Theorem, which is the following given the symbols the author uses:

           P(E|S)*P(S)                  P(E|S)*P(S)
P(S|E) =  ------------- =  -----------------------------------
               P(E)         P(E|S=1)*P(S=1) + P(E|S=0)*P(S=0)

On the right, the numerator is the conditional probability of the answer being right or not, E, given whether the student knows or not, S, weighted by the prior.

The denominator is the prior probability of E: the probability of getting answer E given the prior distribution. It uses the law of total probability: P(E) isn't given to us directly, but can calculate it because we know all of the P(E|S) combinations and P(S).

They represent the probability of state S after (or posterior to) observing results, in this case just one observation.

Conceptually, it gives you an updated estimate of whether the student knows (S=1) or doesn't know (S=0) the material after getting the response to a question. If they get the question right, you're more sure now that they know the material. If they got 2/2 questions right then you'd be even more sure. If they got 4/5 wrong then you'd be pretty sure they don't know the material.

Bayes' Theorem makes this quantitative. From the input and output values:

  • prior: knowing Newton's law is 50% yes, 50% no
  • after getting one question right: 94% yes, 6% no
  • after getting one question wrong: 17% yes, 83% no

You might be curious why it isn't symmetric: getting the question wrong doesn't mean the percentages are 6% yes, 94% no. The reason is mathematically described by the Bayes Factor. For each result E we can look at the probabilities P(E|S):

  • for E=1, getting it right: P(E=1|S=1) is 0.8, but P(E=1|S=0) is only 0.05. So by 16:1 odds the right answer comes from knowing the material. This is very lopsided, so the posterior probabilities are closer to 100%/0%
    • Note: the 94%/6% result is exactly 16:1 odds!
  • for E=0, getting it wrong: P(E=0|S=1) is 0.2, and P(E=0|S=0) is 0.95. So by about 5:1 odds the wrong answer comes from not knowing the material. Not nearly as lopsided as 16:1 odds, so as a result, the posterior probabilities are farther from 0%/100%
    • Note: 17%/83% is exactly the 02:0.95 odds!

The odds work out really nicely in this case because the Bayes Factor equation (derived from Bayes Theorem) is posteriorOdds = bayesFactor * priorOdds, and the prior odds are just P(S=1)/P(S=0) = 1. So it leaves posteriorOdds = bayesFactor. The Bayes Factors are the ratios like 16:1 above. See this answer for more. IMO it's more helpful than the Wiki link for understanding; the Wiki page is more about the derivation.

So in this way, you can conceptually think of the posterior probabilities/odds versus the prior as how different your data was than the prior. In this example, 94%/6% is very different from the prior of 50%/50% so the results are pretty convincing. But I should also note that a prior probability of 0 means P(S|E) = 0 from the formulas no matter what. So there are limits to this intuition. It also illustrates the weakness of Bayesian methods - no amount of data can save you from a sufficiently bad prior!


If the answer still matters, I think to update the posterior probabilities (revised posteriors), one must conduct parameter learning as explained here: http://pgmpy.org/models.html

You did good inferencing with pgmpy, but you cannot derive revised posteriors with inferencing, rather use learning with model.fit(...).

  • $\begingroup$ The link is dead. Can you provide a current one? $\endgroup$ Feb 24, 2022 at 15:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.