Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
| Download

📚 The CoCalc Library - books, templates and other resources

Views: 96160
License: OTHER
1
"""This file contains code used in "Think Stats",
2
by Allen B. Downey, available from greenteapress.com
3
4
Copyright 2013 Allen B. Downey
5
License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html
6
"""
7
8
import thinkbayes
9
import thinkplot
10
11
from math import exp
12
13
"""This file contains a solution to an exercise from Think Bayes,
14
by Allen B. Downey
15
16
I got the idea from Tom Campbell-Ricketts author of the Maximum
17
Entropy blog at
18
19
http://maximum-entropy-blog.blogspot.com
20
21
And he got the idea from E.T. Jaynes, author of the classic
22
_Probability Theory: The Logic of Science_.
23
24
Here's the version from Think Bayes:
25
26
Radioactive decay is well modeled by a Poisson process; the
27
probability that an atom decays is the same at any point in time.
28
29
Suppose that a radioactive source emits particles toward a Geiger
30
counter at an average rate of $r$ particles per second, but the
31
counter only registers a fraction, $f$, of the particles that hit it.
32
If $f$ is 10\% and the counter registers 15 particles in a one second
33
interval, what is the posterior distribution of $n$, the actual number
34
of particles that hit the counter, and $p$, the average rate particles
35
are emitted?
36
37
"""
38
39
FORMATS = ['pdf', 'eps', 'png']
40
41
class Emitter(thinkbayes.Suite):
42
"""Represents hypotheses about r."""
43
44
def __init__(self, rs, f=0.1):
45
"""Initializes the Suite.
46
47
rs: sequence of hypothetical emission rates
48
f: fraction of particles registered
49
"""
50
detectors = [Detector(r, f) for r in rs]
51
thinkbayes.Suite.__init__(self, detectors)
52
53
def Update(self, data):
54
"""Updates the Suite based on data.
55
56
data: number of particles counted
57
"""
58
thinkbayes.Suite.Update(self, data)
59
60
for detector in self.Values():
61
detector.Update()
62
63
def Likelihood(self, data, hypo):
64
"""Likelihood of the data given the hypothesis.
65
66
Args:
67
data: number of particles counted
68
hypo: emission rate, r
69
70
Returns:
71
probability density of the data under the hypothesis
72
"""
73
detector = hypo
74
like = detector.SuiteLikelihood(data)
75
return like
76
77
def DistOfR(self, name=''):
78
"""Returns the PMF of r."""
79
items = [(detector.r, prob) for detector, prob in self.Items()]
80
return thinkbayes.MakePmfFromItems(items, name=name)
81
82
def DistOfN(self, name=''):
83
"""Returns the PMF of n."""
84
return thinkbayes.MakeMixture(self, name=name)
85
86
87
class Emitter2(thinkbayes.Suite):
88
"""Represents hypotheses about r."""
89
90
def __init__(self, rs, f=0.1):
91
"""Initializes the Suite.
92
93
rs: sequence of hypothetical emission rates
94
f: fraction of particles registered
95
"""
96
detectors = [Detector(r, f) for r in rs]
97
thinkbayes.Suite.__init__(self, detectors)
98
99
def Likelihood(self, data, hypo):
100
"""Likelihood of the data given the hypothesis.
101
102
Args:
103
data: number of counted per unit time
104
hypo: emission rate, r
105
106
Returns:
107
probability density of the data under the hypothesis
108
"""
109
return hypo.Update(data)
110
111
def DistOfR(self, name=''):
112
"""Returns the PMF of r."""
113
items = [(detector.r, prob) for detector, prob in self.Items()]
114
return thinkbayes.MakePmfFromItems(items, name=name)
115
116
def DistOfN(self, name=''):
117
"""Returns the PMF of n."""
118
return thinkbayes.MakeMixture(self, name=name)
119
120
121
class Detector(thinkbayes.Suite):
122
"""Represents hypotheses about n."""
123
124
def __init__(self, r, f, high=500, step=5):
125
"""Initializes the suite.
126
127
r: known emission rate, r
128
f: fraction of particles registered
129
high: maximum number of particles, n
130
step: step size between hypothetical values of n
131
"""
132
pmf = thinkbayes.MakePoissonPmf(r, high, step=step)
133
thinkbayes.Suite.__init__(self, pmf, name=r)
134
self.r = r
135
self.f = f
136
137
def Likelihood(self, data, hypo):
138
"""Likelihood of the data given the hypothesis.
139
140
data: number of particles counted
141
hypo: number of particles hitting the counter, n
142
"""
143
k = data
144
n = hypo
145
p = self.f
146
147
return thinkbayes.EvalBinomialPmf(k, n, p)
148
149
def SuiteLikelihood(self, data):
150
"""Adds up the total probability of the data under the suite.
151
152
data: number of particles counted
153
"""
154
total = 0
155
for hypo, prob in self.Items():
156
like = self.Likelihood(data, hypo)
157
total += prob * like
158
return total
159
160
161
def main():
162
k = 15
163
f = 0.1
164
165
# plot Detector suites for a range of hypothetical r
166
thinkplot.PrePlot(num=3)
167
for r in [100, 250, 400]:
168
suite = Detector(r, f, step=1)
169
suite.Update(k)
170
thinkplot.Pmf(suite)
171
print suite.MaximumLikelihood()
172
173
thinkplot.Save(root='jaynes1',
174
xlabel='Number of particles (n)',
175
ylabel='PMF',
176
formats=FORMATS)
177
178
# plot the posterior distributions of r and n
179
hypos = range(1, 501, 5)
180
suite = Emitter2(hypos, f=f)
181
suite.Update(k)
182
183
thinkplot.PrePlot(num=2)
184
post_r = suite.DistOfR(name='posterior r')
185
post_n = suite.DistOfN(name='posterior n')
186
187
thinkplot.Pmf(post_r)
188
thinkplot.Pmf(post_n)
189
190
thinkplot.Save(root='jaynes2',
191
xlabel='Emission rate',
192
ylabel='PMF',
193
formats=FORMATS)
194
195
196
if __name__ == '__main__':
197
main()
198
199