class_docstr: Keras compatible data generator that wraps a Keras Sequence and provides corrupted
  data for training Deep Graph Infomax.
  
  Args:
      base_sequence: the uncorrupted Sequence object.
      corrupt_index_groups: the groups among which nodes will be shuffled (see :class:`.CorruptedGenerator` for more details)
      num_batch_dims: the number of axes that are "batch" dimensions
class_docstr_tok: ["Keras","compatible","data","generator","that","wraps","a","Keras","Sequence","and","provides","corrupted","data","for","training","Deep","Graph","Infomax",".","Args",":","base_sequence",":","the","uncorrupted","Sequence","object",".","corrupt_index_groups",":","the","groups","among","which","nodes","will","be","shuffled","(","see",":","class",":","`",".CorruptedGenerator","`","for","more","details",")","num_batch_dims",":","the","number","of","axes","that","are","``","batch","''","dimensions"]
code: def __getitem__(self, index):
      inputs, _ = self.base_sequence[index]
  
      def corrupt_group(group_idx, group):
          try:
              feats_orig = [inputs[idx] for idx in group]
          except IndexError:
              # Provide a better error for indices being out of bounds (doing it earlier/outside
              # `__getitem__` would require evaluating the base generator beforehand/non-lazily)
              invalid = [idx for idx in group if idx >= len(inputs)]
              raise ValueError(
                  f"corrupt_index_groups (group number {group_idx}): expected valid indices among the {len(inputs)} input tensors, found some too large: {comma_sep(invalid)}"
              )
  
          # this assumes that the input satisfies: last axis holds features for individual nodes;
          # all earlier axes are just arranging those nodes. In particular, a node shouldn't have
          # its features spread across multiple non-last axes, although it can appear more
          # than once.
          feature_dim = feats_orig[0].shape[-1]
          nodes_per_input = [
              np.product(feat.shape[:-1]) for feat in feats_orig
          ]
          sections = np.cumsum(nodes_per_input)
  
          feats_rank_2 = [
              feat.reshape(-1, feature_dim) for feat in feats_orig
          ]
          all_feats_shuffled = np.concatenate(feats_rank_2, axis=0)
          np.random.shuffle(all_feats_shuffled)
  
          feats_rank_2_shuffled = np.split(
              all_feats_shuffled, sections[:-1]
          )
  
          return (
              shuf.reshape(orig.shape)
              for shuf, orig in zip(feats_rank_2_shuffled, feats_orig)
          )
  
      shuffled_feats = [
          corrupted
          for group_idx, group in enumerate(self.corrupt_index_groups)
          for corrupted in corrupt_group(group_idx, group)
      ]
  
      # create the appropriate labels
      # we assume the smallest batch shape is the correct output shape
      # e.g. for fullbatch methods the correct output shape is (1, num_output_nodes) not (1, num_nodes_in_graph)
      # this is true for all current methods but might have to be re-evaluated in the future
      output_batch_shape = min(
          inp.shape[: self.num_batch_dims] for inp in inputs
      )
      targets = np.broadcast_to(
          [np.float32(1), 0], (*output_batch_shape, 2)
      )
  
      return shuffled_feats + inputs, targets
  
file_path: stellargraph/stellargraph/mapper/corrupted.py
imports: import numpy
  from tensorflow.keras.utils import Sequence
  from .None import Generator
  from ..core.validation import comma_sep
label_desc: Use image node_id 3 for calling the CorruptedSequence obj's underlying member method code with example usage: obj.__getitem__(index) and returns: unknown,  targets, unknown