Metropolis proposal dist

Hi
Does anyone have an example of using the proposal_dist argument in the metropolis sampler ?
I’d like to use some domain knowledge and provide random samples from a different pdf (there is a good reason to do this) as jump proposals in this chain. It’s not clear to me if this is possible here ?
Thanks
Rhys

You can do something like the following:

import pymc3 as pm
from pymc3.step_methods.metropolis import Proposal


class MyCustomProposal(Proposal):
    def __call__(self):
        # do whatever you need. Notice self.s has the state of the
        # proposal instance


with pm.Model():
    # define variables
    proposal_state = # something appropriate
    step = pm.Metropolis(vars, proposal_dist=MyCustomProposal(proposal_state))

You can checkout the source code of Metropolis to see how the default NormalProposal or MultivariateNormalProposal are constructed to gain more intuition.

2 Likes

Hi Thanks for the reply !
So i’d effectively like to make the proposal independent of the current position, I notice in the metropolis sampler it is effectively:
new_proposal = current point + proposal_dist()

Do you think the best way to avoid this to to hack Metropolis step so that we have:
new_proposal = proposal_dist() ?

or can i do something in MyCustomProposal(Proposal) like :
def __call__self() :
return my_proposal - current_pos

This could then be supplied to the metropolis step as the current_pos would cancel out.

Thanks
Rhys

What you do is likely resulting quite poor proposal and, more importantly, invalid proposal as detail balance is not guaranteed (unless the proposal is uniform).

Hi
This proposal will be based around some domain knowledge for the parameter space, I’m also aware that I will need to carefully balance the jump probability.
I suppose my current question is mostly based around whether or not a proposal_dist can take current position as an argument ? or whether I’m better off adjusting the metropolis step function ?
Thanks again
Rhys

In that case, I dont think you can use the metropolis kernel directly, as the proposal distribution does not take current value. You will need to build your own sampler - I think you can copy the code from Metropolis and do new_proposal = proposal_dist()

Great thanks for your help !