1 """
2 This module implements classes to represent an arbitrary Bayesian random variable.
3
4 """
5
6
7 from numpy import arange,compress, array, exp
8 import like, sys
9 import pylab as P
10 from scipy import stats
11
12
13
14 conjlist = [
15 'bernoulli',
16 'binom',
17 'nbinom',
18 'poisson',
19 'geom',
20 ]
21
22
23 -def Continuous(priortype,pars, range,resolution=1024):
24 return __BayesC(priortype,pars, range,resolution)
25
26 -def Discrete(priortype,pars, range,resolution=1024):
27 return __BayesD(priortype,pars, range,resolution)
28
30 """
31 Bayesian random variate.
32 """
33 - def __init__(self, disttype,pars, rang,resolution=1024):
34 '''
35 Initializes random variable.
36
37 :parameters:
38 - `disttype`: must be a valid RNG from scipy.stats
39 - `pars`: are the parameters of the distribution.
40 - `rang`: range of the variable support.
41 - `resolution`: resolution of the support.
42 '''
43 self.distn = dist_type.name
44 self._flavorize(disttype(*pars), disttype)
45 self.pars = pars
46 self.rang = rang
47 self.res = (rang[1]-rang[0])*1./resolution
48 self.likefun = self._Likelihood(self.distn)
49 self.likelihood = None
50 self.data = []
51 self.posterior=array([])
52
54 '''
55 Add methods from distribution type
56 '''
57 self.cdf = pt.cdf
58 self.isf = pt.isf
59 if isinstance(ptbase,stats.rv_continuous):
60 self.pdf = pt.pdf
61 elif isinstance(ptbase,stats.rv_discrete):
62 self.pdf = pt.pmf
63 else: sys.exit('Invalid distribution object')
64 self.ppf = pt.ppf
65 self.rvs = pt.rvs
67 """
68 Calculate likelihood function
69 """
70 if self.data:
71 d = self.data[-1]
72 sc = self.pars[1]
73 m = self.rang[0]
74 M = self.rang[1]
75 step = self.res
76
77 lik = exp(array([self.likefun((d,i,sc)) for i in arange(m,M,step)]))
78 self.likelihood = lik/sum(lik)
79
81 """
82 Adds dataset to variable's data store
83 """
84 self.data.append(array(data))
85 self._update()
86
88 '''
89 Returns a sample from the prior distribution
90
91 :Parameters:
92 - `n`: Sample size.
93 '''
94 return self.rvs(size=n)
95
97 """
98 Returns the prior PDF.
99 """
100 return self.pdf(arange(self.rang[0],self.rang[1],self.res))
101
102 - def getPosteriorSample(self, n):
103 """
104 Return a sample of the posterior distribution.
105 Uses SIR algorithm.
106
107 :Parameters:
108 - `n`: Sample size.
109 """
110 if self.posterior.any():
111 k= stats.kde.gausian_kde(self.posterior)
112 s= k.resample(n)
113 else:
114 s = self.getPriorSample(n)
115 if self.data:
116 m = self.rang[0]
117 M = self.rang[1]
118 step = self.res
119 supp = arange(m,M,step)
120 s = compress(less(s.ravel(),M) & greater(s.ravel(),m),s)
121 d = stats.uniform.rvs(loc=0,scale=1,size=len(s))
122 w = self.pdf(supp)*self.likelihood
123 w = w/sum(w)
124 sx = searchsorted(supp,s)
125 w = w[sx-1]
126 post = compress(d<w,s)
127 self.posterior = post
128 return post
129 else:
130 return array([])
131
133 '''
134 Defines parametric family of the likelihood function.
135 Returns likelihood function.
136
137 :Parameters:
138 - `typ`: must be a string.
139 '''
140
141 if typ == 'norm':
142 return lambda(x):like.Normal(x[0],x[1],1./x[2])
143 elif typ == 'expon':
144 return lambda(x):(1./x[2])**x[0].size*exp(-(1./x[2])*sum(x[0]))
145 elif typ == 'beta':
146 return lambda(x):like.Beta(x[0],x[1],x[2])
147
148 - def _postFromConjugate(dname,*pars):
149 '''
150 Returns posterior distribution function using conjugate prior theory
151 '''
152 if not self.data:
153 return
154 if dname == 'bernoulli':
155 pdist = stats.beta(pars[0])
156
157
158 -class __BayesC(_BayesVar, stats.rv_continuous):
159 - def __init__(self, priortype,pars, range,resolution=512):
161
162 -class __BayesD(_BayesVar, stats.rv_discrete):
163 - def __init__(self, priortype,pars, range,resolution=512):
165 if __name__=="__main__":
166
167 bv = Continuous(stats.norm,(3,1),range=(0,5), resolution=1000)
168 data = ones(10)
169 bv.addData(data)
170 p = bv.getPosteriorSample(200000)
171 P.plot(arange(bv.rang[0],bv.rang[1], bv.res),bv.likelihood/max(bv.likelihood), 'ro', lw=2)
172 P.plot(arange(bv.rang[0],bv.rang[1], bv.res),bv.getPriorDist(),'g+',lw=2)
173 P.hist(p, normed=1)
174 P.legend(['Likelihood','Prior', 'Posterior'])
175 P.title('Bayesian inference')
176 P.savefig('bayesvar.png',dpi=400)
177 P.show()
178