In the previous chapter we solved the 101 Bowls Problem, and I admitted that it is not really about guessing which bowl the cookies came from; it is about estimating proportions.
In this chapter, we take another step toward Bayesian statistics by solving the Euro problem. Weβll start with the same prior distribution, and weβll see that the update is the same, mathematically. But I will argue that it is a different problem, philosophically, and use it to introduce two defining elements of Bayesian statistics: choosing prior distributions, and using probability to represent the unknown.
When spun on edge 250 times, a Belgian one-euro coin came up heads 140 times and tails 110. βIt looks very suspicious to me,β said Barry Blight, a statistics lecturer at the London School of Economics. βIf the coin were unbiased, the chance of getting a result as extreme as that would be less than 7%.β
To answer that question, weβll proceed in two steps. First weβll use the binomial distribution to see where that 7% came from; then weβll use Bayesβs Theorem to estimate the probability that this coin comes up heads.
Suppose I tell you that a coin is "fair", that is, the probability of heads is 50%. If you spin it twice, there are four outcomes: HH, HT, TH, and TT. All four outcomes have the same probability, 25%.
If we add up the total number of heads, there are three possible results: 0, 1, or 2. The probabilities of 0 and 2 are 25%, and the probability of 1 is 50%.
More generally, suppose the probability of heads is \(p\) and we spin the coin \(n\) times. The probability that we get a total of \(k\) heads is given by the binomial distribution:
We could evaluate this expression ourselves, but we can also use the SciPy function binom.pmf. For example, if we flip a coin n=2 times and the probability of heads is p=0.5, hereβs the probability of getting k=1 heads:
import numpy as np
ks = np.arange(n+1)
ps = binom.pmf(ks, n, p)
ps
array([0.25, 0.5 , 0.25])
The result is a NumPy array with the probability of 0, 1, or 2 heads. If we put these probabilities in a Pmf, the result is the distribution of k for the given values of n and p.
In the article MacKay quotes, the statistician says, "If the coin were unbiased the chance of getting a result as extreme as that would be less than 7%."
We can use the binomial distribution to check his math. The following function takes a PMF and computes the total probability of quantities greater than or equal to threshold.
The result is about 3.3%, which is less than the quoted 7%. The reason for the difference is that the statistician includes all outcomes "as extreme as" 140, which includes outcomes less than or equal to 110.
To see where that comes from, recall that the expected number of heads is 125. If we get 140, weβve exceeded that expectation by 15. And if we get 110, we have come up short by 15.
Any given coin has some probability of landing heads up when spun on edge; Iβll call this probability x. It seems reasonable to believe that x depends on physical characteristics of the coin, like the distribution of weight. If a coin is perfectly balanced, we expect x to be close to 50%, but for a lopsided coin, x might be substantially different. We can use Bayesβs theorem and the observed data to estimate x.
For simplicity, Iβll start with a uniform prior, which assumes that all values of x are equally likely. That might not be a reasonable assumption, so weβll come back and consider other priors later.
def update_euro(pmf, dataset):
"""Update pmf with a given sequence of H and T."""
for data in dataset:
pmf *= likelihood[data]
pmf.normalize()
The first argument is a Pmf that represents the prior. The second argument is a sequence of strings. Each time through the loop, we multiply pmf by the likelihood of one outcome, H for heads or T for tails.
Notice that normalize is outside the loop, so the posterior distribution only gets normalized once, at the end. Thatβs more efficient than normalizing it after each spin (although weβll see later that it can also cause problems with floating-point arithmetic).
The posterior distribution represents our beliefs about x after seeing the data. It indicates that values less than 0.4 and greater than 0.7 are unlikely; values between 0.5 and 0.6 are the most likely.
But that might not be a reasonable choice based on what we know about coins. I can believe that if a coin is lopsided, x might deviate substantially from 0.5, but it seems unlikely that the Belgian Euro coin is so imbalanced that x is 0.1 or 0.9.
And thatβs good news. To see why, imagine two people who disagree angrily about which prior is better, uniform or triangle. Each of them has reasons for their preference, but neither of them can persuade the other to change their mind.
But suppose they agree to use the data to update their beliefs. When they compare their posterior distributions, they find that there is almost nothing left to argue about.
This is an example of swamping the priors: with enough data, people who start with different priors will tend to converge on the same posterior distribution.
A more efficient alternative is to compute the likelihood of the entire dataset at once. For each hypothetical value of x, we have to compute the probability of getting 140 heads out of 250 spins.
Well, we know how to do that; this is the question the binomial distribution answers. If the probability of heads is \(p\text{,}\) the probability of \(k\) heads in \(n\) spins is:
And we can use SciPy to compute it. The following function takes a Pmf that represents a prior distribution and a tuple of integers that represent the data:
from scipy.stats import binom
def update_binomial(pmf, data):
"""Update pmf using the binomial distribution."""
k, n = data
xs = pmf.qs
likelihood = binom.pmf(k, n, xs)
pmf *= likelihood
pmf.normalize()
The data are represented with a tuple of values for k and n, rather than a long string of outcomes. Hereβs the update.
You might have noticed similarities between the Euro problem and the 101 Bowls Problem inΒ <<_101Bowls>>. The prior distributions are the same, the likelihoods are the same, and with the same data the results would be the same. But there are two differences.
The first is the choice of the prior. With 101 bowls, the uniform prior is implied by the statement of the problem, which says that we choose one of the bowls at random with equal probability.
In the Euro problem, the choice of the prior is subjective; that is, reasonable people could disagree, maybe because they have different information about coins or because they interpret the same information differently.
The other difference is the nature of what we are estimating. In the 101 Bowls problem, we choose the bowl randomly, so it is uncontroversial to compute the probability of choosing each bowl. In the Euro problem, the proportion of heads is a physical property of a given coin. Under some interpretations of probability, thatβs a problem because physical properties are not considered random.
As an example, consider the age of the universe. Currently, our best estimate is 13.80 billion years, but it might be off by 0.02 billion years in either direction (see here).
Now suppose we would like to know the probability that the age of the universe is actually greater than 13.81 billion years. Under some interpretations of probability, we would not be able to answer that question. We would be required to say something like, "The age of the universe is not a random quantity, so it has no probability of exceeding a particular value."
Under the Bayesian interpretation of probability, it is meaningful and useful to treat physical quantities as if they were random and compute probabilities about them.
In the Euro problem, the prior distribution represents what we believe about coins in general and the posterior distribution represents what we believe about a particular coin after seeing the data. So we can use the posterior distribution to compute probabilities about the coin and its proportion of heads.
The subjectivity of the prior and the interpretation of the posterior are key differences between using Bayesβs Theorem and doing Bayesian statistics.
Bayesβs Theorem is a mathematical law of probability; no reasonable person objects to it. But Bayesian statistics is surprisingly controversial. Historically, many people have been bothered by its subjectivity and its use of probability for things that are not random.
In this chapter I posed David MacKayβs Euro problem and we started to solve it. Given the data, we computed the posterior distribution for x, the probability a Euro coin comes up heads.
We tried two different priors, updated them with the same data, and found that the posteriors were nearly the same. This is good news, because it suggests that if two people start with different beliefs and see the same data, their beliefs tend to converge.
This chapter introduces the binomial distribution, which we used to compute the posterior distribution more efficiently. And I discussed the differences between applying Bayesβs Theorem, as in the 101 Bowls problem, and doing Bayesian statistics, as in the Euro problem.
However, we still havenβt answered MacKayβs question: "Do these data give evidence that the coin is biased rather than fair?" Iβm going to leave this question hanging a little longer; weβll come back to it in <<_Testing>>.
In Major League Baseball, most players have a batting average between .200 and .330, which means that their probability of getting a hit is between 0.2 and 0.33.
Suppose a player appearing in their first game gets 3 hits out of 3 attempts. What is the posterior distribution for their probability of getting a hit?
For this exercise, Iβll construct the prior distribution by starting with a uniform distribution and updating it with imaginary data until it has a shape that reflects my background knowledge of batting averages.
This distribution indicates that most players have a batting average near 250, with only a few players below 175 or above 350. Iβm not sure how accurately this prior reflects the distribution of batting averages in Major League Baseball, but it is good enough for this exercise.
Whenever you survey people about sensitive issues, you have to deal with social desirability bias, which is the tendency of people to adjust their answers to show themselves in the most positive light. One way to improve the accuracy of the results is randomized response.
As an example, suppose you want to know how many people cheat on their taxes. If you ask them directly, it is likely that some of the cheaters will lie. You can get a more accurate estimate if you ask them indirectly, like this: Ask each person to flip a coin and, without revealing the outcome,
If someone says YES, we donβt know whether they actually cheat on their taxes; they might have flipped heads. Knowing this, people might be more willing to answer honestly.
Suppose you survey 100 people this way and get 80 YESes and 20 NOs. Based on this data, what is the posterior distribution for the fraction of people who cheat on their taxes? What is the most likely quantity in the posterior distribution?
# I'll use a uniform distribution again, although there might
# be background information we could use to choose a more
# specific prior.
hypos = np.linspace(0, 1, 101)
prior = Pmf(1, hypos)
# If the actual fraction of cheaters is `x`, the number of
# YESes is (0.5 + x/2), and the number of NOs is (1-x)/2
likelihood = {
'Y': 0.5 + hypos/2,
'N': (1-hypos)/2
}
dataset = 'Y' * 80 + 'N' * 20
posterior = prior.copy()
for data in dataset:
posterior *= likelihood[data]
posterior.normalize()
3.6945139133967024e-21
posterior.plot(label='80 YES, 20 NO')
decorate(xlabel='Proportion of cheaters',
ylabel='PMF')
Suppose you want to test whether a coin is fair, but you donβt want to spin it hundreds of times. So you make a machine that spins the coin automatically and uses computer vision to determine the outcome.
However, you discover that the machine is not always accurate. Specifically, suppose the probability is y=0.2 that an actual heads is reported as tails, or actual tails reported as heads.
In preparation for an alien invasion, the Earth Defense League (EDL) has been working on new missiles to shoot down space invaders. Of course, some missile designs are better than others; letβs assume that each design has some probability of hitting an alien ship, x.
Now suppose the new ultra-secret Alien Blaster 9000 is being tested. In a press conference, an EDL general reports that the new design has been tested twice, taking two shots during each test. The results of the test are confidential, so the general wonβt say how many targets were hit, but they report: "The same number of targets were hit in the two tests, so we have reason to think this new design is consistent."
Hint: If the probability of hitting each target is \(x\text{,}\) the probability of hitting one target in both tests is \(\left[2x(1-x)\right]^2\text{.}\)
# Here's a specific version for n=2 shots per test
x = hypos
likes = [(1-x)**4, (2*x*(1-x))**2, x**4]
likelihood = np.sum(likes, axis=0)
# Here's a more general version for any n shots per test
from scipy.stats import binom
n = 2
likes2 = [binom.pmf(k, n, x)**2 for k in range(n+1)]
likelihood2 = np.sum(likes2, axis=0)
# Here are the likelihoods, computed both ways
import matplotlib.pyplot as plt
plt.plot(x, likelihood, label='special case')
plt.plot(x, likelihood2, label='general formula')
decorate(xlabel='Probability of hitting the target',
ylabel='Likelihood',
title='Likelihood of getting the same result')
posterior.plot(label='Two tests, two shots, same outcome',
color='C4')
decorate(xlabel='Probability of hitting the target',
ylabel='PMF',
title='Posterior distribution',
ylim=[0, 0.015])
# Getting the same result in both tests is more likely for
# extreme values of `x` and least likely when `x=0.5`.
# In this example, the prior indicates that `x` is less than 0.5,
# and the update gives more weight to extreme values.
# So the dataset makes lower values of `x` more likely.