Having trouble setting up basic HMC model

Hey all–my apologies for the newbie question, but I’m having some trouble setting up even a pretty basic model using HMC. Here’s the code I’m having trouble with:

import numpy as np
import tensorflow as tf
from edward.models import Normal, Empirical
import edward as ed

X_train = np.array([[ 0.87024415,  0.65901989],
       [ 0.09892046,  0.92157853],
       [ 0.34324086,  0.7804544 ],
       [ 0.19976632,  0.90515983],
       [ 0.75492591,  0.50158632],
       [ 0.41315702,  0.63009453],
       [ 0.40734398,  0.74817169],
       [ 0.85471708,  0.69424045],
       [ 0.14578448,  0.95430565],
       [ 0.51036876,  0.63925266]], dtype=np.float32)

y_train = np.array([[-0.1065    ],
       [-0.005     ],
       [ 0.0488    ],
       [ 0.0714    ],
       [-0.0192    ],
       [ 0.0944    ],
       [ 0.        ],
       [-0.0888    ],
       [ 0.0392    ],
       [-0.73610002]], dtype=np.float32)

layer_1_size = 10

W_0 = Normal(loc = tf.zeros([2,layer_1_size]), scale = tf.ones([2,layer_1_size]))
W_1 = Normal(loc = tf.zeros([layer_1_size,1]), scale = tf.ones([layer_1_size,1]))
b_0 = Normal(loc = tf.zeros(layer_1_size), scale = tf.ones(layer_1_size))
b_1 = Normal(loc = tf.zeros(1), scale = tf.ones(1))

x = tf.placeholder(dtype=np.float32)

y = Normal(loc = tf.matmul(tf.tanh(tf.matmul(x, W_0) + b_0), W_1) + b_1,
           scale = 0.1)

T = 10000
ydata = tf.constant(np.repeat([y_train],T,axis=0))

qy = Empirical(params = ydata)
inference = ed.HMC({y: qy}, data = {x: X_train})
inference.run(n_iter=10000)

When I run that, I get:

---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-122-8793699b40bc> in <module>()
----> 1 inference.run(n_iter=10000)

/home/matthew/anaconda3/envs/edward/lib/python3.6/site-packages/edward/inferences/inference.py in run(self, variables, use_coordinator, *args, **kwargs)
    114       Passed into ``initialize``.
    115     """
--> 116     self.initialize(*args, **kwargs)
    117 
    118     if variables is None:

/home/matthew/anaconda3/envs/edward/lib/python3.6/site-packages/edward/inferences/hmc.py in initialize(self, step_size, n_steps, *args, **kwargs)
     62     self.n_steps = n_steps
     63     self.scope_iter = 0  # a convenient counter for log joint calculations
---> 64     return super(HMC, self).initialize(*args, **kwargs)
     65 
     66   def build_update(self):

/home/matthew/anaconda3/envs/edward/lib/python3.6/site-packages/edward/inferences/monte_carlo.py in initialize(self, *args, **kwargs)
     96     self.n_accept = tf.Variable(0, trainable=False, name="n_accept")
     97     self.n_accept_over_t = self.n_accept / self.t
---> 98     self.train = self.build_update()
     99 
    100   def update(self, feed_dict=None):

/home/matthew/anaconda3/envs/edward/lib/python3.6/site-packages/edward/inferences/hmc.py in build_update(self)
    113     assign_ops = []
    114     for z, qz in six.iteritems(self.latent_vars):
--> 115       variable = qz.get_variables()[0]
    116       assign_ops.append(tf.scatter_update(variable, self.t, sample[z]))
    117 

IndexError: list index out of range

I have no idea what list is even being accessed here. All the dimensions seem right but maybe I’ve got something wrong:

ydata
<tf.Tensor 'Const_112:0' shape=(10000, 10, 1) dtype=float32>

qy
<ed.RandomVariable 'Empirical_74/' shape=(10, 1) dtype=float32>

Incidentally, is my understanding of Empirical correct that I should be setting up a tf.constant tensor with the number of desired samples as the first dimension, with the target data repeated for each one?

Thanks very much for any assistance you can provide!

Matt

1 Like

Before delving into code, it’s useful to reason about what your model is and what it means to infer hidden structure from your model via a posterior distribution.

In your example, you wrote a Bayesian neural network with likelihood y given x, and with weight and bias parameters W_0,W_1,b_0,b_1. You then set up data xdata and ydata.

To perform inference means to calculate a distribution over the weights and biases given the data. In particular, with something like HMC, you should set up Empirical distributions that each approximate W_0,W_1,b_0,b_1 respectively. For more background, I recommend the pages linked to in http://edwardlib.org/tutorials/.

So I guess based on your answer that I’m having some sort of fundamental misunderstanding about what the function of the Empirical distributions is in your examples. I’m coming from a PyMC background so I may be making some unfounded assumptions about how the syntax works. Here, I was attempting to place standard normal priors on W_0, W_1, b_0, and b_1, and then draw inference given x and y. I had assumed that y: qy (with qy filled with the observed values) was the way to get edward to treat y as a likelihood rather than as a prior, like setting the observed=True flag in PyMC (and then putting the observed values of y in qy). But it sounds like instead the Empiricals are used for holding the HMC samples from the posterior for the unknown parameters?

Yes.

To treat y as data, you simply pass it into the corresponding argument during inference:

inference = ed.HMC({W_0: qW_0, b_0: qb_0,
                    W_1: qW_1, b_1: qb_1,
                    W_2: qW_2, b_2: qb_2}, data={X: X_train, y: y_train})

where q* are all the Empirical approximations. See the inference API for more details. For this example, a useful reference is the examples/bayesian_nn.py script in the Github repository.

2 Likes

Ah, excellent, thank you!