# Buggy code
def prob_is_largest(self, Y, mu, var, gh_x, gh_w):
    # work out what the mean and variance is of the indicated latent function.
    oh_on = tf.cast(
        tf.one_hot(tf.reshape(Y, (-1,)), self.num_classes, 1.0, 0.0), tf.float64
    )
    mu_selected = tf.reduce_sum(oh_on * mu, 1)
    var_selected = tf.reduce_sum(oh_on * var, 1)

    # generate Gauss Hermite grid
    X = tf.reshape(mu_selected, (-1, 1)) + gh_x * tf.reshape(
        tf.sqrt(tf.clip_by_value(2.0 * var_selected, 1e-10, np.inf)), (-1, 1)
    )

    # compute the CDF of the Gaussian between the latent functions and the grid (including the selected function)
    dist = (tf.expand_dims(X, 1) - tf.expand_dims(mu, 2)) / tf.expand_dims(
        tf.sqrt(tf.clip_by_value(var, 1e-10, np.inf)), 2
    )
    cdfs = 0.5 * (1.0 + tf.erf(dist / np.sqrt(2.0)))

    cdfs = cdfs * (1 - 2e-4) + 1e-4

    # blank out all the distances on the selected latent function
    oh_off = tf.cast(
        tf.one_hot(tf.reshape(Y, (-1,)), self.num_classes, 0.0, 1.0), tf.float64
    )
    cdfs = cdfs * tf.expand_dims(oh_off, 2) + tf.expand_dims(oh_on, 2)

    # take the product over the latent functions, and the sum over the GH grid.
    return tf.matmul(
        tf.reduce_prod(cdfs, 1), tf.reshape(gh_w / np.sqrt(np.pi), (-1, 1))
    )


# Traceback (ValueError)
python
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-5-e4eebd086840> in <module>()
1 m.kern.white.variance.fixed = True
2 m.Z.fixed = True
----> 3 _ = m.optimize()

/Users/danmarthaler/GPflow/GPflow/model.pyc in optimize(self, method, tol, callback, maxiter, **kw)
207
208         if type(method) is str:
--> 209             return self._optimize_np(method, tol, callback, maxiter, **kw)
210         else:
211             return self._optimize_tf(method, callback, maxiter, **kw)

/Users/danmarthaler/GPflow/GPflow/model.pyc in _optimize_np(self, method, tol, callback, maxiter, **kw)
265         """
266         if self._needs_recompile:
--> 267             self._compile()
268
269         options = dict(disp=True, maxiter=maxiter)

/Users/danmarthaler/GPflow/GPflow/model.pyc in _compile(self, optimizer)
127         with self.tf_mode():
128             f = self.build_likelihood() + self.build_prior()
--> 129             g, = tf.gradients(f, self._free_vars)
130
131         self._minusF = tf.neg(f, name='objective')

/usr/local/lib/python2.7/site-packages/tensorflow/python/ops/gradients.pyc in gradients(ys, xs, grad_ys, name, colocate_gradients_with_ops, gate_gradients, aggregation_method)
476                 # If grad_fn was found, do not use SymbolicGradient even for
477                 # functions.
--> 478                 in_grads = _AsList(grad_fn(op, *out_grads))
479               else:
480                 # For function call ops, we add a 'SymbolicGradient'

/usr/local/lib/python2.7/site-packages/tensorflow/python/ops/math_grad.pyc in _ProdGrad(op, grad)
128   reduced = math_ops.cast(op.inputs[1], dtypes.int32)
129   idx = math_ops.range(0, array_ops.rank(op.inputs[0]))
--> 130   other, _ = array_ops.listdiff(idx, reduced)
131   perm = array_ops.concat(0, [reduced, other])
132   reduced_num = math_ops.reduce_prod(array_ops.gather(input_shape, reduced))

/usr/local/lib/python2.7/site-packages/tensorflow/python/ops/gen_array_ops.pyc in list_diff(x, y, name)
1199     idx: A `Tensor` of type `int32`. 1-D. Positions of `x` values preserved in `out`.
1200   """
-> 1201   result = _op_def_lib.apply_op("ListDiff", x=x, y=y, name=name)
1202   return _ListDiffOutput._make(result)
1203

/usr/local/lib/python2.7/site-packages/tensorflow/python/framework/op_def_library.pyc in apply_op(self, op_type_name, name, **keywords)
701           op = g.create_op(op_type_name, inputs, output_types, name=scope,
702                            input_types=input_types, attrs=attr_protos,
--> 703                            op_def=op_def)
704           outputs = op.outputs
705           return _Restructure(ops.convert_n_to_tensor(outputs),

/usr/local/lib/python2.7/site-packages/tensorflow/python/framework/ops.pyc in create_op(self, op_type, inputs, dtypes, input_types, name, attrs, op_def, compute_shapes, compute_device)
2310                     original_op=self._default_original_op, op_def=op_def)
2311     if compute_shapes:
-> 2312       set_shapes_for_outputs(ret)
2313     self._add_op(ret)
2314     self._record_op_seen_by_control_dependencies(ret)

/usr/local/lib/python2.7/site-packages/tensorflow/python/framework/ops.pyc in set_shapes_for_outputs(op)
1702       raise RuntimeError("No shape function registered for standard op: %s"
1703                          % op.type)
-> 1704   shapes = shape_func(op)
1705   if shapes is None:
1706     raise RuntimeError(

/usr/local/lib/python2.7/site-packages/tensorflow/python/ops/array_ops.pyc in _ListDiffShape(op)
1979   """Shape function for the ListDiff op."""
1980   op.inputs[0].get_shape().assert_has_rank(1)
-> 1981   op.inputs[1].get_shape().assert_has_rank(1)
1982   # TODO(mrry): Indicate that the length falls within an interval?
1983   return [tensor_shape.vector(None)] * 2

/usr/local/lib/python2.7/site-packages/tensorflow/python/framework/tensor_shape.pyc in assert_has_rank(self, rank)
619     """
620     if self.ndims not in (None, rank):
--> 621       raise ValueError("Shape %s must have rank %d" % (self, rank))
622
623   def with_rank(self, rank):

ValueError: Shape () must have rank 1

# Fixed code
def prob_is_largest(self, Y, mu, var, gh_x, gh_w):
    # work out what the mean and variance is of the indicated latent function.
    oh_on = tf.cast(
        tf.one_hot(tf.reshape(Y, (-1,)), self.num_classes, 1.0, 0.0), tf.float64
    )
    mu_selected = tf.reduce_sum(oh_on * mu, 1)
    var_selected = tf.reduce_sum(oh_on * var, 1)

    # generate Gauss Hermite grid
    X = tf.reshape(mu_selected, (-1, 1)) + gh_x * tf.reshape(
        tf.sqrt(tf.clip_by_value(2.0 * var_selected, 1e-10, np.inf)), (-1, 1)
    )

    # compute the CDF of the Gaussian between the latent functions and the grid (including the selected function)
    dist = (tf.expand_dims(X, 1) - tf.expand_dims(mu, 2)) / tf.expand_dims(
        tf.sqrt(tf.clip_by_value(var, 1e-10, np.inf)), 2
    )
    cdfs = 0.5 * (1.0 + tf.erf(dist / np.sqrt(2.0)))

    cdfs = cdfs * (1 - 2e-4) + 1e-4

    # blank out all the distances on the selected latent function
    oh_off = tf.cast(
        tf.one_hot(tf.reshape(Y, (-1,)), self.num_classes, 0.0, 1.0), tf.float64
    )
    cdfs = cdfs * tf.expand_dims(oh_off, 2) + tf.expand_dims(oh_on, 2)

    # take the product over the latent functions, and the sum over the GH grid.
    return tf.matmul(
        tf.reduce_prod(cdfs, reduction_indices=[1]),
        tf.reshape(gh_w / np.sqrt(np.pi), (-1, 1)),
    )