code: def prepare_labels_and_predictions(
      labels: Any,
      predictions: Any,
      prediction_key: Optional[str] = None,
      label_vocabulary: Optional[Union[np.ndarray, List[str]]] = None,
  ) -> Tuple[np.ndarray, np.ndarray]:
      """Prepares labels and predictions for use in calculations.
  
      If the predictions are a dict (i.e. estimator based output) this function will
      apply the necessary lookup based on the prediction_key provided (or using a
      default set of common keys such as 'probabilities', etc). Note that the
      predictions passed as args must be AFTER the model_name and/or output_name
      lookups have been performed. This function also applies any label vocabulary
      transformations where possible.
  
      If successful, the final output of calling this function will be a pair of
      numpy arrays representing the labels and predictions.
  
      Args:
        labels: List, np.ndarray, or SparseTensorValue of values (1D, 2D, or 3D).
        predictions: List or np.ndarray of prediction values (1D, 2D, or 3D) or a
          dict of prediction values keyed by prediction_key or common estimator keys
          (logistic, probabilties, etc).
        prediction_key: Optional predictions key. Used when the predict output is a
          dict.
        label_vocabulary: Optional label vocabulary to convert label values to ints
          (if prediction is a dict containing an 'all_classes' key that will be used
          if label_vocabulary is None).
  
      Returns:
        A (labels, predictions) tuple suitable for metric calculations.
  
      Raises:
        ValueError: If the labels or predictions are in an invalid format.
      """
      if isinstance(predictions, Mapping):
          if label_vocabulary is None:
              if _ALL_CLASSES in predictions:
                  # Check for use of estimator label vocab under ALL_CLASSES. This was
                  # added in 06/2019 for eval signatures because the CLASSES only contains
                  # the label for the chosen class.
                  label_vocabulary = util.to_numpy(
                      predictions[_ALL_CLASSES]
                  )
              elif (
                  tf.saved_model.CLASSIFY_OUTPUT_SCORES in predictions
                  and tf.saved_model.CLASSIFY_OUTPUT_CLASSES
                  in predictions
              ):
                  # For classification model using the default serving signature, the
                  # CLASSES contains the full vocabulary. The check for scores is needed
                  # here to avoid matching CLASSES in the eval case (scores are not used
                  # in eval).
                  label_vocabulary = util.to_numpy(
                      predictions[
                          tf.saved_model.CLASSIFY_OUTPUT_CLASSES
                      ]
                  )
              if label_vocabulary is not None:
                  while len(label_vocabulary.shape) > 1:
                      label_vocabulary = label_vocabulary[
                          0
                      ]  # Remove the bach dimensions
          if not prediction_key:
              # Estimator predictions use dicts of scores, probabilities, classes, etc.
              for k in (
                  tf.saved_model.CLASSIFY_OUTPUT_SCORES,
                  tf.saved_model.REGRESS_OUTPUTS,
                  _PREDICTIONS,
                  _LOGISTIC,
                  _PROBABILITIES,
                  _LOGITS,
              ):
                  if k in predictions:
                      predictions = predictions[k]
                      prediction_key = k
                      break
          elif prediction_key in predictions:
              predictions = predictions[prediction_key]
  
      if isinstance(predictions, Mapping):
          raise ValueError(
              "unable to prepare prediction for metric computation because the "
              "prediction is a dict with unrecognized keys. If a multi-output model "
              "was used check that an output name was provided in all the relevant "
              "settings (MetricsSpec.output_names, etc). If the model returns a dict "
              "for its output and the output does not contain one of the common "
              "prediction keys (e.g. logistic, probabilities, etc), then "
              "ModelSpec.prediction_key can be used to specify which key to use for "
              f"the predicted value: prediction={predictions}, "
              f"prediction_key={prediction_key}"
          )
  
      if predictions is not None:
          predictions = util.to_numpy(predictions)
  
      def _maybe_convert_labels_to_one_hot(labels, predictions):
          # String lookups that fail result in a -1 label value. Most metrics
          # won't accept this as a valid value so we convert to a one_hot value to
          # ensure that we are only working with 0's (i.e. -1 maps to all 0's in
          # one-hot).
          if labels.size and np.all(labels == -1):
              return one_hot(labels, predictions)
          return labels
  
      if labels is not None:
          if isinstance(labels, types.SparseTensorValue) or isinstance(
              labels, tf.compat.v1.SparseTensorValue
          ):
              if predictions is None or predictions.size == 0:
                  raise ValueError(
                      "predictions must also be used if labels are of type "
                      f"SparseTensorValue: labels={labels}"
                  )
              values = (
                  labels.values
                  if labels.values is not None
                  else np.array([])
              )
              indices = (
                  labels.indices
                  if labels.indices is not None
                  else np.array([])
              )
              if (
                  label_vocabulary is not None
                  and values.dtype.kind in ("U", "S", "O")
              ):
                  values = _string_labels_to_class_ids(
                      label_vocabulary, values
                  )
                  # If vocab is used then the values will be the indices into the vocab
                  # and we should use multi-hot encoding to store the output. We can
                  # accomplish this by passing 1's for the values and using the values
                  # converted from the vocab as the indices to insert the 1's at the
                  # proper offsets in the resulting multi-hot vector.
                  labels = _to_dense_tensor(
                      np.ones(values.shape), values, predictions.shape
                  )
                  labels = _maybe_convert_labels_to_one_hot(
                      labels, predictions
                  )
              else:
                  labels = _to_dense_tensor(
                      values, indices, predictions.shape
                  )
          else:
              labels = util.to_numpy(labels)
              if (
                  label_vocabulary is not None
                  and labels.dtype.kind in ("U", "S", "O")
              ):
                  labels = _string_labels_to_class_ids(
                      label_vocabulary, labels
                  )
                  labels = _maybe_convert_labels_to_one_hot(
                      labels, predictions
                  )
  
      return (labels, predictions)
  
imports: import inspect
  import math
  from typing import Any, Callable, Dict, Iterable, Iterator, List, Mapping, Optional, Tuple, Union
  import numpy
  import tensorflow
  from tensorflow_model_analysis import constants
  from tensorflow_model_analysis.api import types
  from tensorflow_model_analysis.metrics import metric_types
  from tensorflow_model_analysis.proto import config_pb2
  from tensorflow_model_analysis.utils import util
  from tensorflow_metadata.proto.v0 import schema_pb2
label_desc: Use image node_id 20 for calling a global function with example usage: prepare_labels_and_predictions(labels, predictions, prediction_key, label_vocabulary) and returns: labels,  predictions, labels, one_hot