1
1
import numpy as np
2
2
import numpy .random as nr
3
3
import theano
4
+ import scipy .linalg
4
5
5
6
from ..distributions import draw_values
6
7
from .arraystep import ArrayStepShared , ArrayStep , metrop_select , Competence
@@ -41,8 +42,16 @@ def __call__(self):
41
42
42
43
43
44
class MultivariateNormalProposal (Proposal ):
45
+ def __init__ (self , s ):
46
+ n , m = s .shape
47
+ if n != m :
48
+ raise ValueError ("Covariance matrix is not symmetric." )
49
+ self .n = n
50
+ self .chol = scipy .linalg .cholesky (s , lower = True )
51
+
44
52
def __call__ (self , num_draws = None ):
45
- return nr .multivariate_normal (mean = np .zeros (self .s .shape [0 ]), cov = self .s , size = num_draws )
53
+ b = np .random .randn (self .n )
54
+ return np .dot (self .chol , b )
46
55
47
56
48
57
class Metropolis (ArrayStepShared ):
@@ -76,7 +85,7 @@ class Metropolis(ArrayStepShared):
76
85
'tune' : np .bool ,
77
86
}]
78
87
79
- def __init__ (self , vars = None , S = None , proposal_dist = NormalProposal , scaling = 1. ,
88
+ def __init__ (self , vars = None , S = None , proposal_dist = None , scaling = 1. ,
80
89
tune = True , tune_interval = 100 , model = None , mode = None , ** kwargs ):
81
90
82
91
model = pm .modelcontext (model )
@@ -87,7 +96,16 @@ def __init__(self, vars=None, S=None, proposal_dist=NormalProposal, scaling=1.,
87
96
88
97
if S is None :
89
98
S = np .ones (sum (v .dsize for v in vars ))
90
- self .proposal_dist = proposal_dist (S )
99
+
100
+ if proposal_dist is not None :
101
+ self .proposal_dist = proposal_dist (S )
102
+ elif S .ndim == 1 :
103
+ self .proposal_dist = NormalProposal (S )
104
+ elif S .ndim == 2 :
105
+ self .proposal_dist = MultivariateNormalProposal (S )
106
+ else :
107
+ raise ValueError ("Invalid rank for variance: %s" % S .ndim )
108
+
91
109
self .scaling = np .atleast_1d (scaling )
92
110
self .tune = tune
93
111
self .tune_interval = tune_interval
0 commit comments