Showing preview only (3,670K chars total). Download the full file or copy to clipboard to get everything.
Repository: AllenDowney/BayesMadeSimple
Branch: master
Commit: bb42972c44ea
Files: 47
Total size: 3.5 MB
Directory structure:
gitextract_l0qxa50k/
├── 01_cookie.ipynb
├── 01_cookie_soln.ipynb
├── 02_euro.ipynb
├── 02_euro_soln.ipynb
├── 03_bandit.ipynb
├── 03_bandit_soln.ipynb
├── 03_euro.ipynb
├── 04_bandit.ipynb
├── README.md
├── _config.yml
├── bandit_soln.ipynb
├── billiards.py
├── cookie_soln.ipynb
├── debug.ipynb
├── dice.py
├── dice_soln.ipynb
├── dice_soln.py
├── distribution.py
├── empyrical_dist.py
├── environment.yml
├── euro.py
├── euro2.py
├── euro2_soln.py
├── euro_soln.ipynb
├── euro_soln.py
├── flip.ipynb
├── install_test.py
├── lincoln.py
├── sat.py
├── sat_ranks.csv
├── sat_scale.csv
├── sat_soln.py
├── thinkbayes.py
├── thinkbayes2.py
├── thinkplot.py
├── train.py
├── train2.py
├── train_soln.py
├── tutorial.md
├── volunteer.py
├── world_cup01.ipynb
├── world_cup01soln.ipynb
├── world_cup02.ipynb
├── world_cup_soln.ipynb
├── zigzag.ipynb
├── zigzag2.ipynb
└── zigzag3.ipynb
================================================
FILE CONTENTS
================================================
================================================
FILE: 01_cookie.ipynb
================================================
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Bayesian Statistics Made Simple\n",
"\n",
"Code and exercises from my workshop on Bayesian statistics in Python.\n",
"\n",
"Copyright 2020 Allen Downey\n",
"\n",
"MIT License: https://opensource.org/licenses/MIT"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"import seaborn as sns"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The cookie problem\n",
"\n",
"> Suppose you have two bowls of cookies. Bowl 1 contains 30 vanilla and 10 chocolate cookies. Bowl 2 contains 20 vanilla of each.\n",
">\n",
"> You choose one of the bowls at random and, without looking into the bowl, choose one of the cookies at random. It turns out to be a vanilla cookie.\n",
">\n",
"> What is the chance that you chose Bowl 1?\n",
"\n",
"Assume that there was an equal chance of choosing either bowl and an equal chance of choosing any cookie in the bowl.\n",
"\n",
"Here are the hypotheses and prior probabilities."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"hypos = 'Bowl 1', 'Bowl 2'\n",
"probs = 1/2, 1/2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To compute the answer, I'll use a Pandas `Series` to represent the hypotheses and their probabilities."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"prior = pd.Series(probs, hypos)\n",
"prior"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This `Series` represents a probability mass function (PMF)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we compute the likelihood of the data under each hypothesis.\n",
"\n",
"* The chance of getting a vanilla cookie from Bowl 1 is 3/4.\n",
"\n",
"* The chance of getting a vanilla cookie from Bowl 2 is 1/2."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"likelihood = 3/4, 1/2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The next step is to multiply the priors by the likelihoods:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"unnorm = prior * likelihood\n",
"unnorm"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The result is called `unnorm` because it is an \"unnormalized posterior\".\n",
"\n",
"To compute the posteriors, we have to divide through by $P(D)$, which is the sum of the unnormalized posteriors."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"prob_data = unnorm.sum()\n",
"prob_data"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Notice that we get 5/8, which is what we got by computing $P(D)$ directly.\n",
"\n",
"Now we divide by `prob_data` to get the normalized posteriors:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"posterior = unnorm / prob_data\n",
"posterior"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The posterior probability for Bowl 1 is 0.6, which is what we got using Bayes's Theorem explicitly.\n",
"\n",
"As a bonus, we also get the posterior probability of Bowl 2, which is 0.4.\n",
"\n",
"The posterior probabilities add up to 1, which they should, because the hypotheses are \"complementary\"; that is, either one of them is true or the other, but not both.\n",
"\n",
"When we add up the unnormalized posteriors and divide through, we force the posteriors to add up to 1. This process is called \"normalization\", which is why the total probability of the data is also called the \"[normalizing constant](https://en.wikipedia.org/wiki/Normalizing_constant#Bayes'_theorem)\"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Exercise 1\n",
"\n",
"Suppose we put the first cookie back, stir, draw another cookie from the same bowl, and it's a chocolate cookie. What is the probability we drew both cookies from Bowl 1?\n",
"\n",
"Hint: The prior for the second update is the posterior from the first update."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"prior2 = posterior\n",
"prior2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now \n",
"\n",
"1. Compute the likelihood of the data under each hypothesis,\n",
"2. Multiply the new prior by the likelihoods.\n",
"3. Divide through by the total probability of the data."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"# Solution goes here"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"# Solution goes here"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"# Solution goes here"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"# Solution goes here"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 101 Bowls\n",
"\n",
"Suppose instead of 2 bowls there are 101 bowls:\n",
"\n",
"* Bowl 0 contains no vanilla cookies,\n",
"\n",
"* Bowl 1 contains 1% vanilla cookies,\n",
"\n",
"* Bowl 2 contains 2% vanilla cookies,\n",
"\n",
"and so on, up to\n",
"\n",
"* Bowl 99 contains 99% vanilla cookies, and\n",
"\n",
"* Bowl 100 contains all vanilla cookies.\n",
"\n",
"As in the previous problem, there are only two kinds of cookies, vanilla and chocolate. So Bowl 0 is all chocolate cookies, Bowl 1 is 99% chocolate, and so on.\n",
"\n",
"Suppose we choose a bowl at random, choose a cookie at random, and it turns out to be vanilla. What is the probability that the cookie came from Bowl $x$, for each value of $x$?\n",
"\n",
"To represent the prior, I'll use a Pandas `Series` with 101 equally spaced quantities from 0 to 1."
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"xs = np.linspace(0, 1, num=101)\n",
"prob = 1/101\n",
"\n",
"prior = pd.Series(prob, xs)\n",
"prior.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here's what it looks like."
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"prior.plot()\n",
"\n",
"plt.xlabel('Fraction of vanilla cookies')\n",
"plt.ylabel('Probability')\n",
"plt.title('Prior');"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now that we have a prior, we need to compute likelihoods.\n",
"\n",
"Here are the likelihoods for a vanilla cookie:"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"likelihood_vanilla = xs"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And for a chocolate cookie."
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"likelihood_chocolate = 1 - xs"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To compute unnormalized posteriors, we multiply the priors and the likelihoods."
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [],
"source": [
"unnorm = prior * likelihood_vanilla"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To normalize, we divide through by the total probability of the data."
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"posterior = unnorm / unnorm.sum()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here's what the posterior looks like."
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
"posterior.plot()\n",
"\n",
"plt.xlabel('Fraction of vanilla cookies')\n",
"plt.ylabel('Probability')\n",
"plt.title('Posterior, one vanilla');"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Suppose we put the first cookie back, stir the bowl, draw from the same bowl again, and get a vanilla cookie again.\n",
"\n",
"What's are the posterior probabilities now?\n",
"\n",
"We can do another update, using the posterior from the first draw as the prior for the second draw."
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [],
"source": [
"prior2 = posterior\n",
"unnorm2 = prior2 * likelihood_vanilla\n",
"posterior2 = unnorm2 / unnorm2.sum()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And here's what it looks like."
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [],
"source": [
"posterior2.plot()\n",
"\n",
"plt.xlabel('Fraction of vanilla cookies')\n",
"plt.ylabel('Probability')\n",
"plt.title('Posterior, two vanilla');"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Exercise 2\n",
"\n",
"Suppose we put the second cookie back, stir the bowl, draw from the same bowl again, and get a chocolate cookie.\n",
"\n",
"Now what are the posterior probabilities?"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [],
"source": [
"# Solution goes here"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [],
"source": [
"# Solution goes here"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [],
"source": [
"# Solution goes here"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.5"
}
},
"nbformat": 4,
"nbformat_minor": 1
}
================================================
FILE: 01_cookie_soln.ipynb
================================================
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Bayesian Statistics Made Simple\n",
"\n",
"Code and exercises from my workshop on Bayesian statistics in Python.\n",
"\n",
"Copyright 2020 Allen Downey\n",
"\n",
"MIT License: https://opensource.org/licenses/MIT"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"import seaborn as sns"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The cookie problem\n",
"\n",
"> Suppose you have two bowls of cookies. Bowl 1 contains 30 vanilla and 10 chocolate cookies. Bowl 2 contains 20 vanilla of each.\n",
">\n",
"> You choose one of the bowls at random and, without looking into the bowl, choose one of the cookies at random. It turns out to be a vanilla cookie.\n",
">\n",
"> What is the chance that you chose Bowl 1?\n",
"\n",
"Assume that there was an equal chance of choosing either bowl and an equal chance of choosing any cookie in the bowl.\n",
"\n",
"Here are the hypotheses and prior probabilities."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"hypos = 'Bowl 1', 'Bowl 2'\n",
"probs = 1/2, 1/2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To compute the answer, I'll use a Pandas `Series` to represent the hypotheses and their probabilities."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Bowl 1 0.5\n",
"Bowl 2 0.5\n",
"dtype: float64"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"prior = pd.Series(probs, hypos)\n",
"prior"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This `Series` represents a probability mass function (PMF)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we compute the likelihood of the data under each hypothesis.\n",
"\n",
"* The chance of getting a vanilla cookie from Bowl 1 is 3/4.\n",
"\n",
"* The chance of getting a vanilla cookie from Bowl 2 is 1/2."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"likelihood = 3/4, 1/2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The next step is to multiply the priors by the likelihoods:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Bowl 1 0.375\n",
"Bowl 2 0.250\n",
"dtype: float64"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"unnorm = prior * likelihood\n",
"unnorm"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The result is called `unnorm` because it is an \"unnormalized posterior\".\n",
"\n",
"To compute the posteriors, we have to divide through by $P(D)$, which is the sum of the unnormalized posteriors."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.625"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"prob_data = unnorm.sum()\n",
"prob_data"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Notice that we get 5/8, which is what we got by computing $P(D)$ directly.\n",
"\n",
"Now we divide by `prob_data` to get the normalized posteriors:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Bowl 1 0.6\n",
"Bowl 2 0.4\n",
"dtype: float64"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"posterior = unnorm / prob_data\n",
"posterior"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The posterior probability for Bowl 1 is 0.6, which is what we got using Bayes's Theorem explicitly.\n",
"\n",
"As a bonus, we also get the posterior probability of Bowl 2, which is 0.4.\n",
"\n",
"The posterior probabilities add up to 1, which they should, because the hypotheses are \"complementary\"; that is, either one of them is true or the other, but not both.\n",
"\n",
"When we add up the unnormalized posteriors and divide through, we force the posteriors to add up to 1. This process is called \"normalization\", which is why the total probability of the data is also called the \"[normalizing constant](https://en.wikipedia.org/wiki/Normalizing_constant#Bayes'_theorem)\"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Exercise 1\n",
"\n",
"Suppose we put the first cookie back, stir, draw another cookie from the same bowl, and it's a chocolate cookie. What is the probability we drew both cookies from Bowl 1?\n",
"\n",
"Hint: The prior for the second update is the posterior from the first update."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Bowl 1 0.6\n",
"Bowl 2 0.4\n",
"dtype: float64"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"prior2 = posterior\n",
"prior2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now \n",
"\n",
"1. Compute the likelihood of the data under each hypothesis,\n",
"2. Multiply the new prior by the likelihoods.\n",
"3. Divide through by the total probability of the data."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"# Solution\n",
"\n",
"likelihood2 = 1/4, 1/2"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Bowl 1 0.15\n",
"Bowl 2 0.20\n",
"dtype: float64"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Solution\n",
"\n",
"unnorm2 = prior2 * likelihood2\n",
"unnorm2"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.35"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Solution\n",
"\n",
"prob_data2 = unnorm2.sum()\n",
"prob_data2"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Bowl 1 0.428571\n",
"Bowl 2 0.571429\n",
"dtype: float64"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Solution\n",
"\n",
"posterior2 = unnorm2 / prob_data2\n",
"posterior2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 101 Bowls\n",
"\n",
"Suppose instead of 2 bowls there are 101 bowls:\n",
"\n",
"* Bowl 0 contains no vanilla cookies,\n",
"\n",
"* Bowl 1 contains 1% vanilla cookies,\n",
"\n",
"* Bowl 2 contains 2% vanilla cookies,\n",
"\n",
"and so on, up to\n",
"\n",
"* Bowl 99 contains 99% vanilla cookies, and\n",
"\n",
"* Bowl 100 contains all vanilla cookies.\n",
"\n",
"As in the previous problem, there are only two kinds of cookies, vanilla and chocolate. So Bowl 0 is all chocolate cookies, Bowl 1 is 99% chocolate, and so on.\n",
"\n",
"Suppose we choose a bowl at random, choose a cookie at random, and it turns out to be vanilla. What is the probability that the cookie came from Bowl $x$, for each value of $x$?\n",
"\n",
"To represent the prior, I'll use a Pandas `Series` with 101 equally spaced quantities from 0 to 1."
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.00 0.009901\n",
"0.01 0.009901\n",
"0.02 0.009901\n",
"0.03 0.009901\n",
"0.04 0.009901\n",
"dtype: float64"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"xs = np.linspace(0, 1, num=101)\n",
"prob = 1/101\n",
"\n",
"prior = pd.Series(prob, xs)\n",
"prior.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here's what it looks like."
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"prior.plot()\n",
"\n",
"plt.xlabel('Fraction of vanilla cookies')\n",
"plt.ylabel('Probability')\n",
"plt.title('Prior');"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now that we have a prior, we need to compute likelihoods.\n",
"\n",
"Here are the likelihoods for a vanilla cookie:"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"likelihood_vanilla = xs"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And for a chocolate cookie."
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"likelihood_chocolate = 1 - xs"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To compute unnormalized posteriors, we multiply the priors and the likelihoods."
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [],
"source": [
"unnorm = prior * likelihood_vanilla"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To normalize, we divide through by the total probability of the data."
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"posterior = unnorm / unnorm.sum()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here's what the posterior looks like."
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"posterior.plot()\n",
"\n",
"plt.xlabel('Fraction of vanilla cookies')\n",
"plt.ylabel('Probability')\n",
"plt.title('Posterior, one vanilla');"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Suppose we put the first cookie back, stir the bowl, draw from the same bowl again, and get a vanilla cookie again.\n",
"\n",
"What's are the posterior probabilities now?\n",
"\n",
"We can do another update, using the posterior from the first draw as the prior for the second draw."
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [],
"source": [
"prior2 = posterior\n",
"unnorm2 = prior2 * likelihood_vanilla\n",
"posterior2 = unnorm2 / unnorm2.sum()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And here's what it looks like."
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"posterior2.plot()\n",
"\n",
"plt.xlabel('Fraction of vanilla cookies')\n",
"plt.ylabel('Probability')\n",
"plt.title('Posterior, two vanilla');"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Exercise 2\n",
"\n",
"Suppose we put the second cookie back, stir the bowl, draw from the same bowl again, and get a chocolate cookie.\n",
"\n",
"Now what are the posterior probabilities?"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [],
"source": [
"# Solution\n",
"\n",
"prior3 = posterior2\n",
"unnorm3 = prior3 * likelihood_chocolate\n",
"posterior3 = unnorm3 / unnorm3.sum()"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"# Solution\n",
"\n",
"posterior3.plot()\n",
"\n",
"plt.xlabel('Fraction of vanilla cookies')\n",
"plt.ylabel('Probability')\n",
"plt.title('Posterior, two vanilla, one chocolate');"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.67"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Solution\n",
"\n",
"posterior3.idxmax()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.5"
}
},
"nbformat": 4,
"nbformat_minor": 1
}
================================================
FILE: 02_euro.ipynb
================================================
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Bayesian Statistics Made Simple\n",
"\n",
"Code and exercises from my workshop on Bayesian statistics in Python.\n",
"\n",
"Copyright 2020 Allen Downey\n",
"\n",
"MIT License: https://opensource.org/licenses/MIT"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"import seaborn as sns"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The Euro problem\n",
"\n",
"Here's a problem from David MacKay's book, [*Information Theory, Inference, and Learning Algorithms*](http://www.inference.org.uk/mackay/itila/p0.html), which is the book where I first learned about Bayesian statistics. MacKay writes:\n",
"\n",
"> A statistical statement appeared in The Guardian on\n",
"Friday January 4, 2002:\n",
">\n",
"> >\"When spun on edge 250 times, a Belgian one-euro coin came\n",
"up heads 140 times and tails 110. ‘It looks very suspicious\n",
"to me’, said Barry Blight, a statistics lecturer at the London\n",
"School of Economics. ‘If the coin were unbiased the chance of\n",
"getting a result as extreme as that would be less than 7%’.\"\n",
">\n",
"> But [asks MacKay] do these data give evidence that the coin is biased rather than fair?\n",
"\n",
"To answer this question, we have to make some modeling choices.\n",
"\n",
"First, let's assume that if you spin a coin on edge, there is some probability that it will land heads up. I'll call that probability $x$.\n",
"\n",
"Second, let's assume that $x$ varies from one coin to the next, depending on how the coin is balanced and maybe some other factors."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"With these assumptions we can formulate MacKay's question as an inference problem: given the data --- 140 heads and 110 tails --- what do we think $x$ is for this coin?\n",
"\n",
"This formulation is similar to the 101 Bowls problem we saw in the previous notebook.\n",
"\n",
"But in the 101 Bowls problem, we are told that we choose a bowl at random, which implies that all bowls have the same prior probability.\n",
"\n",
"For the Euro problem, we have to think harder about the prior. What values of $x$ do you think are reasonable?\n",
"\n",
"It seems likely that many coins are \"fair\", meaning that the probability of heads is close to 50%. Do you think there are coins where $x$ is 75%? How about 90%?\n",
"\n",
"To be honest, I don't really know. To get started, I will assume that all values of $x$, from 0% to 100%, are equally likely. Then we'll come back and try another prior.\n",
"\n",
"Here's a uniform prior from 0 to 100."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"xs = np.linspace(0, 1, num=101)\n",
"p = 1/101\n",
"prior = pd.Series(p, index=xs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And here's what it looks like."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"prior.plot()\n",
"\n",
"plt.xlabel('Possible values of x')\n",
"plt.ylabel('Probability')\n",
"plt.title('Prior');"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here are the likelihoods for heads and tails:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"likelihood_heads = xs\n",
"likelihood_tails = 1 - xs"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Suppose we toss the coin twice and get one heads and one tails.\n",
"\n",
"We can compute the posterior probability for each value of $x$ like this:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"posterior = prior * likelihood_heads * likelihood_tails\n",
"posterior /= posterior.sum()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And here's what the posterior distribution looks like."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"posterior.plot()\n",
"\n",
"plt.xlabel('Possible values of x')\n",
"plt.ylabel('Probability')\n",
"plt.title('Posterior')\n",
"\n",
"posterior.idxmax()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Exercise 1\n",
"\n",
"Go back and run the update again for the following outcomes:\n",
"\n",
"* Two heads, one tails.\n",
"\n",
"* 7 heads, 3 tails.\n",
"\n",
"* 70 heads, 30 tails.\n",
"\n",
"* 140 heads, 110 tails."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## A better prior\n",
"\n",
"Remember that this result is based on a uniform prior, which assumes that any value of $x$ from 0 to 100 is equally likely.\n",
"\n",
"Given what we know about coins, that's probably not true. I can believe that if you spin a lop-sided coin on edge, it might be somewhat more likely to land on heads or tails. \n",
"\n",
"But unless the coin is heavily weighted on one side, I would be surprised if $x$ were greater than 60% or less than 40%.\n",
"\n",
"Of course, I could be wrong, but in general I would expect to find $x$ closer to 50%, and I would be surprised to find it near 0% or 100%.\n",
"\n",
"We can represent that prior belief with a triangle-shaped prior.\n",
"Here's an array that ramps up from 0 to 49 and ramps down from 50 to 0."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"ramp_up = np.arange(50)\n",
"ramp_down = np.arange(50, -1, -1)\n",
"\n",
"ps = np.append(ramp_up, ramp_down)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I'll put it in a `Series` and normalize it so it adds up to 1."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"triangle = pd.Series(ps, xs)\n",
"triangle /= triangle.sum()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here's what the triangle prior looks like."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"triangle.plot(color='C1')\n",
"\n",
"plt.xlabel('Possible values of x')\n",
"plt.ylabel('Probability')\n",
"plt.title('Triangle prior');"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now let's update it with the data."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"posterior1 = prior * likelihood_heads**140 * likelihood_tails**110\n",
"posterior1 /= posterior1.sum()"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"posterior2 = triangle * likelihood_heads**140 * likelihood_tails**110\n",
"posterior2 /= posterior2.sum()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And plot the results, along with the posterior based on a uniform prior."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"posterior1.plot(label='Uniform prior')\n",
"posterior2.plot(label='Triangle prior')\n",
"\n",
"plt.xlabel('Possible values of x')\n",
"plt.ylabel('Probability')\n",
"plt.title('Posterior after 140 heads, 110 tails')\n",
"plt.legend();"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The posterior distributions are almost identical because, in this case, we have enough data to \"swamp the prior\"; that is, the posteriors depend strongly on the data and only weakly on the priors.\n",
"\n",
"This is good news, because it suggests that we can use data to resolve arguments. Suppose two people disagree about the correct prior. If neither can persuade the other, they might have to agree to disagree.\n",
"\n",
"But if they get new data, and each of them does a Bayesian update, they will usually find their beliefs converging.\n",
"\n",
"And with enough data, the remaining difference can be so small that it makes no difference in practice."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Summarizing the posterior distribution\n",
"\n",
"The posterior distribution contains all of the information we have about the value of $x$. But sometimes we want to summarize this information.\n",
"\n",
"We have already seen one way to summarize a posterior distribution, the Maximum Aposteori Probability, or MAP:"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"posterior1.idxmax()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`idxmax` returns the value of $x$ with the highest probability.\n",
"\n",
"In this example, we get the same MAP with the triangle prior:"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"posterior2.idxmax()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Another way to summarize the posterior distribution is the posterior mean.\n",
"\n",
"Given a set of values, $x_i$, and the corresponding probabilities, $p_i$, the mean of the distribution is:\n",
"\n",
"$\\sum_i x_i p_i$\n",
"\n",
"The following function takes a Pmf and computes its mean. Note that this function only works correctly if the Pmf is normalized."
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"def pmf_mean(pmf):\n",
" \"\"\"Compute the mean of a PMF.\n",
" \n",
" pmf: Series representing a PMF\n",
" \n",
" return: float\n",
" \"\"\"\n",
" return np.sum(pmf.index * pmf)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here's the posterior mean based on the uniform prior:"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"pmf_mean(posterior1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And here's the posterior mean with the triangle prior:"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [],
"source": [
"pmf_mean(posterior2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The posterior means are not identical, but they are close enough that the difference probably doesn't matter.\n",
"\n",
"In this example, the posterior mean is very close to the MAP. That's true when the posterior distribution is symmetric, but it is not always true."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If someone asks what we think $x$ is, the MAP or the posterior mean might be a good answer."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Credible intervals\n",
"\n",
"Another way to summarize a posterior distribution is a credible interval, which is a range of quantities whose probabilities add up to a given total.\n",
"\n",
"The following function takes a `Series` as a parameter and a probability, `prob`, and return an interval that contains the given probability.\n",
"\n",
"If you are interested, it computes the cumulative distribution function (CDF) and then uses interpolation to estimate percentiles."
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"from scipy.interpolate import interp1d\n",
"\n",
"def credible_interval(pmf, prob):\n",
" \"\"\"Compute the mean of a PMF.\n",
" \n",
" pmf: Series representing a PMF\n",
" prob: probability of the interval\n",
" \n",
" return: pair of float\n",
" \"\"\"\n",
" # make the CDF\n",
" xs = pmf.index\n",
" ys = pmf.cumsum()\n",
" \n",
" # compute the probabilities\n",
" p = (1-prob)/2\n",
" ps = [p, 1-p]\n",
" \n",
" # interpolate the inverse CDF\n",
" options = dict(bounds_error=False,\n",
" fill_value=(xs[0], xs[-1]), \n",
" assume_sorted=True)\n",
" interp = interp1d(ys, xs, **options)\n",
" return interp(ps)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here's the 90% credible interval for `posterior1`."
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
"credible_interval(posterior1, 0.9)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And for `posterior2`."
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [],
"source": [
"credible_interval(posterior2, 0.9)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The credible interval for `posterior2` is slightly narrower."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.5"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
================================================
FILE: 02_euro_soln.ipynb
================================================
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Bayesian Statistics Made Simple\n",
"\n",
"Code and exercises from my workshop on Bayesian statistics in Python.\n",
"\n",
"Copyright 2020 Allen Downey\n",
"\n",
"MIT License: https://opensource.org/licenses/MIT"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"import seaborn as sns"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The Euro problem\n",
"\n",
"Here's a problem from David MacKay's book, [*Information Theory, Inference, and Learning Algorithms*](http://www.inference.org.uk/mackay/itila/p0.html), which is the book where I first learned about Bayesian statistics. MacKay writes:\n",
"\n",
"> A statistical statement appeared in The Guardian on\n",
"Friday January 4, 2002:\n",
">\n",
"> >\"When spun on edge 250 times, a Belgian one-euro coin came\n",
"up heads 140 times and tails 110. ‘It looks very suspicious\n",
"to me’, said Barry Blight, a statistics lecturer at the London\n",
"School of Economics. ‘If the coin were unbiased the chance of\n",
"getting a result as extreme as that would be less than 7%’.\"\n",
">\n",
"> But [asks MacKay] do these data give evidence that the coin is biased rather than fair?\n",
"\n",
"To answer this question, we have to make some modeling choices.\n",
"\n",
"First, let's assume that if you spin a coin on edge, there is some probability that it will land heads up. I'll call that probability $x$.\n",
"\n",
"Second, let's assume that $x$ varies from one coin to the next, depending on how the coin is balanced and maybe some other factors."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"With these assumptions we can formulate MacKay's question as an inference problem: given the data --- 140 heads and 110 tails --- what do we think $x$ is for this coin?\n",
"\n",
"This formulation is similar to the 101 Bowls problem we saw in the previous notebook.\n",
"\n",
"But in the 101 Bowls problem, we are told that we choose a bowl at random, which implies that all bowls have the same prior probability.\n",
"\n",
"For the Euro problem, we have to think harder about the prior. What values of $x$ do you think are reasonable?\n",
"\n",
"It seems likely that many coins are \"fair\", meaning that the probability of heads is close to 50%. Do you think there are coins where $x$ is 75%? How about 90%?\n",
"\n",
"To be honest, I don't really know. To get started, I will assume that all values of $x$, from 0% to 100%, are equally likely. Then we'll come back and try another prior.\n",
"\n",
"Here's a uniform prior from 0 to 100."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"xs = np.linspace(0, 1, num=101)\n",
"p = 1/101\n",
"prior = pd.Series(p, index=xs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And here's what it looks like."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"prior.plot()\n",
"\n",
"plt.xlabel('Possible values of x')\n",
"plt.ylabel('Probability')\n",
"plt.title('Prior');"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here are the likelihoods for heads and tails:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"likelihood_heads = xs\n",
"likelihood_tails = 1 - xs"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Suppose we toss the coin twice and get one heads and one tails.\n",
"\n",
"We can compute the posterior probability for each value of $x$ like this:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"posterior = prior * likelihood_heads * likelihood_tails\n",
"posterior /= posterior.sum()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And here's what the posterior distribution looks like."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.5"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"posterior.plot()\n",
"\n",
"plt.xlabel('Possible values of x')\n",
"plt.ylabel('Probability')\n",
"plt.title('Posterior')\n",
"\n",
"posterior.idxmax()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Exercise 1\n",
"\n",
"Go back and run the update again for the following outcomes:\n",
"\n",
"* Two heads, one tails.\n",
"\n",
"* 7 heads, 3 tails.\n",
"\n",
"* 70 heads, 30 tails.\n",
"\n",
"* 140 heads, 110 tails."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## A better prior\n",
"\n",
"Remember that this result is based on a uniform prior, which assumes that any value of $x$ from 0 to 100 is equally likely.\n",
"\n",
"Given what we know about coins, that's probably not true. I can believe that if you spin a lop-sided coin on edge, it might be somewhat more likely to land on heads or tails. \n",
"\n",
"But unless the coin is heavily weighted on one side, I would be surprised if $x$ were greater than 60% or less than 40%.\n",
"\n",
"Of course, I could be wrong, but in general I would expect to find $x$ closer to 50%, and I would be surprised to find it near 0% or 100%.\n",
"\n",
"We can represent that prior belief with a triangle-shaped prior.\n",
"Here's an array that ramps up from 0 to 49 and ramps down from 50 to 0."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"ramp_up = np.arange(50)\n",
"ramp_down = np.arange(50, -1, -1)\n",
"\n",
"ps = np.append(ramp_up, ramp_down)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I'll put it in a `Series` and normalize it so it adds up to 1."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"triangle = pd.Series(ps, xs)\n",
"triangle /= triangle.sum()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here's what the triangle prior looks like."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"triangle.plot(color='C1')\n",
"\n",
"plt.xlabel('Possible values of x')\n",
"plt.ylabel('Probability')\n",
"plt.title('Triangle prior');"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now let's update it with the data."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"posterior1 = prior * likelihood_heads**140 * likelihood_tails**110\n",
"posterior1 /= posterior1.sum()"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"posterior2 = triangle * likelihood_heads**140 * likelihood_tails**110\n",
"posterior2 /= posterior2.sum()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And plot the results, along with the posterior based on a uniform prior."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"posterior1.plot(label='Uniform prior')\n",
"posterior2.plot(label='Triangle prior')\n",
"\n",
"plt.xlabel('Possible values of x')\n",
"plt.ylabel('Probability')\n",
"plt.title('Posterior after 140 heads, 110 tails')\n",
"plt.legend();"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The posterior distributions are almost identical because, in this case, we have enough data to \"swamp the prior\"; that is, the posteriors depend strongly on the data and only weakly on the priors.\n",
"\n",
"This is good news, because it suggests that we can use data to resolve arguments. Suppose two people disagree about the correct prior. If neither can persuade the other, they might have to agree to disagree.\n",
"\n",
"But if they get new data, and each of them does a Bayesian update, they will usually find their beliefs converging.\n",
"\n",
"And with enough data, the remaining difference can be so small that it makes no difference in practice."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Summarizing the posterior distribution\n",
"\n",
"The posterior distribution contains all of the information we have about the value of $x$. But sometimes we want to summarize this information.\n",
"\n",
"We have already seen one way to summarize a posterior distribution, the Maximum Aposteori Probability, or MAP:"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.56"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"posterior1.idxmax()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`idxmax` returns the value of $x$ with the highest probability.\n",
"\n",
"In this example, we get the same MAP with the triangle prior:"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.56"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"posterior2.idxmax()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Another way to summarize the posterior distribution is the posterior mean.\n",
"\n",
"Given a set of values, $x_i$, and the corresponding probabilities, $p_i$, the mean of the distribution is:\n",
"\n",
"$\\sum_i x_i p_i$\n",
"\n",
"The following function takes a Pmf and computes its mean. Note that this function only works correctly if the Pmf is normalized."
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"def pmf_mean(pmf):\n",
" \"\"\"Compute the mean of a PMF.\n",
" \n",
" pmf: Series representing a PMF\n",
" \n",
" return: float\n",
" \"\"\"\n",
" return np.sum(pmf.index * pmf)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here's the posterior mean based on the uniform prior:"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.5595238095238096"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pmf_mean(posterior1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And here's the posterior mean with the triangle prior:"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.5574349943859507"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pmf_mean(posterior2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The posterior means are not identical, but they are close enough that the difference probably doesn't matter.\n",
"\n",
"In this example, the posterior mean is very close to the MAP. That's true when the posterior distribution is symmetric, but it is not always true."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If someone asks what we think $x$ is, the MAP or the posterior mean might be a good answer."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Credible intervals\n",
"\n",
"Another way to summarize a posterior distribution is a credible interval, which is a range of quantities whose probabilities add up to a given total.\n",
"\n",
"The following function takes a `Series` as a parameter and a probability, `prob`, and return an interval that contains the given probability.\n",
"\n",
"If you are interested, it computes the cumulative distribution function (CDF) and then uses interpolation to estimate percentiles."
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"from scipy.interpolate import interp1d\n",
"\n",
"def credible_interval(pmf, prob):\n",
" \"\"\"Compute the mean of a PMF.\n",
" \n",
" pmf: Series representing a PMF\n",
" prob: probability of the interval\n",
" \n",
" return: pair of float\n",
" \"\"\"\n",
" # make the CDF\n",
" xs = pmf.index\n",
" ys = pmf.cumsum()\n",
" \n",
" # compute the probabilities\n",
" p = (1-prob)/2\n",
" ps = [p, 1-p]\n",
" \n",
" # interpolate the inverse CDF\n",
" options = dict(bounds_error=False,\n",
" fill_value=(xs[0], xs[-1]), \n",
" assume_sorted=True)\n",
" interp = interp1d(ys, xs, **options)\n",
" return interp(ps)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here's the 90% credible interval for `posterior1`."
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([0.50259405, 0.60603433])"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"credible_interval(posterior1, 0.9)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And for `posterior2`."
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([0.50114608, 0.60373672])"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"credible_interval(posterior2, 0.9)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The credible interval for `posterior2` is slightly narrower."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.5"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
================================================
FILE: 03_bandit.ipynb
================================================
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Bayesian Statistics Made Simple\n",
"\n",
"Code and exercises from my workshop on Bayesian statistics in Python.\n",
"\n",
"Copyright 2020 Allen Downey\n",
"\n",
"MIT License: https://opensource.org/licenses/MIT"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"import seaborn as sns"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The Bayesian bandit problem\n",
"\n",
"Suppose you have several \"one-armed bandit\" slot machines, and there's reason to think that they have different probabilities of paying off.\n",
"\n",
"Each time you play a machine, you either win or lose, and you can use the outcome to update your belief about the probability of winning.\n",
"\n",
"Then, to decide which machine to play next, you can use the \"Bayesian bandit\" strategy, explained below.\n",
"\n",
"First, let's see how to do the update."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The prior\n",
"\n",
"If we know nothing about the probability of wining, we can start with a uniform prior."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"xs = np.linspace(0, 1, 101)\n",
"prior = pd.Series(1/101, index=xs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here's what it looks like."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"def decorate_bandit(title):\n",
" \"\"\"Labels the axes.\n",
" \n",
" title: string\n",
" \"\"\"\n",
" plt.xlabel('Probability of winning')\n",
" plt.ylabel('PMF')\n",
" plt.title(title)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"prior.plot()\n",
"decorate_bandit('Prior distribution')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The update\n",
"\n",
"The following function takes a prior distribution and an outcome, either `'W'` or `'L'`.\n",
"\n",
"It does a Bayesian update in place; that is, it modifies the distribution based on the outcome."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"def update(pmf, data):\n",
" \"\"\"Likelihood function for Bayesian bandit\n",
" \n",
" pmf: Series that maps hypotheses to probabilities\n",
" data: string, either 'W' or 'L'\n",
" \"\"\"\n",
" xs = pmf.index\n",
" if data == 'W':\n",
" pmf *= xs\n",
" else:\n",
" pmf *= 1-xs\n",
" \n",
" pmf /= pmf.sum()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here's an example that starts with a uniform prior and updates with one win and one loss."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"bandit = prior.copy()\n",
"update(bandit, 'W')\n",
"update(bandit, 'L')\n",
"bandit.plot()\n",
"decorate_bandit('Posterior distribution, 1 loss, 1 win')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Exercise 1\n",
"\n",
"Suppose you play a machine 10 times and win once. What is the posterior distribution of $x$?"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"# Solution goes here"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Multiple bandits"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now suppose we have several bandits and we want to decide which one to play.\n",
"\n",
"For this example, we have 4 machines with these probabilities:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"actual_probs = [0.10, 0.20, 0.30, 0.40]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The function `play` simulates playing one machine once and returns `W` or `L`."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"from collections import Counter\n",
"\n",
"# count how ma
gitextract_l0qxa50k/ ├── 01_cookie.ipynb ├── 01_cookie_soln.ipynb ├── 02_euro.ipynb ├── 02_euro_soln.ipynb ├── 03_bandit.ipynb ├── 03_bandit_soln.ipynb ├── 03_euro.ipynb ├── 04_bandit.ipynb ├── README.md ├── _config.yml ├── bandit_soln.ipynb ├── billiards.py ├── cookie_soln.ipynb ├── debug.ipynb ├── dice.py ├── dice_soln.ipynb ├── dice_soln.py ├── distribution.py ├── empyrical_dist.py ├── environment.yml ├── euro.py ├── euro2.py ├── euro2_soln.py ├── euro_soln.ipynb ├── euro_soln.py ├── flip.ipynb ├── install_test.py ├── lincoln.py ├── sat.py ├── sat_ranks.csv ├── sat_scale.csv ├── sat_soln.py ├── thinkbayes.py ├── thinkbayes2.py ├── thinkplot.py ├── train.py ├── train2.py ├── train_soln.py ├── tutorial.md ├── volunteer.py ├── world_cup01.ipynb ├── world_cup01soln.ipynb ├── world_cup02.ipynb ├── world_cup_soln.ipynb ├── zigzag.ipynb ├── zigzag2.ipynb └── zigzag3.ipynb
SYMBOL INDEX (744 symbols across 20 files)
FILE: billiards.py
class Billiards (line 28) | class Billiards(thinkbayes.Suite):
method Likelihood (line 30) | def Likelihood(self, data, hypo):
function ProbWinMatch (line 42) | def ProbWinMatch(pmf):
function main (line 49) | def main():
FILE: dice.py
class Dice (line 13) | class Dice(Suite):
method Likelihood (line 16) | def Likelihood(self, data, hypo):
function main (line 26) | def main():
FILE: dice_soln.py
class Dice (line 13) | class Dice(Suite):
method Likelihood (line 16) | def Likelihood(self, data, hypo):
function main (line 28) | def main():
FILE: distribution.py
function underride (line 19) | def underride(d, **options):
class Pmf (line 33) | class Pmf(pd.Series):
method __init__ (line 36) | def __init__(self, *args, **kwargs):
method copy (line 49) | def copy(self, **kwargs):
method __getitem__ (line 56) | def __getitem__(self, qs):
method qs (line 64) | def qs(self):
method ps (line 72) | def ps(self):
method _repr_html_ (line 79) | def _repr_html_(self):
method normalize (line 87) | def normalize(self):
method mean (line 96) | def mean(self):
method median (line 104) | def median(self):
method quantile (line 111) | def quantile(self, ps):
method var (line 121) | def var(self):
method std (line 130) | def std(self):
method sample (line 137) | def sample(self, *args, **kwargs):
method choice (line 149) | def choice(self, *args, **kwargs):
method bar (line 162) | def bar(self, **options):
method __add__ (line 170) | def __add__(self, x):
method __sub__ (line 184) | def __sub__(self, x):
method make_joint (line 201) | def make_joint(self, other, **options):
method marginal (line 214) | def marginal(self, i, name=None):
method conditional (line 228) | def conditional(self, i, j, val, name=None):
method update (line 249) | def update(self, likelihood, data):
method max_prob (line 263) | def max_prob(self):
method make_cdf (line 270) | def make_cdf(self, normalize=True):
method quantile (line 283) | def quantile(self, ps):
method credible_interval (line 299) | def credible_interval(self, p):
method from_seq (line 311) | def from_seq(seq, normalize=True, sort=True, **options):
method gt (line 336) | def gt(self, x):
method lt (line 350) | def lt(self, x):
method ge (line 364) | def ge(self, x):
method le (line 378) | def le(self, x):
method eq (line 392) | def eq(self, x):
method ne (line 406) | def ne(self, x):
function pmf_conv (line 421) | def pmf_conv(pmf1, pmf2, ufunc):
function pmf_add (line 436) | def pmf_add(pmf1, pmf2):
function pmf_sub (line 447) | def pmf_sub(pmf1, pmf2):
function pmf_outer (line 458) | def pmf_outer(pmf1, pmf2, ufunc):
function pmf_gt (line 472) | def pmf_gt(pmf1, pmf2):
function pmf_lt (line 484) | def pmf_lt(pmf1, pmf2):
function pmf_ge (line 496) | def pmf_ge(pmf1, pmf2):
function pmf_le (line 508) | def pmf_le(pmf1, pmf2):
function pmf_eq (line 520) | def pmf_eq(pmf1, pmf2):
function pmf_ne (line 532) | def pmf_ne(pmf1, pmf2):
class Cdf (line 544) | class Cdf(pd.Series):
method __init__ (line 547) | def __init__(self, *args, **kwargs):
method copy (line 560) | def copy(self, **kwargs):
method forward (line 568) | def forward(self):
method inverse (line 578) | def inverse(self):
method from_seq (line 594) | def from_seq(seq, normalize=True, sort=True, **options):
method qs (line 608) | def qs(self):
method ps (line 616) | def ps(self):
method _repr_html_ (line 623) | def _repr_html_(self):
method normalize (line 631) | def normalize(self):
method make_pmf (line 640) | def make_pmf(self, normalize=False):
method choice (line 652) | def choice(self, *args, **kwargs):
method mean (line 666) | def mean(self):
method var (line 673) | def var(self):
method std (line 680) | def std(self):
method median (line 687) | def median(self):
FILE: empyrical_dist.py
function underride (line 19) | def underride(d, **options):
class Pmf (line 33) | class Pmf(pd.Series):
method __init__ (line 36) | def __init__(self, *args, **kwargs):
method copy (line 49) | def copy(self, deep=True):
method __getitem__ (line 56) | def __getitem__(self, qs):
method qs (line 64) | def qs(self):
method ps (line 72) | def ps(self):
method _repr_html_ (line 79) | def _repr_html_(self):
method normalize (line 87) | def normalize(self):
method mean (line 96) | def mean(self):
method median (line 105) | def median(self):
method quantile (line 112) | def quantile(self, ps, **kwargs):
method var (line 122) | def var(self):
method std (line 131) | def std(self):
method choice (line 138) | def choice(self, *args, **kwargs):
method sample (line 151) | def sample(self, *args, **kwargs):
method plot (line 170) | def plot(self, **options):
method bar (line 179) | def bar(self, **options):
method add (line 187) | def add(self, x):
method sub (line 202) | def sub(self, x):
method rsub (line 217) | def rsub(self, x):
method mul (line 231) | def mul(self, x):
method div (line 247) | def div(self, x):
method rdiv (line 263) | def rdiv(self, x):
method make_joint (line 278) | def make_joint(self, other, **options):
method marginal (line 291) | def marginal(self, i, name=None):
method conditional (line 305) | def conditional(self, i, j, val, name=None):
method update (line 326) | def update(self, likelihood, data):
method max_prob (line 340) | def max_prob(self):
method make_cdf (line 347) | def make_cdf(self, normalize=True):
method quantile (line 360) | def quantile(self, ps):
method credible_interval (line 370) | def credible_interval(self, p):
method from_seq (line 382) | def from_seq(seq, normalize=True, sort=True, **options):
method gt (line 407) | def gt(self, x):
method lt (line 421) | def lt(self, x):
method ge (line 435) | def ge(self, x):
method le (line 449) | def le(self, x):
method eq (line 463) | def eq(self, x):
method ne (line 477) | def ne(self, x):
function pmf_conv (line 492) | def pmf_conv(pmf1, pmf2, ufunc):
function pmf_add (line 507) | def pmf_add(pmf1, pmf2):
function pmf_sub (line 518) | def pmf_sub(pmf1, pmf2):
function pmf_mul (line 529) | def pmf_mul(pmf1, pmf2):
function pmf_div (line 539) | def pmf_div(pmf1, pmf2):
function pmf_outer (line 549) | def pmf_outer(pmf1, pmf2, ufunc):
function pmf_gt (line 563) | def pmf_gt(pmf1, pmf2):
function pmf_lt (line 575) | def pmf_lt(pmf1, pmf2):
function pmf_ge (line 587) | def pmf_ge(pmf1, pmf2):
function pmf_le (line 599) | def pmf_le(pmf1, pmf2):
function pmf_eq (line 611) | def pmf_eq(pmf1, pmf2):
function pmf_ne (line 623) | def pmf_ne(pmf1, pmf2):
class Cdf (line 635) | class Cdf(pd.Series):
method __init__ (line 638) | def __init__(self, *args, **kwargs):
method copy (line 651) | def copy(self, deep=True):
method from_seq (line 659) | def from_seq(seq, normalize=True, sort=True, **options):
method qs (line 673) | def qs(self):
method ps (line 681) | def ps(self):
method _repr_html_ (line 688) | def _repr_html_(self):
method plot (line 696) | def plot(self, **options):
method step (line 705) | def step(self, **options):
method normalize (line 714) | def normalize(self):
method forward (line 724) | def forward(self, **kwargs):
method inverse (line 742) | def inverse(self, **kwargs):
method make_pmf (line 764) | def make_pmf(self, normalize=False):
method choice (line 776) | def choice(self, *args, **kwargs):
method sample (line 790) | def sample(self, *args, **kwargs):
method mean (line 808) | def mean(self):
method var (line 815) | def var(self):
method std (line 822) | def std(self):
method median (line 829) | def median(self):
FILE: euro.py
class Euro (line 31) | class Euro(thinkbayes.Suite):
method Likelihood (line 33) | def Likelihood(self, data, hypo):
function main (line 43) | def main():
FILE: euro2.py
class Euro (line 31) | class Euro(thinkbayes.Suite):
method Likelihood (line 33) | def Likelihood(self, data, hypo):
function AverageLikelihood (line 45) | def AverageLikelihood(suite, data):
function main (line 64) | def main():
FILE: euro2_soln.py
class Euro (line 31) | class Euro(thinkbayes.Suite):
method Likelihood (line 33) | def Likelihood(self, data, hypo):
function AverageLikelihood (line 45) | def AverageLikelihood(suite, data):
function main (line 64) | def main():
FILE: euro_soln.py
class Euro (line 31) | class Euro(thinkbayes.Suite):
method Likelihood (line 33) | def Likelihood(self, data, hypo):
function main (line 46) | def main():
FILE: install_test.py
function RenderPdf (line 19) | def RenderPdf(mu, sigma, n=101):
function main (line 29) | def main():
FILE: lincoln.py
function choose (line 53) | def choose(n, k, d={}):
function binom (line 76) | def binom(k, n, p):
class Lincoln (line 86) | class Lincoln(thinkbayes.Suite, thinkbayes.Joint):
method Likelihood (line 89) | def Likelihood(self, data, hypo):
function main (line 103) | def main():
FILE: sat.py
function ReadScale (line 16) | def ReadScale(filename='sat_scale.csv', col=2):
function ReadRanks (line 48) | def ReadRanks(filename='sat_ranks.csv'):
function DivideValues (line 72) | def DivideValues(pmf, denom):
class Exam (line 85) | class Exam(object):
method __init__ (line 91) | def __init__(self):
method Lookup (line 101) | def Lookup(self, raw):
method Reverse (line 105) | def Reverse(self, score):
method ReverseScale (line 113) | def ReverseScale(self, pmf):
class Sat (line 130) | class Sat(thinkbayes.Suite):
method __init__ (line 133) | def __init__(self, exam):
method Likelihood (line 142) | def Likelihood(self, data, hypo):
function PmfProbGreater (line 153) | def PmfProbGreater(pmf1, pmf2):
function main (line 172) | def main():
FILE: sat_soln.py
function ReadScale (line 16) | def ReadScale(filename='sat_scale.csv', col=2):
function ReadRanks (line 48) | def ReadRanks(filename='sat_ranks.csv'):
function DivideValues (line 72) | def DivideValues(pmf, denom):
class Exam (line 85) | class Exam(object):
method __init__ (line 91) | def __init__(self):
method Lookup (line 101) | def Lookup(self, raw):
method Reverse (line 105) | def Reverse(self, score):
method ReverseScale (line 113) | def ReverseScale(self, pmf):
class Sat (line 130) | class Sat(thinkbayes.Suite):
method __init__ (line 133) | def __init__(self, exam):
method Likelihood (line 142) | def Likelihood(self, data, hypo):
function PmfProbGreater (line 153) | def PmfProbGreater(pmf1, pmf2):
function main (line 172) | def main():
FILE: thinkbayes.py
function RandomSeed (line 48) | def RandomSeed(x):
function Odds (line 57) | def Odds(p):
function Probability (line 75) | def Probability(o):
function Probability2 (line 87) | def Probability2(yes, no):
class Interpolator (line 97) | class Interpolator(object):
method __init__ (line 105) | def __init__(self, xs, ys):
method Lookup (line 109) | def Lookup(self, x):
method Reverse (line 113) | def Reverse(self, y):
method _Bisect (line 117) | def _Bisect(self, x, xs, ys):
class _DictWrapper (line 129) | class _DictWrapper(object):
method __init__ (line 132) | def __init__(self, obj=None, label=None):
method __hash__ (line 163) | def __hash__(self):
method __str__ (line 166) | def __str__(self):
method __eq__ (line 172) | def __eq__(self, other):
method __len__ (line 175) | def __len__(self):
method __iter__ (line 178) | def __iter__(self):
method iterkeys (line 181) | def iterkeys(self):
method __contains__ (line 185) | def __contains__(self, value):
method __getitem__ (line 188) | def __getitem__(self, value):
method __setitem__ (line 191) | def __setitem__(self, value, prob):
method __delitem__ (line 194) | def __delitem__(self, value):
method Copy (line 197) | def Copy(self, label=None):
method Scale (line 212) | def Scale(self, factor):
method Log (line 226) | def Log(self, m=None):
method Exp (line 246) | def Exp(self, m=None):
method GetDict (line 263) | def GetDict(self):
method SetDict (line 267) | def SetDict(self, d):
method Values (line 271) | def Values(self):
method Items (line 280) | def Items(self):
method Render (line 284) | def Render(self, **options):
method MakeCdf (line 297) | def MakeCdf(self, label=None):
method Print (line 302) | def Print(self):
method Set (line 307) | def Set(self, x, y=0):
method Incr (line 316) | def Incr(self, x, term=1):
method Mult (line 325) | def Mult(self, x, factor):
method Remove (line 334) | def Remove(self, x):
method Total (line 344) | def Total(self):
method MaxLike (line 349) | def MaxLike(self):
method Largest (line 353) | def Largest(self, n=10):
method Smallest (line 360) | def Smallest(self, n=10):
class Hist (line 368) | class Hist(_DictWrapper):
method Freq (line 373) | def Freq(self, x):
method Freqs (line 384) | def Freqs(self, xs):
method IsSubset (line 388) | def IsSubset(self, other):
method Subtract (line 396) | def Subtract(self, other):
class Pmf (line 402) | class Pmf(_DictWrapper):
method Prob (line 409) | def Prob(self, x, default=0):
method Probs (line 421) | def Probs(self, xs):
method Percentile (line 425) | def Percentile(self, percentage):
method ProbGreater (line 442) | def ProbGreater(self, x):
method ProbLess (line 455) | def ProbLess(self, x):
method __lt__ (line 468) | def __lt__(self, obj):
method __gt__ (line 477) | def __gt__(self, obj):
method __ge__ (line 486) | def __ge__(self, obj):
method __le__ (line 495) | def __le__(self, obj):
method Normalize (line 504) | def Normalize(self, fraction=1.0):
method Random (line 527) | def Random(self):
method Mean (line 546) | def Mean(self):
method Var (line 557) | def Var(self, mu=None):
method Std (line 573) | def Std(self, mu=None):
method MaximumLikelihood (line 584) | def MaximumLikelihood(self):
method CredibleInterval (line 592) | def CredibleInterval(self, percentage=90):
method __add__ (line 606) | def __add__(self, other):
method AddPmf (line 618) | def AddPmf(self, other):
method AddConstant (line 631) | def AddConstant(self, other):
method __sub__ (line 643) | def __sub__(self, other):
method SubPmf (line 655) | def SubPmf(self, other):
method __mul__ (line 668) | def __mul__(self, other):
method MulPmf (line 680) | def MulPmf(self, other):
method MulConstant (line 693) | def MulConstant(self, other):
method __div__ (line 705) | def __div__(self, other):
method DivPmf (line 719) | def DivPmf(self, other):
method Max (line 732) | def Max(self, k):
class Joint (line 743) | class Joint(Pmf):
method Marginal (line 749) | def Marginal(self, i, label=None):
method Conditional (line 761) | def Conditional(self, i, j, val, label=None):
method MaxLikeInterval (line 781) | def MaxLikeInterval(self, percentage=90):
function MakeJoint (line 806) | def MakeJoint(pmf1, pmf2):
function MakeHistFromList (line 825) | def MakeHistFromList(t, label=None):
function MakeHistFromDict (line 838) | def MakeHistFromDict(d, label=None):
function MakePmfFromList (line 851) | def MakePmfFromList(t, label=None):
function MakePmfFromDict (line 864) | def MakePmfFromDict(d, label=None):
function MakePmfFromItems (line 877) | def MakePmfFromItems(t, label=None):
function MakePmfFromHist (line 890) | def MakePmfFromHist(hist, label=None):
function MakeMixture (line 906) | def MakeMixture(metapmf, label='mix'):
function MakeUniformPmf (line 922) | def MakeUniformPmf(low, high, n):
class Cdf (line 936) | class Cdf(object):
method __init__ (line 944) | def __init__(self, obj=None, ps=None, label=None):
method __str__ (line 997) | def __str__(self):
method __len__ (line 1002) | def __len__(self):
method __getitem__ (line 1005) | def __getitem__(self, x):
method __setitem__ (line 1008) | def __setitem__(self):
method __delitem__ (line 1011) | def __delitem__(self):
method __eq__ (line 1014) | def __eq__(self, other):
method Copy (line 1017) | def Copy(self, label=None):
method MakePmf (line 1026) | def MakePmf(self, label=None):
method Values (line 1032) | def Values(self):
method Items (line 1037) | def Items(self):
method Shift (line 1047) | def Shift(self, term):
method Scale (line 1057) | def Scale(self, factor):
method Prob (line 1067) | def Prob(self, x):
method Probs (line 1082) | def Probs(self, xs):
method Value (line 1097) | def Value(self, p):
method ValueArray (line 1112) | def ValueArray(self, ps):
method Percentile (line 1128) | def Percentile(self, p):
method PercentileRank (line 1139) | def PercentileRank(self, x):
method Random (line 1148) | def Random(self):
method Sample (line 1152) | def Sample(self, n):
method Mean (line 1161) | def Mean(self):
method CredibleInterval (line 1175) | def CredibleInterval(self, percentage=90):
method _Round (line 1192) | def _Round(self, multiplier=1000.0):
method Render (line 1202) | def Render(self, **options):
method Max (line 1226) | def Max(self, k):
function MakeCdfFromItems (line 1238) | def MakeCdfFromItems(items, label=None):
function MakeCdfFromDict (line 1251) | def MakeCdfFromDict(d, label=None):
function MakeCdfFromList (line 1264) | def MakeCdfFromList(seq, label=None):
function MakeCdfFromHist (line 1277) | def MakeCdfFromHist(hist, label=None):
function MakeCdfFromPmf (line 1293) | def MakeCdfFromPmf(pmf, label=None):
class UnimplementedMethodException (line 1309) | class UnimplementedMethodException(Exception):
class Suite (line 1313) | class Suite(Pmf):
method Update (line 1316) | def Update(self, data):
method LogUpdate (line 1328) | def LogUpdate(self, data):
method UpdateSet (line 1343) | def UpdateSet(self, dataset):
method LogUpdateSet (line 1362) | def LogUpdateSet(self, dataset):
method Likelihood (line 1375) | def Likelihood(self, data, hypo):
method LogLikelihood (line 1383) | def LogLikelihood(self, data, hypo):
method Print (line 1391) | def Print(self):
method MakeOdds (line 1396) | def MakeOdds(self):
method MakeProbs (line 1407) | def MakeProbs(self):
function MakeSuiteFromList (line 1413) | def MakeSuiteFromList(t, label=None):
function MakeSuiteFromHist (line 1428) | def MakeSuiteFromHist(hist, label=None):
function MakeSuiteFromDict (line 1446) | def MakeSuiteFromDict(d, label=None):
class Pdf (line 1462) | class Pdf(object):
method Density (line 1465) | def Density(self, x):
method GetLinspace (line 1472) | def GetLinspace(self):
method MakePmf (line 1481) | def MakePmf(self, **options):
method Render (line 1496) | def Render(self, **options):
method Items (line 1522) | def Items(self):
class NormalPdf (line 1528) | class NormalPdf(Pdf):
method __init__ (line 1531) | def __init__(self, mu=0, sigma=1, label=None):
method __str__ (line 1542) | def __str__(self):
method GetLinspace (line 1545) | def GetLinspace(self):
method Density (line 1553) | def Density(self, xs):
class ExponentialPdf (line 1563) | class ExponentialPdf(Pdf):
method __init__ (line 1566) | def __init__(self, lam=1, label=None):
method __str__ (line 1575) | def __str__(self):
method GetLinspace (line 1578) | def GetLinspace(self):
method Density (line 1586) | def Density(self, xs):
class EstimatedPdf (line 1596) | class EstimatedPdf(Pdf):
method __init__ (line 1599) | def __init__(self, sample, label=None):
method __str__ (line 1611) | def __str__(self):
method GetLinspace (line 1614) | def GetLinspace(self):
method Density (line 1621) | def Density(self, xs):
function CredibleInterval (line 1629) | def CredibleInterval(pmf, percentage=90):
function PmfProbLess (line 1647) | def PmfProbLess(pmf1, pmf2):
function PmfProbGreater (line 1665) | def PmfProbGreater(pmf1, pmf2):
function PmfProbEqual (line 1683) | def PmfProbEqual(pmf1, pmf2):
function RandomSum (line 1701) | def RandomSum(dists):
function SampleSum (line 1712) | def SampleSum(dists, n):
function EvalNormalPdf (line 1724) | def EvalNormalPdf(x, mu, sigma):
function MakeNormalPmf (line 1736) | def MakeNormalPmf(mu, sigma, num_sigmas, n=201):
function EvalBinomialPmf (line 1757) | def EvalBinomialPmf(k, n, p):
function EvalHypergeomPmf (line 1765) | def EvalHypergeomPmf(k, N, K, n):
function EvalPoissonPmf (line 1774) | def EvalPoissonPmf(k, lam):
function MakePoissonPmf (line 1788) | def MakePoissonPmf(lam, high, step=1):
function EvalExponentialPdf (line 1804) | def EvalExponentialPdf(x, lam):
function EvalExponentialCdf (line 1815) | def EvalExponentialCdf(x, lam):
function MakeExponentialPmf (line 1820) | def MakeExponentialPmf(lam, high, n=200):
function StandardNormalCdf (line 1837) | def StandardNormalCdf(x):
function EvalNormalCdf (line 1852) | def EvalNormalCdf(x, mu=0, sigma=1):
function EvalNormalCdfInverse (line 1868) | def EvalNormalCdfInverse(p, mu=0, sigma=1):
function EvalLognormalCdf (line 1886) | def EvalLognormalCdf(x, mu=0, sigma=1):
function RenderExpoCdf (line 1898) | def RenderExpoCdf(lam, low, high, n=101):
function RenderNormalCdf (line 1914) | def RenderNormalCdf(mu, sigma, low, high, n=101):
function RenderParetoCdf (line 1930) | def RenderParetoCdf(xmin, alpha, low, high, n=50):
class Beta (line 1949) | class Beta(object):
method __init__ (line 1954) | def __init__(self, alpha=1, beta=1, label=None):
method Update (line 1960) | def Update(self, data):
method Mean (line 1969) | def Mean(self):
method Random (line 1973) | def Random(self):
method Sample (line 1977) | def Sample(self, n):
method EvalPdf (line 1985) | def EvalPdf(self, x):
method MakePmf (line 1989) | def MakePmf(self, steps=101, label=None):
method MakeCdf (line 2011) | def MakeCdf(self, steps=101):
class Dirichlet (line 2019) | class Dirichlet(object):
method __init__ (line 2025) | def __init__(self, n, conc=1, label=None):
method Update (line 2040) | def Update(self, data):
method Random (line 2048) | def Random(self):
method Likelihood (line 2056) | def Likelihood(self, data):
method LogLikelihood (line 2072) | def LogLikelihood(self, data):
method MarginalBeta (line 2087) | def MarginalBeta(self, i):
method PredictivePmf (line 2101) | def PredictivePmf(self, xs, label=None):
function BinomialCoef (line 2113) | def BinomialCoef(n, k):
function LogBinomialCoef (line 2124) | def LogBinomialCoef(n, k):
function NormalProbability (line 2138) | def NormalProbability(ys, jitter=0.0):
function Jitter (line 2159) | def Jitter(values, jitter=0.5):
function NormalProbabilityPlot (line 2171) | def NormalProbabilityPlot(sample, fit_color='0.8', **options):
function Mean (line 2189) | def Mean(xs):
function Var (line 2199) | def Var(xs, mu=None, ddof=0):
function Std (line 2217) | def Std(xs, mu=None, ddof=0):
function MeanVar (line 2230) | def MeanVar(xs, ddof=0):
function Trim (line 2247) | def Trim(t, p=0.01):
function TrimmedMean (line 2262) | def TrimmedMean(t, p=0.01):
function TrimmedMeanVar (line 2276) | def TrimmedMeanVar(t, p=0.01):
function CohenEffectSize (line 2293) | def CohenEffectSize(group1, group2):
function Cov (line 2312) | def Cov(xs, ys, meanx=None, meany=None):
function Corr (line 2336) | def Corr(xs, ys):
function SerialCorr (line 2357) | def SerialCorr(series, lag=1):
function SpearmanCorr (line 2371) | def SpearmanCorr(xs, ys):
function MapToRanks (line 2386) | def MapToRanks(t):
function LeastSquares (line 2412) | def LeastSquares(xs, ys):
function FitLine (line 2431) | def FitLine(xs, inter, slope):
function Residuals (line 2443) | def Residuals(xs, ys, inter, slope):
function CoefDetermination (line 2461) | def CoefDetermination(ys, res):
function CorrelatedGenerator (line 2474) | def CorrelatedGenerator(rho):
function CorrelatedNormalGenerator (line 2490) | def CorrelatedNormalGenerator(mu, sigma, rho):
function RawMoment (line 2503) | def RawMoment(xs, k):
function CentralMoment (line 2509) | def CentralMoment(xs, k):
function StandardizedMoment (line 2516) | def StandardizedMoment(xs, k):
function Skewness (line 2524) | def Skewness(xs):
function Median (line 2530) | def Median(xs):
function IQR (line 2541) | def IQR(xs):
function PearsonMedianSkewness (line 2552) | def PearsonMedianSkewness(xs):
class FixedWidthVariables (line 2563) | class FixedWidthVariables(object):
method __init__ (line 2566) | def __init__(self, variables, index_base=0):
method ReadFixedWidth (line 2585) | def ReadFixedWidth(self, filename, **options):
function ReadStataDct (line 2599) | def ReadStataDct(dct_file, **options):
function Resample (line 2635) | def Resample(xs, n=None):
function SampleRows (line 2648) | def SampleRows(df, nrows, replace=False):
function ResampleRows (line 2662) | def ResampleRows(df):
function ResampleRowsWeighted (line 2672) | def ResampleRowsWeighted(df, column='finalwgt'):
function PercentileRow (line 2687) | def PercentileRow(array, p):
function PercentileRows (line 2699) | def PercentileRows(ys_seq, percents):
function Smooth (line 2724) | def Smooth(xs, sigma=2, **options):
class HypothesisTest (line 2733) | class HypothesisTest(object):
method __init__ (line 2736) | def __init__(self, data):
method PValue (line 2747) | def PValue(self, iters=1000):
method MaxTestStat (line 2761) | def MaxTestStat(self):
method PlotCdf (line 2766) | def PlotCdf(self, label=None):
method TestStatistic (line 2776) | def TestStatistic(self, data):
method MakeModel (line 2783) | def MakeModel(self):
method RunModel (line 2788) | def RunModel(self):
function main (line 2796) | def main():
FILE: thinkbayes2.py
function RandomSeed (line 50) | def RandomSeed(x):
function Odds (line 59) | def Odds(p):
function Probability (line 77) | def Probability(o):
function Probability2 (line 89) | def Probability2(yes, no):
class Interpolator (line 99) | class Interpolator(object):
method __init__ (line 107) | def __init__(self, xs, ys):
method Lookup (line 111) | def Lookup(self, x):
method Reverse (line 115) | def Reverse(self, y):
method _Bisect (line 119) | def _Bisect(self, x, xs, ys):
class _DictWrapper (line 136) | class _DictWrapper(object):
method __init__ (line 139) | def __init__(self, obj=None, label=None):
method __hash__ (line 170) | def __hash__(self):
method __str__ (line 173) | def __str__(self):
method __repr__ (line 180) | def __repr__(self):
method __eq__ (line 187) | def __eq__(self, other):
method __len__ (line 193) | def __len__(self):
method __iter__ (line 196) | def __iter__(self):
method iterkeys (line 199) | def iterkeys(self):
method __contains__ (line 203) | def __contains__(self, value):
method __getitem__ (line 206) | def __getitem__(self, value):
method __setitem__ (line 209) | def __setitem__(self, value, prob):
method __delitem__ (line 212) | def __delitem__(self, value):
method Copy (line 215) | def Copy(self, label=None):
method Scale (line 230) | def Scale(self, factor):
method Log (line 244) | def Log(self, m=None):
method Exp (line 264) | def Exp(self, m=None):
method GetDict (line 281) | def GetDict(self):
method SetDict (line 285) | def SetDict(self, d):
method Values (line 289) | def Values(self):
method Items (line 298) | def Items(self):
method SortedItems (line 302) | def SortedItems(self):
method Render (line 322) | def Render(self, **options):
method MakeCdf (line 332) | def MakeCdf(self, label=None):
method Print (line 337) | def Print(self):
method Set (line 342) | def Set(self, x, y=0):
method Incr (line 351) | def Incr(self, x, term=1):
method Mult (line 360) | def Mult(self, x, factor):
method Remove (line 369) | def Remove(self, x):
method Total (line 379) | def Total(self):
method MaxLike (line 384) | def MaxLike(self):
method Largest (line 388) | def Largest(self, n=10):
method Smallest (line 395) | def Smallest(self, n=10):
class Hist (line 403) | class Hist(_DictWrapper):
method Freq (line 408) | def Freq(self, x):
method Freqs (line 419) | def Freqs(self, xs):
method IsSubset (line 423) | def IsSubset(self, other):
method Subtract (line 431) | def Subtract(self, other):
class Pmf (line 437) | class Pmf(_DictWrapper):
method Prob (line 444) | def Prob(self, x, default=0):
method Probs (line 456) | def Probs(self, xs):
method Percentile (line 460) | def Percentile(self, percentage):
method ProbGreater (line 477) | def ProbGreater(self, x):
method ProbLess (line 490) | def ProbLess(self, x):
method ProbEqual (line 503) | def ProbEqual(self, x):
method Normalize (line 519) | def Normalize(self, fraction=1):
method Random (line 540) | def Random(self):
method Sample (line 559) | def Sample(self, n):
method Mean (line 567) | def Mean(self):
method Median (line 575) | def Median(self):
method Var (line 583) | def Var(self, mu=None):
method Expect (line 596) | def Expect(self, func):
method Std (line 604) | def Std(self, mu=None):
method Mode (line 615) | def Mode(self):
method CredibleInterval (line 630) | def CredibleInterval(self, percentage=90):
method __add__ (line 644) | def __add__(self, other):
method AddPmf (line 658) | def AddPmf(self, other):
method AddConstant (line 671) | def AddConstant(self, other):
method __sub__ (line 686) | def __sub__(self, other):
method SubPmf (line 698) | def SubPmf(self, other):
method __mul__ (line 711) | def __mul__(self, other):
method MulPmf (line 723) | def MulPmf(self, other):
method MulConstant (line 736) | def MulConstant(self, other):
method __div__ (line 748) | def __div__(self, other):
method DivPmf (line 762) | def DivPmf(self, other):
method Max (line 775) | def Max(self, k):
class Joint (line 787) | class Joint(Pmf):
method Marginal (line 793) | def Marginal(self, i, label=None):
method Conditional (line 805) | def Conditional(self, i, j, val, label=None):
method MaxLikeInterval (line 825) | def MaxLikeInterval(self, percentage=90):
function MakeJoint (line 850) | def MakeJoint(pmf1, pmf2):
function MakeHistFromList (line 869) | def MakeHistFromList(t, label=None):
function MakeHistFromDict (line 882) | def MakeHistFromDict(d, label=None):
function MakePmfFromList (line 895) | def MakePmfFromList(t, label=None):
function MakePmfFromDict (line 908) | def MakePmfFromDict(d, label=None):
function MakePmfFromItems (line 921) | def MakePmfFromItems(t, label=None):
function MakePmfFromHist (line 934) | def MakePmfFromHist(hist, label=None):
function MakeMixture (line 950) | def MakeMixture(metapmf, label='mix'):
function MakeUniformPmf (line 966) | def MakeUniformPmf(low, high, n):
class Cdf (line 980) | class Cdf:
method __init__ (line 988) | def __init__(self, obj=None, ps=None, label=None):
method __str__ (line 1041) | def __str__(self):
method __repr__ (line 1048) | def __repr__(self):
method __len__ (line 1056) | def __len__(self):
method __getitem__ (line 1059) | def __getitem__(self, x):
method __setitem__ (line 1062) | def __setitem__(self):
method __delitem__ (line 1065) | def __delitem__(self):
method __eq__ (line 1068) | def __eq__(self, other):
method Print (line 1071) | def Print(self):
method Copy (line 1076) | def Copy(self, label=None):
method MakePmf (line 1085) | def MakePmf(self, label=None):
method Items (line 1091) | def Items(self):
method Shift (line 1101) | def Shift(self, term):
method Scale (line 1111) | def Scale(self, factor):
method Prob (line 1121) | def Prob(self, x):
method Probs (line 1136) | def Probs(self, xs):
method Value (line 1151) | def Value(self, p):
method Values (line 1166) | def Values(self, ps=None):
method Percentile (line 1189) | def Percentile(self, p):
method Percentiles (line 1200) | def Percentiles(self, ps):
method PercentileRank (line 1212) | def PercentileRank(self, x):
method PercentileRanks (line 1221) | def PercentileRanks(self, xs):
method Random (line 1230) | def Random(self):
method Sample (line 1234) | def Sample(self, n):
method Mean (line 1243) | def Mean(self):
method CredibleInterval (line 1257) | def CredibleInterval(self, percentage=90):
method _Round (line 1274) | def _Round(self, multiplier=1000):
method Render (line 1284) | def Render(self, **options):
method Max (line 1308) | def Max(self, k):
function MakeCdfFromItems (line 1320) | def MakeCdfFromItems(items, label=None):
function MakeCdfFromDict (line 1333) | def MakeCdfFromDict(d, label=None):
function MakeCdfFromList (line 1346) | def MakeCdfFromList(seq, label=None):
function MakeCdfFromHist (line 1359) | def MakeCdfFromHist(hist, label=None):
function MakeCdfFromPmf (line 1375) | def MakeCdfFromPmf(pmf, label=None):
class UnimplementedMethodException (line 1391) | class UnimplementedMethodException(Exception):
class Suite (line 1395) | class Suite(Pmf):
method Update (line 1398) | def Update(self, data):
method LogUpdate (line 1410) | def LogUpdate(self, data):
method UpdateSet (line 1425) | def UpdateSet(self, dataset):
method LogUpdateSet (line 1444) | def LogUpdateSet(self, dataset):
method Likelihood (line 1457) | def Likelihood(self, data, hypo):
method LogLikelihood (line 1465) | def LogLikelihood(self, data, hypo):
method Print (line 1473) | def Print(self):
method MakeOdds (line 1478) | def MakeOdds(self):
method MakeProbs (line 1489) | def MakeProbs(self):
function MakeSuiteFromList (line 1495) | def MakeSuiteFromList(t, label=None):
function MakeSuiteFromHist (line 1510) | def MakeSuiteFromHist(hist, label=None):
function MakeSuiteFromDict (line 1528) | def MakeSuiteFromDict(d, label=None):
class Pdf (line 1544) | class Pdf(object):
method Density (line 1547) | def Density(self, x):
method GetLinspace (line 1554) | def GetLinspace(self):
method MakePmf (line 1563) | def MakePmf(self, **options):
method Render (line 1578) | def Render(self, **options):
method Items (line 1604) | def Items(self):
class NormalPdf (line 1610) | class NormalPdf(Pdf):
method __init__ (line 1613) | def __init__(self, mu=0, sigma=1, label=None):
method __str__ (line 1624) | def __str__(self):
method GetLinspace (line 1627) | def GetLinspace(self):
method Density (line 1635) | def Density(self, xs):
class ExponentialPdf (line 1645) | class ExponentialPdf(Pdf):
method __init__ (line 1648) | def __init__(self, lam=1, label=None):
method __str__ (line 1657) | def __str__(self):
method GetLinspace (line 1660) | def GetLinspace(self):
method Density (line 1668) | def Density(self, xs):
class EstimatedPdf (line 1678) | class EstimatedPdf(Pdf):
method __init__ (line 1681) | def __init__(self, sample, label=None):
method __str__ (line 1693) | def __str__(self):
method GetLinspace (line 1696) | def GetLinspace(self):
method Density (line 1703) | def Density(self, xs):
method Sample (line 1710) | def Sample(self, n):
function CredibleInterval (line 1720) | def CredibleInterval(pmf, percentage=90):
function PmfProbLess (line 1738) | def PmfProbLess(pmf1, pmf2):
function PmfProbGreater (line 1756) | def PmfProbGreater(pmf1, pmf2):
function PmfProbEqual (line 1774) | def PmfProbEqual(pmf1, pmf2):
function RandomSum (line 1792) | def RandomSum(dists):
function SampleSum (line 1803) | def SampleSum(dists, n):
function EvalNormalPdf (line 1815) | def EvalNormalPdf(x, mu, sigma):
function MakeNormalPmf (line 1827) | def MakeNormalPmf(mu, sigma, num_sigmas, n=201):
function EvalBinomialPmf (line 1848) | def EvalBinomialPmf(k, n, p):
function MakeBinomialPmf (line 1856) | def MakeBinomialPmf(n, p):
function EvalGammaPdf (line 1867) | def EvalGammaPdf(x, a):
function MakeGammaPmf (line 1878) | def MakeGammaPmf(xs, a):
function EvalGeometricPmf (line 1893) | def EvalGeometricPmf(k, p, loc=0):
function MakeGeometricPmf (line 1905) | def MakeGeometricPmf(p, loc=0, high=10):
function EvalHypergeomPmf (line 1921) | def EvalHypergeomPmf(k, N, K, n):
function EvalPoissonPmf (line 1930) | def EvalPoissonPmf(k, lam):
function MakePoissonPmf (line 1941) | def MakePoissonPmf(lam, high, step=1):
function EvalExponentialPdf (line 1957) | def EvalExponentialPdf(x, lam):
function EvalExponentialCdf (line 1968) | def EvalExponentialCdf(x, lam):
function MakeExponentialPmf (line 1973) | def MakeExponentialPmf(lam, high, n=200):
function EvalWeibullPdf (line 1990) | def EvalWeibullPdf(x, lam, k):
function EvalWeibullCdf (line 2003) | def EvalWeibullCdf(x, lam, k):
function MakeWeibullPmf (line 2009) | def MakeWeibullPmf(lam, k, high, n=200):
function EvalParetoPdf (line 2025) | def EvalParetoPdf(x, xm, alpha):
function MakeParetoPmf (line 2036) | def MakeParetoPmf(xm, alpha, high, num=101):
function StandardNormalCdf (line 2051) | def StandardNormalCdf(x):
function EvalNormalCdf (line 2066) | def EvalNormalCdf(x, mu=0, sigma=1):
function EvalNormalCdfInverse (line 2082) | def EvalNormalCdfInverse(p, mu=0, sigma=1):
function EvalLognormalCdf (line 2100) | def EvalLognormalCdf(x, mu=0, sigma=1):
function RenderExpoCdf (line 2112) | def RenderExpoCdf(lam, low, high, n=101):
function RenderNormalCdf (line 2128) | def RenderNormalCdf(mu, sigma, low, high, n=101):
function RenderParetoCdf (line 2144) | def RenderParetoCdf(xmin, alpha, low, high, n=50):
class Beta (line 2163) | class Beta:
method __init__ (line 2168) | def __init__(self, alpha=1, beta=1, label=None):
method Update (line 2174) | def Update(self, data):
method Mean (line 2183) | def Mean(self):
method MAP (line 2187) | def MAP(self):
method Random (line 2193) | def Random(self):
method Sample (line 2197) | def Sample(self, n):
method EvalPdf (line 2205) | def EvalPdf(self, x):
method MakePmf (line 2209) | def MakePmf(self, steps=101, label=None):
method MakeCdf (line 2239) | def MakeCdf(self, steps=101):
method Percentile (line 2246) | def Percentile(self, ps):
class Dirichlet (line 2256) | class Dirichlet(object):
method __init__ (line 2262) | def __init__(self, n, conc=1, label=None):
method Update (line 2277) | def Update(self, data):
method Random (line 2285) | def Random(self):
method Likelihood (line 2293) | def Likelihood(self, data):
method LogLikelihood (line 2309) | def LogLikelihood(self, data):
method MarginalBeta (line 2324) | def MarginalBeta(self, i):
method PredictivePmf (line 2338) | def PredictivePmf(self, xs, label=None):
function BinomialCoef (line 2350) | def BinomialCoef(n, k):
function LogBinomialCoef (line 2361) | def LogBinomialCoef(n, k):
function NormalProbability (line 2375) | def NormalProbability(ys, jitter=0):
function Jitter (line 2396) | def Jitter(values, jitter=0.5):
function NormalProbabilityPlot (line 2408) | def NormalProbabilityPlot(sample, fit_color='0.8', **options):
function Mean (line 2426) | def Mean(xs):
function Var (line 2436) | def Var(xs, mu=None, ddof=0):
function Std (line 2454) | def Std(xs, mu=None, ddof=0):
function MeanVar (line 2467) | def MeanVar(xs, ddof=0):
function Trim (line 2484) | def Trim(t, p=0.01):
function TrimmedMean (line 2499) | def TrimmedMean(t, p=0.01):
function TrimmedMeanVar (line 2513) | def TrimmedMeanVar(t, p=0.01):
function CohenEffectSize (line 2530) | def CohenEffectSize(group1, group2):
function Cov (line 2549) | def Cov(xs, ys, meanx=None, meany=None):
function Corr (line 2573) | def Corr(xs, ys):
function SerialCorr (line 2594) | def SerialCorr(series, lag=1):
function SpearmanCorr (line 2608) | def SpearmanCorr(xs, ys):
function MapToRanks (line 2623) | def MapToRanks(t):
function LeastSquares (line 2649) | def LeastSquares(xs, ys):
function FitLine (line 2668) | def FitLine(xs, inter, slope):
function Residuals (line 2680) | def Residuals(xs, ys, inter, slope):
function CoefDetermination (line 2698) | def CoefDetermination(ys, res):
function CorrelatedGenerator (line 2711) | def CorrelatedGenerator(rho):
function CorrelatedNormalGenerator (line 2727) | def CorrelatedNormalGenerator(mu, sigma, rho):
function RawMoment (line 2740) | def RawMoment(xs, k):
function CentralMoment (line 2746) | def CentralMoment(xs, k):
function StandardizedMoment (line 2753) | def StandardizedMoment(xs, k):
function Skewness (line 2761) | def Skewness(xs):
function Median (line 2767) | def Median(xs):
function IQR (line 2778) | def IQR(xs):
function PearsonMedianSkewness (line 2789) | def PearsonMedianSkewness(xs):
class FixedWidthVariables (line 2800) | class FixedWidthVariables(object):
method __init__ (line 2803) | def __init__(self, variables, index_base=0):
method ReadFixedWidth (line 2822) | def ReadFixedWidth(self, filename, **options):
function ReadStataDct (line 2836) | def ReadStataDct(dct_file, **options):
function Resample (line 2875) | def Resample(xs, n=None):
function SampleRows (line 2888) | def SampleRows(df, nrows, replace=False):
function ResampleRows (line 2902) | def ResampleRows(df):
function ResampleRowsWeighted (line 2912) | def ResampleRowsWeighted(df, column='finalwgt'):
function PercentileRow (line 2927) | def PercentileRow(array, p):
function PercentileRows (line 2939) | def PercentileRows(ys_seq, percents):
function Smooth (line 2964) | def Smooth(xs, sigma=2, **options):
class HypothesisTest (line 2973) | class HypothesisTest(object):
method __init__ (line 2976) | def __init__(self, data):
method PValue (line 2987) | def PValue(self, iters=1000):
method MaxTestStat (line 3001) | def MaxTestStat(self):
method PlotCdf (line 3006) | def PlotCdf(self, label=None):
method TestStatistic (line 3016) | def TestStatistic(self, data):
method MakeModel (line 3023) | def MakeModel(self):
method RunModel (line 3028) | def RunModel(self):
function main (line 3036) | def main():
FILE: thinkplot.py
class _Brewer (line 32) | class _Brewer(object):
method Colors (line 62) | def Colors(cls):
method ColorGenerator (line 68) | def ColorGenerator(cls, num):
method InitIter (line 78) | def InitIter(cls, num):
method ClearIter (line 85) | def ClearIter(cls):
method GetIter (line 91) | def GetIter(cls, num):
function _UnderrideColor (line 104) | def _UnderrideColor(options):
function PrePlot (line 125) | def PrePlot(num=None, rows=None, cols=None):
function SubPlot (line 171) | def SubPlot(plot_number, rows=None, cols=None, **options):
function _Underride (line 184) | def _Underride(d, **options):
function Clf (line 201) | def Clf():
function Figure (line 211) | def Figure(**options):
function Plot (line 217) | def Plot(obj, ys=None, style='', **options):
function Vlines (line 244) | def Vlines(xs, y1, y2, **options):
function Hlines (line 258) | def Hlines(ys, x1, x2, **options):
function FillBetween (line 272) | def FillBetween(xs, y1, y2=None, where=None, **options):
function Bar (line 287) | def Bar(xs, ys, **options):
function Scatter (line 300) | def Scatter(xs, ys=None, **options):
function HexBin (line 317) | def HexBin(xs, ys, **options):
function Pdf (line 328) | def Pdf(pdf, **options):
function Pdfs (line 342) | def Pdfs(pdfs, **options):
function Hist (line 356) | def Hist(hist, **options):
function Hists (line 400) | def Hists(hists, **options):
function Pmf (line 414) | def Pmf(pmf, **options):
function Pmfs (line 460) | def Pmfs(pmfs, **options):
function Diff (line 474) | def Diff(t):
function Cdf (line 487) | def Cdf(cdf, complement=False, transform=None, **options):
function Cdfs (line 540) | def Cdfs(cdfs, complement=False, transform=None, **options):
function Contour (line 552) | def Contour(obj, pcolor=False, contour=True, imshow=False, **options):
function Pcolor (line 591) | def Pcolor(xs, ys, zs, pcolor=True, contour=False, **options):
function Text (line 618) | def Text(x, y, s, **options):
function Config (line 636) | def Config(**options):
function Show (line 680) | def Show(**options):
function Plotly (line 694) | def Plotly(**options):
function Save (line 710) | def Save(root=None, formats=None, **options):
function SaveFormat (line 745) | def SaveFormat(root, fmt='eps', **options):
function main (line 783) | def main():
FILE: train.py
class Train (line 14) | class Train(thinkbayes.Suite):
method Likelihood (line 20) | def Likelihood(self, data, hypo):
function main (line 31) | def main():
FILE: train2.py
class Train (line 14) | class Train(thinkbayes.Suite):
method Likelihood (line 20) | def Likelihood(self, data, hypo):
function main (line 33) | def main():
FILE: train_soln.py
class Train (line 14) | class Train(thinkbayes.Suite):
method Likelihood (line 20) | def Likelihood(self, data, hypo):
function main (line 33) | def main():
FILE: volunteer.py
class Volunteer (line 33) | class Volunteer(thinkbayes.Suite):
method Likelihood (line 35) | def Likelihood(self, data, hypo):
method Likelihood1 (line 48) | def Likelihood1(self, data, hypo):
method Likelihood2 (line 63) | def Likelihood2(self, data, hypo):
function MarginalDistribution (line 84) | def MarginalDistribution(suite, index):
function MarginalProduct (line 98) | def MarginalProduct(suite):
function main (line 111) | def main():
Condensed preview — 47 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,741K chars).
[
{
"path": "01_cookie.ipynb",
"chars": 11151,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"# Bayesian Statistics Made Simple\\n"
},
{
"path": "01_cookie_soln.ipynb",
"chars": 83649,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"# Bayesian Statistics Made Simple\\n"
},
{
"path": "02_euro.ipynb",
"chars": 14434,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"# Bayesian Statistics Made Simple\\n"
},
{
"path": "02_euro_soln.ipynb",
"chars": 85422,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"# Bayesian Statistics Made Simple\\n"
},
{
"path": "03_bandit.ipynb",
"chars": 16030,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"# Bayesian Statistics Made Simple\\n"
},
{
"path": "03_bandit_soln.ipynb",
"chars": 118321,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"# Bayesian Statistics Made Simple\\n"
},
{
"path": "03_euro.ipynb",
"chars": 8984,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"Bayesian Statistics Made Simple\\n\","
},
{
"path": "04_bandit.ipynb",
"chars": 13693,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"Bayesian Statistics Made Simple\\n\","
},
{
"path": "README.md",
"chars": 5321,
"preview": "## Bayesian Statistics Made Simple\n\n[Allen Downey](https:allendowney.com)\n\nBayesian statistical methods are becoming mor"
},
{
"path": "_config.yml",
"chars": 27,
"preview": "theme: jekyll-theme-minimal"
},
{
"path": "bandit_soln.ipynb",
"chars": 107210,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"Bayesian Statistics Made Simple\\n\","
},
{
"path": "billiards.py",
"chars": 1541,
"preview": "\"\"\"This file contains code used in \"Think Stats\",\nby Allen B. Downey, available from greenteapress.com\n\nCopyright 2015 A"
},
{
"path": "cookie_soln.ipynb",
"chars": 65931,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"Bayesian Statistics Made Simple\\n\","
},
{
"path": "debug.ipynb",
"chars": 5861,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"code\",\n \"execution_count\": 1,\n \"metadata\": {},\n \"outputs\": [\n {\n \"name\":"
},
{
"path": "dice.py",
"chars": 870,
"preview": "\"\"\"This file contains code for use with \"Think Bayes\",\nby Allen B. Downey, available from greenteapress.com\n\nCopyright 2"
},
{
"path": "dice_soln.ipynb",
"chars": 65581,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"Bayesian Statistics Made Simple\\n\","
},
{
"path": "dice_soln.py",
"chars": 912,
"preview": "\"\"\"This file contains code for use with \"Think Bayes\",\nby Allen B. Downey, available from greenteapress.com\n\nCopyright 2"
},
{
"path": "distribution.py",
"chars": 16338,
"preview": "\"\"\"\n\nPmf: Represents a Probability Mass Function (PMF).\nCdf: Represents a Cumulative Distribution Function (CDF).\n\nCopyr"
},
{
"path": "empyrical_dist.py",
"chars": 19992,
"preview": "\"\"\"\n\nPmf: Represents a Probability Mass Function (PMF).\nCdf: Represents a Cumulative Distribution Function (CDF).\n\nCopyr"
},
{
"path": "environment.yml",
"chars": 164,
"preview": "name: BayesMadeSimple\n\ndependencies:\n - python=3.7\n - jupyter\n - numpy\n - matplotlib\n - seaborn\n - pandas\n - scip"
},
{
"path": "euro.py",
"chars": 1502,
"preview": "\"\"\"This file contains code used in \"Think Stats\",\nby Allen B. Downey, available from greenteapress.com\n\nCopyright 2013 A"
},
{
"path": "euro2.py",
"chars": 2220,
"preview": "\"\"\"This file contains code used in \"Think Stats\",\nby Allen B. Downey, available from greenteapress.com\n\nCopyright 2013 A"
},
{
"path": "euro2_soln.py",
"chars": 2313,
"preview": "\"\"\"This file contains code used in \"Think Stats\",\nby Allen B. Downey, available from greenteapress.com\n\nCopyright 2013 A"
},
{
"path": "euro_soln.ipynb",
"chars": 204135,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"Bayesian Statistics Made Simple\\n\","
},
{
"path": "euro_soln.py",
"chars": 1568,
"preview": "\"\"\"This file contains code used in \"Think Stats\",\nby Allen B. Downey, available from greenteapress.com\n\nCopyright 2013 A"
},
{
"path": "flip.ipynb",
"chars": 84708,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"## Bayesian Statistics Made Simple\\"
},
{
"path": "install_test.py",
"chars": 1130,
"preview": "\"\"\"This file contains code used in \"Think Stats\",\nby Allen B. Downey, available from greenteapress.com\n\nCopyright 2013 A"
},
{
"path": "lincoln.py",
"chars": 3725,
"preview": "\"\"\"This file contains code used in \"Think Stats\",\nby Allen B. Downey, available from greenteapress.com\n\nCopyright 2014 A"
},
{
"path": "sat.py",
"chars": 4539,
"preview": "\"\"\"This file contains code used in \"Think Bayes\",\nby Allen B. Downey, available from greenteapress.com\n\nCopyright 2012 A"
},
{
"path": "sat_ranks.csv",
"chars": 2064,
"preview": "\"http://professionals.collegeboard.com/profdownload/sat-mathematics-percentile-ranks-2010.pdf\",,,,,,\n,\"Total\",,\"Male\",,\""
},
{
"path": "sat_scale.csv",
"chars": 695,
"preview": "\"http://professionals.collegeboard.com/profdownload/sat-raw-score-to-scaled-score-ranges-2010.pdf\",,,,,\n\"Raw score\",\"Cri"
},
{
"path": "sat_soln.py",
"chars": 4551,
"preview": "\"\"\"This file contains code used in \"Think Bayes\",\nby Allen B. Downey, available from greenteapress.com\n\nCopyright 2012 A"
},
{
"path": "thinkbayes.py",
"chars": 68825,
"preview": "\"\"\"This file contains code for use with \"Think Stats\" and\n\"Think Bayes\", both by Allen B. Downey, available from greente"
},
{
"path": "thinkbayes2.py",
"chars": 75264,
"preview": "\"\"\"This file contains code for use with \"Think Stats\" and\n\"Think Bayes\", both by Allen B. Downey, available from greente"
},
{
"path": "thinkplot.py",
"chars": 20190,
"preview": "\"\"\"This file contains code for use with \"Think Stats\",\nby Allen B. Downey, available from greenteapress.com\n\nCopyright 2"
},
{
"path": "train.py",
"chars": 1049,
"preview": "\"\"\"This file contains code for use with \"Think Bayes\",\nby Allen B. Downey, available from greenteapress.com\n\nCopyright 2"
},
{
"path": "train2.py",
"chars": 1741,
"preview": "\"\"\"This file contains code for use with \"Think Bayes\",\nby Allen B. Downey, available from greenteapress.com\n\nCopyright 2"
},
{
"path": "train_soln.py",
"chars": 1248,
"preview": "\"\"\"This file contains code for use with \"Think Bayes\",\nby Allen B. Downey, available from greenteapress.com\n\nCopyright 2"
},
{
"path": "tutorial.md",
"chars": 4314,
"preview": "## Tutorial: Bayes Made Simple\n\nAllen Downey\n\nThe tutorial material is based on my book, [*Think Bayes*](http://greentea"
},
{
"path": "volunteer.py",
"chars": 3671,
"preview": "\"\"\"This file contains code used in \"Think Stats\",\nby Allen B. Downey, available from greenteapress.com\n\nCopyright 2013 A"
},
{
"path": "world_cup01.ipynb",
"chars": 129484,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"Bayesian Statistics Made Simple\\n\","
},
{
"path": "world_cup01soln.ipynb",
"chars": 153257,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"Bayesian Statistics Made Simple\\n\","
},
{
"path": "world_cup02.ipynb",
"chars": 94302,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"The World Cup Problem: Germany v. A"
},
{
"path": "world_cup_soln.ipynb",
"chars": 116399,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"## Bayesian Statistics Made Simple\\"
},
{
"path": "zigzag.ipynb",
"chars": 581704,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"Bayesian Zig Zag\\n\",\n \"===\\n\",\n "
},
{
"path": "zigzag2.ipynb",
"chars": 509849,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"# Bayesian Zig Zag\\n\",\n \"\\n\",\n "
},
{
"path": "zigzag3.ipynb",
"chars": 946974,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"# Bayesian Zig Zag\\n\",\n \"\\n\",\n "
}
]
About this extraction
This page contains the full source code of the AllenDowney/BayesMadeSimple GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 47 files (3.5 MB), approximately 917.5k tokens, and a symbol index with 744 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.