forked from capprogram/ModelFittingTutorial
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathzombies2.py.sln
97 lines (71 loc) · 3.94 KB
/
zombies2.py.sln
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
"""
Second Zombies Activity
Solutions Written by Katie Eckert
June 24, 2015
"""
import numpy as np
import matplotlib.pyplot as plt
import numpy.random as npr
import pylab
pylab.ion()
# a) Read in data and plot
datain=np.loadtxt("percentzombie.txt") # read in text file with data
time=datain[:,0] # load in time
perzombie=datain[:,1] # load in % zombies
perhuman=100-perzombie # calculate % human = (1- % zombie)
err=3.0 # assume 3% error on measurement of % zombies
# check lengths of arrays
print("time array has %f elements" %np.size(time))
print("percent human array has %f elements" %np.size(perhuman))
plt.figure(1)
plt.clf()
plt.plot(time,perhuman,'b*',markersize=10)
plt.xlabel('time')
plt.ylabel('% human')
plt.xlim(-15,15)
plt.ylim(0,100)
# tryout Bayesian analysis
# b) setup grids
testslope=np.arange(501)/100.-10 # I chose -10 to -5 in steps of 0.01
testyint=np.arange(101)/5.-4 # I chose from -4 to 16 in steps of 0.25
print("min/max slope are %f/%f" % (np.min(testslope),np.max(testslope)))
print("min/max y-intercept are %f/%f" % (np.min(testyint),np.max(testyint)))
# Want to have a prior that compensates for the unequal spacing in angle (rather than flat on slope and y-intercept): prior = (1+slope^2)^(-3/2)
lnpostprobout=np.zeros((np.size(testslope),np.size(testyint))) # setup array to hold posterior probabilities
for i in range(np.size(testslope)): # range over all slope
for j in range(np.size(testyint)): # range over all y-intercepts
modelperhuman=time*testslope[i]+testyint[j] # compute % human fit values for each model
residuals=perhuman-modelperhuman # compute residuals
chisq=np.sum((residuals)**2/err**2) # compute chi^2 for particular model
prior=(1.+testslope[i]**2)**(-3./2.) # compute prior for particular model
lnpostprobout[i,j]=-1.*chisq/2. + np.log(prior) # compute posterior probability for given model
# c) What is marginalized posterior distribution for the percentage of humans at t=0 (today)? We need the marginalized posterior distribution of the y-intercept, so we must marginalize over the slope
postprobout=np.exp(lnpostprobout)
# Marginalize over slope values to see y-intercept posterior distribution
marginalizedpprob_yint=np.sum(postprobout,axis=0)/np.sum(postprobout)
plt.figure(2)
plt.clf()
plt.plot(testyint,marginalizedpprob_yint,'r*',markersize=10)
plt.xlim(np.min(testyint),np.max(testyint))
plt.xlabel("% of humans alive today (t=0)")
plt.ylabel("marginalized posterior of % of humans alive today")
# likely ~5% humans still left as of today
# d) Since I am not a zombie yet, I can place a prior that total zombification (0% human) has not occured yet therefore I set my y-intercept grid space to start with at least 1% human left
testslope2=np.arange(501)/100.-10 # I chose -10 to -5 in steps of 0.01
testyint2=np.arange(101)/5.+1.0 # I chose from 1 to 20 in steps of 0.25
# Use the prior that compensates for the unequal angular spacing
# prior = (1+slope^2)^(-3/2)
lnpostprobout2=np.zeros((np.size(testslope2),np.size(testyint2)))
for i in range(np.size(testslope2)):
for j in range(np.size(testyint2)):
modelperhuman=time*testslope2[i]+testyint2[j]
residuals=perhuman-modelperhuman
chisq=np.sum((residuals)**2/err**2)
prior=(1.+testslope2[i]**2)**(-3./2.)
lnpostprobout2[i,j]=-1.*chisq/2. + np.log(prior)#
postprobout2=np.exp(lnpostprobout2)
#marginalize over slope values to see y-intercept
marginalizedpprob_yint2=np.sum(postprobout2,axis=0)/np.sum(postprobout2)
plt.plot(testyint2,marginalizedpprob_yint2,'g.',markersize=10)
# Now the marginalized posterior distribution is truncated at % of humans = 1 and the probabilities ~5% are larger than in the original y-intercept posterior distribution
# The marginalized posterior distribution for the % of humans left today (time=0) agrees with the MLE value for the % of humans at t=0 (~4.9%), as the distribution peaks near 5 (although we see there is a quite wide distribution from the Bayesian analysis).