1
+ import numpy as np
1
2
import theano
2
3
import scipy
3
4
import theano .tensor as tt
7
8
from .ops import RandomVariable , param_supp_shape_fn
8
9
9
10
10
- # Continuous Numpy-generated variates
11
11
class UniformRVType (RandomVariable ):
12
12
print_name = ("U" , "\\ operatorname{U}" )
13
13
@@ -71,10 +71,19 @@ class GammaRVType(RandomVariable):
71
71
print_name = ("Gamma" , "\\ operatorname{Gamma}" )
72
72
73
73
def __init__ (self ):
74
- super ().__init__ ("gamma" , theano .config .floatX , 0 , [0 , 0 ], "gamma" , inplace = True )
74
+ super ().__init__ (
75
+ "gamma" ,
76
+ theano .config .floatX ,
77
+ 0 ,
78
+ [0 , 0 ],
79
+ lambda rng , shape , rate , size : scipy .stats .gamma .rvs (
80
+ shape , scale = 1.0 / rate , size = size , random_state = rng
81
+ ),
82
+ inplace = True ,
83
+ )
75
84
76
- def make_node (self , shape , scale , size = None , rng = None , name = None ):
77
- return super ().make_node (shape , scale , size = size , rng = rng , name = name )
85
+ def make_node (self , shape , rate , size = None , rng = None , name = None ):
86
+ return super ().make_node (shape , rate , size = size , rng = rng , name = name )
78
87
79
88
80
89
GammaRV = GammaRVType ()
@@ -93,20 +102,27 @@ def make_node(self, scale, size=None, rng=None, name=None):
93
102
ExponentialRV = ExponentialRVType ()
94
103
95
104
96
- # One with multivariate support
97
105
class MvNormalRVType (RandomVariable ):
98
106
print_name = ("N" , "\\ operatorname{N}" )
99
107
100
108
def __init__ (self ):
101
109
super ().__init__ (
102
- "multivariate_normal" ,
103
- theano .config .floatX ,
104
- 1 ,
105
- [1 , 2 ],
106
- "multivariate_normal" ,
107
- inplace = True ,
110
+ "multivariate_normal" , theano .config .floatX , 1 , [1 , 2 ], self ._smpl_fn , inplace = True ,
108
111
)
109
112
113
+ @classmethod
114
+ def _smpl_fn (cls , rng , mean , cov , size ):
115
+ res = np .atleast_1d (
116
+ scipy .stats .multivariate_normal (mean = mean , cov = cov , allow_singular = True ).rvs (
117
+ size = size , random_state = rng
118
+ )
119
+ )
120
+
121
+ if size is not None :
122
+ res = res .reshape (list (size ) + [- 1 ])
123
+
124
+ return res
125
+
110
126
def make_node (self , mean , cov , size = None , rng = None , name = None ):
111
127
return super ().make_node (mean , cov , size = size , rng = rng , name = name )
112
128
@@ -127,7 +143,6 @@ def make_node(self, alpha, size=None, rng=None, name=None):
127
143
DirichletRV = DirichletRVType ()
128
144
129
145
130
- # A discrete Numpy-generated variate
131
146
class PoissonRVType (RandomVariable ):
132
147
print_name = ("Pois" , "\\ operatorname{Pois}" )
133
148
@@ -141,7 +156,6 @@ def make_node(self, rate, size=None, rng=None, name=None):
141
156
PoissonRV = PoissonRVType ()
142
157
143
158
144
- # A SciPy-generated variate
145
159
class CauchyRVType (RandomVariable ):
146
160
print_name = ("C" , "\\ operatorname{C}" )
147
161
@@ -191,12 +205,14 @@ def __init__(self):
191
205
theano .config .floatX ,
192
206
0 ,
193
207
[0 , 0 , 0 ],
194
- lambda rng , * args : scipy .stats .invgamma .rvs (* args , random_state = rng ),
208
+ lambda rng , shape , rate , size : scipy .stats .invgamma .rvs (
209
+ shape , scale = rate , size = size , random_state = rng
210
+ ),
195
211
inplace = True ,
196
212
)
197
213
198
- def make_node (self , a , loc = 0.0 , scale = 1.0 , size = None , rng = None , name = None ):
199
- return super ().make_node (a , loc , scale , size = size , rng = rng , name = name )
214
+ def make_node (self , shape , rate = 1.0 , size = None , rng = None , name = None ):
215
+ return super ().make_node (shape , rate , size = size , rng = rng , name = name )
200
216
201
217
202
218
InvGammaRV = InvGammaRVType ()
@@ -277,9 +293,14 @@ def make_node(self, n, a, b, size=None, rng=None, name=None):
277
293
BetaBinomialRV = BetaBinomialRVType ()
278
294
279
295
280
- # Support shape is determined by the first dimension in the *second* parameter
281
- # (i.e. the probabilities vector)
282
296
class MultinomialRVType (RandomVariable ):
297
+ """A Multinomial random variable type.
298
+
299
+ FYI: Support shape is determined by the first dimension in the *second*
300
+ parameter (i.e. the probabilities vector).
301
+
302
+ """
303
+
283
304
print_name = ("MN" , "\\ operatorname{MN}" )
284
305
285
306
def __init__ (self ):
0 commit comments