code: def evaluate(
      metrics, data, n_samples=500, output_key=None, seed=None
  ):
      """Evaluate fitted model using a set of metrics.
  
      A metric, or scoring rule [@winkler1994evaluating], is a function of
      observed data under the posterior predictive distribution. For
      example in supervised metrics such as classification accuracy, the
      observed data (true output) is compared to the posterior
      predictive's mean (predicted output). In unsupervised metrics such
      as log-likelihood, the probability of observing the data is
      calculated under the posterior predictive's log-density.
  
      Args:
        metrics: list of str and/or (str, params: dict) tuples, str,
        or (str, params: dict) tuple.
          List of metrics or a single metric:
          `'binary_accuracy'`,
          `'categorical_accuracy'`,
          `'sparse_categorical_accuracy'`,
          `'log_loss'` or `'binary_crossentropy'`,
          `'categorical_crossentropy'`,
          `'sparse_categorical_crossentropy'`,
          `'hinge'`,
          `'squared_hinge'`,
          `'mse'` or `'MSE'` or `'mean_squared_error'`,
          `'mae'` or `'MAE'` or `'mean_absolute_error'`,
          `'mape'` or `'MAPE'` or `'mean_absolute_percentage_error'`,
          `'msle'` or `'MSLE'` or `'mean_squared_logarithmic_error'`,
          `'poisson'`,
          `'cosine'` or `'cosine_proximity'`,
          `'log_lik'` or `'log_likelihood'`.
          In lieu of a metric string, this method also accepts (str, params: dict)
          tuples; the first element of this tuple is the metric string, and
          the second is a dict of associated params. At present, this dict only
          expects one key, `'average'`, which stipulates the type of averaging to
          perform on those metrics that permit binary averaging. Permissible
          options include: `None`, `'macro'` and `'micro'`.
        data: dict.
          Data to evaluate model with. It binds observed variables (of type
          `RandomVariable` or `tf.Tensor`) to their realizations (of
          type `tf.Tensor`). It can also bind placeholders (of type
          `tf.Tensor`) used in the model to their realizations.
        n_samples: int.
          Number of posterior samples for making predictions, using the
          posterior predictive distribution.
        output_key: RandomVariable or tf.Tensor.
          It is the key in `data` which corresponds to the model's output.
        seed: a Python integer. Used to create a random seed for the
          distribution
  
      Returns:
        list of float or float.
        A list of evaluations or a single evaluation.
  
      Raises:
        NotImplementedError.
        If an input metric does not match an implemented metric in Edward.
  
      #### Examples
  
      ```python
      # build posterior predictive after inference: it is
      # parameterized by a posterior sample
      x_post = ed.copy(x, {z: qz, beta: qbeta})
  
      # log-likelihood performance
      ed.evaluate('log_likelihood', data={x_post: x_train})
  
      # classification accuracy
      # here, `x_ph` is any features the model is defined with respect to,
      # and `y_post` is the posterior predictive distribution
      ed.evaluate('binary_accuracy', data={y_post: y_train, x_ph: x_train})
  
      # mean squared error
      ed.evaluate('mean_squared_error', data={y: y_data, x: x_data})
      ```
  
      # mean squared logarithmic error with `'micro'` averaging
      ed.evaluate(('mean_squared_logarithmic_error', {'average': 'micro'}),
                  data={y: y_data, x: x_data})
      """
      sess = get_session()
      if isinstance(metrics, str):
          metrics = [metrics]
      elif callable(metrics):
          metrics = [metrics]
      elif not isinstance(metrics, list):
          raise TypeError(
              "metrics must have type str or list, or be callable."
          )
  
      check_data(data)
      if not isinstance(n_samples, int):
          raise TypeError("n_samples must have type int.")
  
      if output_key is None:
          # Default output_key to the only data key that isn't a placeholder.
          keys = [
              key
              for key in six.iterkeys(data)
              if not isinstance(key, tf.Tensor)
              or "Placeholder" not in key.op.type
          ]
          if len(keys) == 1:
              output_key = keys[0]
          else:
              raise KeyError("User must specify output_key.")
      elif not isinstance(output_key, RandomVariable):
          raise TypeError("output_key must have type RandomVariable.")
  
      # Create feed_dict for data placeholders that the model conditions
      # on; it is necessary for all session runs.
      feed_dict = {
          key: value
          for key, value in six.iteritems(data)
          if isinstance(key, tf.Tensor) and "Placeholder" in key.op.type
      }
  
      # Form true data.
      y_true = data[output_key]
      # Make predictions (if there are any supervised metrics).
      if metrics != ["log_lik"] and metrics != ["log_likelihood"]:
          binary_discrete = (Bernoulli, Binomial)
          categorical_discrete = (
              Categorical,
              Multinomial,
              OneHotCategorical,
          )
          total_count = sess.run(
              getattr(output_key, "total_count", tf.constant(1.0))
          )
          if isinstance(
              output_key, binary_discrete + categorical_discrete
          ):
              # Average over realizations of their probabilities, then predict
              # via argmax over probabilities.
              probs = [
                  sess.run(output_key.probs, feed_dict)
                  for _ in range(n_samples)
              ]
              probs = np.sum(probs, axis=0) / n_samples
              if isinstance(output_key, binary_discrete):
                  # make random prediction whenever probs is exactly 0.5
                  random = tf.random_uniform(shape=tf.shape(probs))
                  y_pred = tf.round(
                      tf.where(tf.equal(0.5, probs), random, probs)
                  )
              else:
                  if total_count > 1:
                      mode = compute_multinomial_mode(
                          probs, total_count, seed
                      )
                      if len(output_key.sample_shape):
                          y_pred = tf.reshape(
                              tf.tile(mode, output_key.sample_shape),
                              [-1, len(probs)],
                          )
                      else:
                          y_pred = mode
                  else:
                      y_pred = tf.argmax(probs, len(probs.shape) - 1)
              probs = tf.constant(probs)
          else:
              # Monte Carlo estimate the mean of the posterior predictive.
              y_pred = [
                  sess.run(output_key, feed_dict)
                  for _ in range(n_samples)
              ]
              y_pred = tf.cast(
                  tf.add_n(y_pred), y_pred[0].dtype
              ) / tf.cast(n_samples, y_pred[0].dtype)
          if len(y_true.shape) == 0:
              y_true = tf.expand_dims(y_true, 0)
              y_pred = tf.expand_dims(y_pred, 0)
  
      # Evaluate y_true (according to y_pred if supervised) for all metrics.
      evaluations = []
      for metric in metrics:
          if isinstance(metric, tuple):
              metric, params = metric
          else:
              params = {}
          if metric == "accuracy" or metric == "crossentropy":
              # automate binary or sparse cat depending on its support
              support = sess.run(tf.reduce_max(y_true), feed_dict)
              if support <= 1:
                  metric = "binary_" + metric
              else:
                  metric = "sparse_categorical_" + metric
  
          if metric == "binary_accuracy":
              evaluations += [binary_accuracy(y_true, y_pred, **params)]
          elif metric == "categorical_accuracy":
              evaluations += [
                  categorical_accuracy(y_true, y_pred, **params)
              ]
          elif metric == "sparse_categorical_accuracy":
              evaluations += [
                  sparse_categorical_accuracy(y_true, y_pred, **params)
              ]
          elif metric == "log_loss" or metric == "binary_crossentropy":
              evaluations += [
                  binary_crossentropy(y_true, y_pred, **params)
              ]
          elif metric == "categorical_crossentropy":
              evaluations += [
                  categorical_crossentropy(y_true, y_pred, **params)
              ]
          elif metric == "sparse_categorical_crossentropy":
              evaluations += [
                  sparse_categorical_crossentropy(
                      y_true, y_pred, **params
                  )
              ]
          elif metric == "multinomial_accuracy":
              evaluations += [
                  multinomial_accuracy(y_true, y_pred, **params)
              ]
          elif metric == "kl_divergence":
              y_true_ = y_true / total_count
              y_pred_ = probs
              evaluations += [kl_divergence(y_true_, y_pred_, **params)]
          elif metric == "hinge":
              evaluations += [hinge(y_true, y_pred, **params)]
          elif metric == "squared_hinge":
              evaluations += [squared_hinge(y_true, y_pred, **params)]
          elif (
              metric == "mse"
              or metric == "MSE"
              or metric == "mean_squared_error"
          ):
              evaluations += [
                  mean_squared_error(y_true, y_pred, **params)
              ]
          elif (
              metric == "mae"
              or metric == "MAE"
              or metric == "mean_absolute_error"
          ):
              evaluations += [
                  mean_absolute_error(y_true, y_pred, **params)
              ]
          elif (
              metric == "mape"
              or metric == "MAPE"
              or metric == "mean_absolute_percentage_error"
          ):
              evaluations += [
                  mean_absolute_percentage_error(
                      y_true, y_pred, **params
                  )
              ]
          elif (
              metric == "msle"
              or metric == "MSLE"
              or metric == "mean_squared_logarithmic_error"
          ):
              evaluations += [
                  mean_squared_logarithmic_error(
                      y_true, y_pred, **params
                  )
              ]
          elif metric == "poisson":
              evaluations += [poisson(y_true, y_pred, **params)]
          elif metric == "cosine" or metric == "cosine_proximity":
              evaluations += [
                  cosine_proximity(y_true, y_pred, **params)
              ]
          elif metric == "log_lik" or metric == "log_likelihood":
              # Monte Carlo estimate the log-density of the posterior predictive.
              tensor = tf.reduce_mean(output_key.log_prob(y_true))
              log_pred = [
                  sess.run(tensor, feed_dict) for _ in range(n_samples)
              ]
              log_pred = tf.add_n(log_pred) / tf.cast(
                  n_samples, tensor.dtype
              )
              evaluations += [log_pred]
          elif callable(metric):
              evaluations += [metric(y_true, y_pred, **params)]
          else:
              raise NotImplementedError(
                  "Metric is not implemented: {}".format(metric)
              )
  
      if len(evaluations) == 1:
          return sess.run(evaluations[0], feed_dict)
      else:
          return sess.run(evaluations, feed_dict)
  
imports: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  import numpy
  import six
  import tensorflow
  from edward.models import RandomVariable
  from edward.util import check_data, get_session, compute_multinomial_mode, with_binary_averaging
label_desc: Use image node_id 1 for calling a global function with example usage: evaluate(metrics, data, n_samples, output_key, seed) and returns: sess, sess