pymc ignores the step method that I assign to its nodes.

173 views
Skip to first unread message

Imri Sofer

unread,
Apr 17, 2011, 9:55:49 PM4/17/11
to PyMC
I'm banging my head over this problem all day long. I must be doing
something wrong, but I don't know what it is.
I'm trying to understand why pymc ignores the step method that I
assign to its nodes.


I'm giving here an example using the simplest model ever:

import pymc as pm
N = 1000
x = pm.Uniform('x',-5000,5000, value=0)
m = pm.MCMC([x])
m.sample(1)
m.use_step_method(pm.Metropolis, x, proposal_distribution='Normal',
proposal_sd=1e6)
m.sample(N)
print m.step_method_dict.values()[0][-1].rejected
print x.trace()[:100]


as you can see I create one uniform node and assign a step method with
a hugh sd, so 99% of the proposal would be rejected.


here is the output:
In [47]: print m.step_method_dict.values()[0][-1].rejected
997.0

In [48]: print x.trace()[:50]
[ 3442.67788695 2033.11489349 -2549.58320627 2932.89968053
4518.14156487
-2394.07659712 -3580.3190195 2388.50488069 2034.75494386
-3838.60653186
-3348.58442394 2675.90040551 -1706.82287753 -587.25579854
-3256.67045278
-2255.34554667 1976.7180825 -950.53105221 -2515.26276015
-1243.70333464
-2132.76127171 -3202.86044163 -1943.56651286 1620.25422363
-602.1990391
-3762.14177766 1714.18532211 -4147.28690771 -2259.15863226
4515.19159652
-247.41388043 -2701.40578817 -1407.93389678 4989.32340339
-937.9434862
-3800.10522499 3309.6579381 2658.78396874 -2687.28336492
-2753.15356777
-1229.33151387 -318.88022136 -1921.34358368 -2667.40462231
828.79420248
-789.42083546 -1956.81516587 3405.03038185 -3868.31267845
1141.42214429]



according to m.step_method_dict.values()[0][-1] (which is the step
method I've assigned), 99.7% of proposals were rejected. but according
to the trace none was rejected. the trace was actually sampled from
the uniform distribution. The step method that I assigned was
completely ignored.
Why is that?

thanks
Imri



Chris Fonnesbeck

unread,
Apr 18, 2011, 11:55:07 AM4/18/11
to PyMC
Hi Imri,

This has to do with the fact that there are no data associated with
your model in this example. So, the Stochastic ends up with two
StepMethods, rather than just one -- the DrawFromPrior method is
sticky, in that sense. This is because it does not make much sense to
assign any other method to a dataless model, since there is no
likelihood. The prior is all that exists, so you just sample from it.

cf

Imri Sofer

unread,
Apr 18, 2011, 2:32:09 PM4/18/11
to PyMC
Hi Chris,
thank you for your replay.
I added an observed node but the sampler still ignore my step method.
it seems that the sampler ignore new step methods after it sampled for
the first time.

in the first part of the following code I change the step method and
then sample, and everything is working as expected. In the second part
I initialize the model, sample once, and then try different sampling
method which do not affect the sampler, the only effect I can notice
is a reduction in the number of rejected samples (instead of
increment) which is probably due to tuning.


import pymc as pm
from pylab import *
import sys
N = 500
sds = [0.001, 0.1, 10 ,1e6]
data = randn(50)


##### First Part
print "**** using step method before sampling for the first time ****"
for i_sd in sds:
x = pm.Uniform('x',-5000,5000, value=0)
y = pm.Normal('y', mu=x, tau=1, value=data, observed=True)
m = pm.MCMC([x,y])
m.use_step_method(pm.Metropolis, x,
proposal_distribution='Normal', proposal_sd=i_sd)
m.sample(N, progress_bar=False)
print "**** used prposal_sd=%f" % i_sd
print "precent of rejected samples: %f" % (sum(diff(x.trace()
[:])==0)*1./N)
print
sys.stdout.flush()


###### Second Part
x = pm.Uniform('x',-5000,5000, value=0)
y = pm.Normal('y', mu=x, tau=1, value=data, observed=True)
m = pm.MCMC([x,y])
m.sample(1, progress_bar=False) #!#!#!#!#!#!#!#! taking one sample

print "**** changing the step method after sampling ****"
for i_sd in sds:
m.use_step_method(pm.Metropolis, x,
proposal_distribution='Normal', proposal_sd=i_sd)
m.sample(N, progress_bar=False)
print "**** used prposal_sd=%f" % i_sd
print "precent of rejected samples: %f" % (sum(diff(x.trace()
[:])==0)*1./N)
print



output:
**** using step method before sampling for the first time ****
**** used prposal_sd=0.001000
precent of rejected samples: 0.000000

**** used prposal_sd=0.100000
precent of rejected samples: 0.200000

**** used prposal_sd=10.000000
precent of rejected samples: 0.978000

**** used prposal_sd=1000000.000000
precent of rejected samples: 0.998000

**** changing the step method after sampling ****
**** used prposal_sd=0.001000
precent of rejected samples: 0.632000

**** used prposal_sd=0.100000
precent of rejected samples: 0.578000

**** used prposal_sd=10.000000
precent of rejected samples: 0.476000

**** used prposal_sd=1000000.000000
precent of rejected samples: 0.360000

Anand Patil

unread,
May 5, 2011, 6:22:52 AM5/5/11
to PyMC
Hi all,

The use_step_method method never removes a step method, it only adds
new ones... so at the end of the second part, you have five step
methods assigned to x. One automatically assigned by the first call to
sample(), and one for each element of sds. However, none of them are
DrawFromPrior.

We don't have a remove_step_method method at the moment.

Cheers
Anand

Imri Sofer

unread,
May 5, 2011, 7:39:49 AM5/5/11
to PyMC
Hi Anand,
I may be wrong here, but it seems to me from your answer that what I
have reported is not a bug. is that true?
if it is the case, then how do I assign a step method to a node after
samples were drawn from it? use_step_method does not seems to do that.

thank you,
Imri


On May 5, 6:22 am, Anand Patil <anand.prabhakar.pa...@gmail.com>
wrote:

Anand Patil

unread,
May 5, 2011, 7:48:56 AM5/5/11
to py...@googlegroups.com
Hi Imri,

use_step_method does, it just doesn't take away the old step methods. In your example, all five step methods get to update x during the MCMC. That's the intended behavior, so not a bug.

We don't have a remove_step_method method currently, because it isn't hard to change your code so that the step method you really want is in place before automatic assignment... just move use_step_method to before M.sample(1).

If there's a good reason why remove_step_method is needed, please explain on the issues page.

Cheers,
Anand

--
You received this message because you are subscribed to the Google Groups "PyMC" group.
To post to this group, send email to py...@googlegroups.com.
To unsubscribe from this group, send email to pymc+uns...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/pymc?hl=en.


Imri Sofer

unread,
May 5, 2011, 9:28:56 AM5/5/11
to py...@googlegroups.com
I don't see a good reason to add remove_step_method.
I just think that the average user could encounter problems when the behavior I described is the default behavior of the Sampler. This is what happend to me.
I was working for a whole day trying to make my model to converge (not that simple toy model in my post, something a little bit  more complex). I played with a few step methods and different parameters, and couldn't get the model to converge. After waisting too many hours on it, I discovered that none of my changes were successful because not even one of them was actually used by the Sampler, because of its default behavior. I was assigning the step method after samples were drawn.

I think the default behavior can cause problem to some of the users because:
1) some of them may think (I know I did) that if your model does not mix properly and you would like to switch one of the step methods, you could just do it without the need of  initializing the model.
2) The sampler does not raise an error or disregard the step method, but append it to the step_method_dict, which can seems to the average user as if the sampler is using it.

Anand Patil

unread,
May 5, 2011, 10:07:19 AM5/5/11
to py...@googlegroups.com
Hi Imri,

I can see how that would have been confusing. Please consider adding an example to https://github.com/pymc-devs/pymc/wiki to help other people who encounter the same situation.

Cheers,
Anand
Reply all
Reply to author
Forward
0 new messages