code: def create_attacker_data(
      attack_input_data: data_structures.AttackInputData,
      balance: bool = True,
  ) -> AttackerData:
      """Prepare AttackInputData to train ML attackers.
  
      Combines logits and losses and performs a random train-test split.
  
      Args:
        attack_input_data: Original AttackInputData
        balance: Whether the training and test sets for the membership inference
          attacker should have a balanced (roughly equal) number of samples from the
          training and test sets used to develop the model under attack.
  
      Returns:
        AttackerData.
      """
      attack_input_train = _column_stack(
          attack_input_data.logits_or_probs_train,
          attack_input_data.get_loss_train(),
      )
      attack_input_test = _column_stack(
          attack_input_data.logits_or_probs_test,
          attack_input_data.get_loss_test(),
      )
  
      ntrain, ntest = (
          attack_input_train.shape[0],
          attack_input_test.shape[0],
      )
      features_all = np.concatenate(
          (attack_input_train, attack_input_test)
      )
      labels_all = np.concatenate((np.ones(ntrain), np.zeros(ntest)))
      if attack_input_data.has_nonnull_sample_weights():
          sample_weights_all = np.concatenate(
              (
                  attack_input_data.sample_weight_train,
                  attack_input_data.sample_weight_test,
              ),
              axis=0,
          )
      else:
          sample_weights_all = None
  
      fold_indices = np.arange(ntrain + ntest)
      left_out_indices = np.asarray([], dtype=np.int32)
  
      if balance:
          idx_train, idx_test = range(ntrain), range(
              ntrain, ntrain + ntest
          )
          min_size = min(ntrain, ntest)
          if ntrain > min_size:
              left_out_size = ntrain - min_size
              perm_train = np.random.permutation(
                  idx_train
              )  # shuffle training
              left_out_indices = perm_train[:left_out_size]
              fold_indices = np.concatenate(
                  (perm_train[left_out_size:], idx_test)
              )
          elif ntest > min_size:
              left_out_size = ntest - min_size
              perm_test = np.random.permutation(
                  idx_test
              )  # shuffle test
              left_out_indices = perm_test[:left_out_size]
              fold_indices = np.concatenate(
                  (perm_test[left_out_size:], idx_train)
              )
  
      # Shuffle indices for the downstream attackers.
      fold_indices = np.random.permutation(fold_indices)
  
      return AttackerData(
          features_all=features_all,
          labels_all=labels_all,
          sample_weights_all=sample_weights_all,
          fold_indices=fold_indices,
          left_out_indices=left_out_indices,
          data_size=data_structures.DataSize(
              ntrain=ntrain, ntest=ntest
          ),
      )
  
imports: import contextlib
  import dataclasses
  import logging
  from typing import Optional
  import numpy
  from sklearn import ensemble
  from sklearn import linear_model
  from sklearn import model_selection
  from sklearn import neighbors
  from sklearn import neural_network
  from sklearn.utils import parallel_backend
  from tensorflow_privacy.privacy.privacy_tests.membership_inference_attack import data_structures
label_desc: Use image node_id 1 for calling a global function with example usage: create_attacker_data(attack_input_data, balance) and returns: AttackerData