def variational_loss(self,<EOL>observations,<EOL>observation_index_points=None,<EOL>kl_weight=<NUM_LIT:1.>,<EOL>name='<STR_LIT>'):
with tf.name_scope(name or '<STR_LIT>'):<EOL><INDENT>if observation_index_points is None:<EOL><INDENT>observation_index_points = self._index_points<EOL><DEDENT>observation_index_points = tf.convert_to_tensor(<EOL>value=observation_index_points, dtype=self._dtype,<EOL>name='<STR_LIT>')<EOL>observations = tf.convert_to_tensor(<EOL>value=observations, dtype=self._dtype, name='<STR_LIT>')<EOL>kl_weight = tf.convert_to_tensor(<EOL>value=kl_weight, dtype=self._dtype,<EOL>name='<STR_LIT>')<EOL>kzx = self.kernel.matrix(self._inducing_index_points,<EOL>observation_index_points)<EOL>kzx_linop = tf.linalg.LinearOperatorFullMatrix(kzx)<EOL>loc = (self._mean_fn(observation_index_points) +<EOL>kzx_linop.matvec(self._kzz_inv_varloc, adjoint=True))<EOL>likelihood = independent.Independent(<EOL>normal.Normal(<EOL>loc=loc,<EOL>scale=tf.sqrt(self._observation_noise_variance + self._jitter),<EOL>name='<STR_LIT>'),<EOL>reinterpreted_batch_ndims=<NUM_LIT:1>)<EOL>obs_ll = likelihood.log_prob(observations)<EOL>chol_kzz_linop = tf.linalg.LinearOperatorLowerTriangular(self._chol_kzz)<EOL>chol_kzz_inv_kzx = chol_kzz_linop.solve(kzx)<EOL>kzz_inv_kzx = chol_kzz_linop.solve(chol_kzz_inv_kzx, adjoint=True)<EOL>kxx_diag = tf.linalg.diag_part(<EOL>self.kernel.matrix(<EOL>observation_index_points, observation_index_points))<EOL>ktilde_trace_term = (<EOL>tf.reduce_sum(input_tensor=kxx_diag, axis=-<NUM_LIT:1>) -<EOL>tf.reduce_sum(input_tensor=chol_kzz_inv_kzx ** <NUM_LIT:2>, axis=[-<NUM_LIT:2>, -<NUM_LIT:1>]))<EOL>other_trace_term = tf.reduce_sum(<EOL>input_tensor=(<EOL>self._variational_inducing_observations_posterior.scale.matmul(<EOL>kzz_inv_kzx) ** <NUM_LIT:2>),<EOL>axis=[-<NUM_LIT:2>, -<NUM_LIT:1>])<EOL>trace_term = (<NUM_LIT> * (ktilde_trace_term + other_trace_term) /<EOL>self._observation_noise_variance)<EOL>inducing_prior = gaussian_process.GaussianProcess(<EOL>kernel=self._kernel,<EOL>mean_fn=self._mean_fn,<EOL>index_points=self._inducing_index_points,<EOL>observation_noise_variance=self._observation_noise_variance)<EOL>kl_term = kl_weight * kullback_leibler.kl_divergence(<EOL>self._variational_inducing_observations_posterior,<EOL>inducing_prior)<EOL>lower_bound = (obs_ll - trace_term - kl_term)<EOL>return -tf.reduce_mean(input_tensor=lower_bound)<EOL><DEDENT>
Variational loss for the VGP.

        Given `observations` and `observation_index_points`, compute the
        negative variational lower bound as specified in [Hensman, 2013][1].

        Args:
          observations: `float` `Tensor` representing collection, or batch of
            collections, of observations corresponding to
            `observation_index_points`. Shape has the form `[b1, ..., bB, e]`, which
            must be brodcastable with the batch and example shapes of
            `observation_index_points`. The batch shape `[b1, ..., bB]` must be
            broadcastable with the shapes of all other batched parameters
            (`kernel.batch_shape`, `observation_index_points`, etc.).
          observation_index_points: `float` `Tensor` representing finite (batch of)
            vector(s) of points where observations are defined. Shape has the
            form `[b1, ..., bB, e1, f1, ..., fF]` where `F` is the number of feature
            dimensions and must equal `kernel.feature_ndims` and `e1` is the number
            (size) of index points in each batch (we denote it `e1` to distinguish
            it from the numer of inducing index points, denoted `e2` below). If
            set to `None` uses `index_points` as the origin for observations.
            Default value: None.
          kl_weight: Amount by which to scale the KL divergence loss between prior
            and posterior.
            Default value: 1.
          name: Python `str` name prefixed to Ops created by this class.
            Default value: "GaussianProcess".
        Returns:
          loss: Scalar tensor representing the negative variational lower bound.
            Can be directly used in a `tf.Optimizer`.
        Raises:
          ValueError: if `mean_fn` is not `None` and is not callable.

        #### References

        [1]: Hensman, J., Lawrence, N. "Gaussian Processes for Big Data", 2013
             https://arxiv.org/abs/1309.6835