Search code examples
montecarlotensorflow2.0tensorflow-probability

Using tfp.mcmc.MetropolisHastings for physical model


I am new to Tensorflow and would like to use the Tensorflow Probability Library to model a physical problem. Tensorflow comes with the tfp.mcmc.MetropolisHastings function which is the algorithm I want to use.

I provided my initial distribution. In my case this is a 2d grid and on each grid point sits a 'spin' (the physics don't really matter right know) that can be either +1 or -1. The proposal of a new state x' should be the old grid with one of these spins flipped, so on one point +1 becomes -1 or vice versa. I can pass the step size argument, but my x is not a scalar I can simply increase. How do I model this? Is there a way I can pass an update rule that is not just increasing a value by a certain step size?


Solution

  • I just answered a similar question Perform a RandomWalk step with Tensorflow Probability's RandomWalkMetropolis function

    RandomWalkMetropolis accepts a constructor argument new_state_fn, which is a custom proposal function that consumes the previous state and returns a proposal.

    # TF/TFP Imports
    !pip install --quiet tfp-nightly tf-nightly
    import tensorflow.compat.v2 as tf
    tf.enable_v2_behavior()
    import tensorflow_probability as tfp
    tfd = tfp.distributions
    tfb = tfp.bijectors
    import matplotlib.pyplot as plt
    
    
    def log_prob(x):
      return tfd.Normal(0, 1).log_prob(x)
    
    def custom_proposal(state, extra):
      return state + tfd.Uniform(-.5, .75).sample()
    
    kernel = tfp.mcmc.RandomWalkMetropolis(log_prob, new_state_fn=custom_proposal)
    state = tfd.Normal(0, 1).sample()
    extra = kernel.bootstrap_results(state)
    samples = []
    for _ in range(1000):
      state, extra = kernel.one_step(state, extra)
      samples.append(state)
    
    plt.hist(samples, bins=20)