class_docstr: Computes Mutual Information(MI) between each feature and the label.
  
  This statistic is the estimated Adjusted Mutual Information(AMI) between all
  features and the label. AMI prevents overestimation of MI for high entropy
  features. It is defined as MI(feature, labels) - MI(feature, shuffle(labels)).
  
  To use this statistic, use the `NonStreamingCustomStatsGenerator`. This
  generator can then be specified in the `stats_options` when calling
  `GenerateStatistics`.
  
  Example usage:
  ```
  generator = partitioned_stats_generator.NonStreamingCustomStatsGenerator(
    MutualInformation(...))
  ```
docstr: Computes MI and AMI between all valid features and labels.
  
  Args:
    examples_record_batch: Arrow record_batch containing a batch of examples.
  
  Returns:
    DatasetFeatureStatistics proto containing AMI and MI for each feature.
  
  Raises:
    ValueError: If label_feature does not exist in examples.
code: def compute(
      self, examples_record_batch: pa.RecordBatch
  ) -> statistics_pb2.DatasetFeatureStatistics:
      """Computes MI and AMI between all valid features and labels.
  
      Args:
        examples_record_batch: Arrow record_batch containing a batch of examples.
  
      Returns:
        DatasetFeatureStatistics proto containing AMI and MI for each feature.
  
      Raises:
        ValueError: If label_feature does not exist in examples.
      """
      if self._label_feature_is_unique(examples_record_batch):
          result = {}
          for feature_name in examples_record_batch.schema.names:
              feature_path = types.FeaturePath([feature_name])
              if feature_path != self._label_feature:
                  result[feature_path] = {self._custom_stats_key: 0.0}
          return stats_util.make_dataset_feature_stats_proto(result)
  
      encoded_examples = _encode_examples(
          examples_record_batch,
          self._multivalent_features,
          self._categorical_features,
          self._features_to_ignore,
          self._max_encoding_length,
      )
      if self._normalize_by_max:
          labels = encoded_examples[self._label_feature]
      else:
          labels = encoded_examples.pop(self._label_feature)
      mi_result = self._calculate_mi(
          encoded_examples, labels, self._seed
      )
      if self._normalize_by_max:
          mi_result = self._normalize_mi_values(mi_result)
      return stats_util.make_dataset_feature_stats_proto(mi_result)
  
imports: import collections
  from typing import Any, Dict, Iterable, List, Optional, Set, Tuple
  from absl import logging
  import apache_beam
  import numpy
  import pandas
  import pyarrow
  from tensorflow_data_validation import types
  from tensorflow_data_validation.statistics.generators import partitioned_stats_generator
  from tensorflow_data_validation.utils import feature_partition_util
  from tensorflow_data_validation.utils import mutual_information_util
  from tensorflow_data_validation.utils import schema_util
  from tensorflow_data_validation.utils import stats_util
  from tfx_bsl.arrow import array_util
  from tensorflow_metadata.proto.v0 import schema_pb2
  from tensorflow_metadata.proto.v0 import statistics_pb2
label_desc: Use image node_id 4 for calling the MutualInformation obj's underlying member method code with example usage: obj.compute(examples_record_batch) and returns: stats_util, stats_util