@@ -510,8 +510,8 @@ class DEMetropolis(PopulationArrayStepShared):
510
510
S (and n). Defaults to Uniform(-S,+S).
511
511
scaling : scalar or array
512
512
Initial scale factor for epsilon. Defaults to 0.001
513
- tune : bool
514
- Flag for tuning the scaling . Defaults to True .
513
+ tune : str
514
+ Which hyperparameter to tune . Defaults to None, but can also be 'scaling' or 'lambda' .
515
515
tune_interval : int
516
516
The frequency of tuning. Defaults to 100 iterations.
517
517
model : PyMC Model
@@ -536,10 +536,11 @@ class DEMetropolis(PopulationArrayStepShared):
536
536
'accepted' : np .bool ,
537
537
'tune' : np .bool ,
538
538
'scaling' : np .float64 ,
539
+ 'lambda' : np .float64 ,
539
540
}]
540
541
541
542
def __init__ (self , vars = None , S = None , proposal_dist = None , lamb = None , scaling = 0.001 ,
542
- tune = True , tune_interval = 100 , model = None , mode = None , ** kwargs ):
543
+ tune = None , tune_interval = 100 , model = None , mode = None , ** kwargs ):
543
544
544
545
model = pm .modelcontext (model )
545
546
@@ -549,7 +550,7 @@ def __init__(self, vars=None, S=None, proposal_dist=None, lamb=None, scaling=0.0
549
550
550
551
if S is None :
551
552
S = np .ones (model .ndim )
552
-
553
+
553
554
if proposal_dist is not None :
554
555
self .proposal_dist = proposal_dist (S )
555
556
else :
@@ -559,6 +560,8 @@ def __init__(self, vars=None, S=None, proposal_dist=None, lamb=None, scaling=0.0
559
560
if lamb is None :
560
561
lamb = 2.38 / np .sqrt (2 * model .ndim )
561
562
self .lamb = float (lamb )
563
+ if not tune in {None , 'scaling' , 'lambda' }:
564
+ raise ValueError ('The parameter "tune" must be one of {None, scaling, lambda}' )
562
565
self .tune = tune
563
566
self .tune_interval = tune_interval
564
567
self .steps_until_tune = tune_interval
@@ -572,9 +575,10 @@ def __init__(self, vars=None, S=None, proposal_dist=None, lamb=None, scaling=0.0
572
575
573
576
def astep (self , q0 ):
574
577
if not self .steps_until_tune and self .tune :
575
- # Tune scaling parameter
576
- self .scaling = tune (
577
- self .scaling , self .accepted / float (self .tune_interval ))
578
+ if self .tune == 'scaling' :
579
+ self .scaling = tune (self .scaling , self .accepted / float (self .tune_interval ))
580
+ elif self .tune == 'lambda' :
581
+ self .lamb = tune (self .lamb , self .accepted / float (self .tune_interval ))
578
582
# Reset counter
579
583
self .steps_until_tune = self .tune_interval
580
584
self .accepted = 0
@@ -598,6 +602,7 @@ def astep(self, q0):
598
602
stats = {
599
603
'tune' : self .tune ,
600
604
'scaling' : self .scaling ,
605
+ 'lambda' : self .lamb ,
601
606
'accept' : np .exp (accept ),
602
607
'accepted' : accepted
603
608
}
0 commit comments