class_docstr: Implementation of a learned black-box membership inference attack.
  
  This implementation can use as input to the learning process probabilities/logits or losses,
  depending on the type of model and provided configuration.
docstr: Train the attack model.
  
  :param x: Records that were used in training the target estimator. Can be None if supplying `pred`.
  :param y: True labels for `x`. If not supplied, attack will be based solely on model predictions.
  :param test_x: Records that were not used in training the target estimator. Can be None if supplying
                 `test_pred`.
  :param test_y: True labels for `test_x`. If not supplied, attack will be based solely on model predictions.
  :param pred: Estimator predictions for the records, if not supplied will be generated by calling the estimators'
               `predict` function. Only relevant for input_type='prediction'.
  :param test_pred: Estimator predictions for the test records, if not supplied will be generated by calling the
                    estimators' `predict` function. Only relevant for input_type='prediction'.
  :return: An array holding the inferred membership status, 1 indicates a member and 0 indicates non-member.
docstr_tok: ["Train","the","attack","model",".",":","param","x",":","Records","that","were","used","in","training","the","target","estimator",".","Can","be","None","if","supplying","`","pred","`",".",":","param","y",":","True","labels","for","`","x","`",".","If","not","supplied",",","attack","will","be","based","solely","on","model","predictions",".",":","param","test_x",":","Records","that","were","not","used","in","training","the","target","estimator",".","Can","be","None","if","supplying","`","test_pred","`",".",":","param","test_y",":","True","labels","for","`","test_x","`",".","If","not","supplied",",","attack","will","be","based","solely","on","model","predictions",".",":","param","pred",":","Estimator","predictions","for","the","records",",","if","not","supplied","will","be","generated","by","calling","the","estimators'","`","predict","`","function",".","Only","relevant","for","input_type='prediction","'",".",":","param","test_pred",":","Estimator","predictions","for","the","test","records",",","if","not","supplied","will","be","generated","by","calling","the","estimators","'","`","predict","`","function",".","Only","relevant","for","input_type='prediction","'",".",":","return",":","An","array","holding","the","inferred","membership","status",",","1","indicates","a","member","and","0","indicates","non-member","."]
code: def fit(  # pylint: disable=W0613
      self,
      x: Optional[np.ndarray] = None,
      y: Optional[np.ndarray] = None,
      test_x: Optional[np.ndarray] = None,
      test_y: Optional[np.ndarray] = None,
      pred: Optional[np.ndarray] = None,
      test_pred: Optional[np.ndarray] = None,
      **kwargs,
  ):
      """
      Train the attack model.
  
      :param x: Records that were used in training the target estimator. Can be None if supplying `pred`.
      :param y: True labels for `x`. If not supplied, attack will be based solely on model predictions.
      :param test_x: Records that were not used in training the target estimator. Can be None if supplying
                     `test_pred`.
      :param test_y: True labels for `test_x`. If not supplied, attack will be based solely on model predictions.
      :param pred: Estimator predictions for the records, if not supplied will be generated by calling the estimators'
                   `predict` function. Only relevant for input_type='prediction'.
      :param test_pred: Estimator predictions for the test records, if not supplied will be generated by calling the
                        estimators' `predict` function. Only relevant for input_type='prediction'.
      :return: An array holding the inferred membership status, 1 indicates a member and 0 indicates non-member.
      """
      if x is None and pred is None:
          raise ValueError("Must supply either x or pred")
      if test_x is None and test_pred is None:
          raise ValueError("Must supply either test_x or test_pred")
  
      if self.estimator.input_shape is not None:
          if (
              x is not None
              and self.estimator.input_shape[0] != x.shape[1]
          ):  # pragma: no cover
              raise ValueError(
                  "Shape of x does not match input_shape of estimator"
              )
          if (
              test_x is not None
              and self.estimator.input_shape[0] != test_x.shape[1]
          ):  # pragma: no cover
              raise ValueError(
                  "Shape of test_x does not match input_shape of estimator"
              )
  
      if (
          y is not None
          and test_y is not None
          and not self._regressor_model
      ):
          y = check_and_transform_label_format(
              y,
              nb_classes=self.estimator.nb_classes,
              return_one_hot=True,
          )
          test_y = check_and_transform_label_format(
              test_y,
              nb_classes=self.estimator.nb_classes,
              return_one_hot=True,
          )
  
      if (
          x is not None and y is not None and y.shape[0] != x.shape[0]
      ):  # pragma: no cover
          raise ValueError("Number of rows in x and y do not match")
      if (
          pred is not None
          and y is not None
          and y.shape[0] != pred.shape[0]
      ):  # pragma: no cover
          raise ValueError("Number of rows in pred and y do not match")
      if (
          test_x is not None
          and test_y is not None
          and test_y.shape[0] != test_x.shape[0]
      ):  # pragma: no cover
          raise ValueError(
              "Number of rows in test_x and test_y do not match"
          )
      if (
          test_pred is not None
          and test_y is not None
          and test_y.shape[0] != test_pred.shape[0]
      ):  # pragma: no cover
          raise ValueError(
              "Number of rows in test_pred and test_y do not match"
          )
  
      # Create attack dataset
      # uses final probabilities/logits
      x_len = 0
      test_len = 0
      if pred is None and x is not None:
          x_len = x.shape[0]
      elif pred is not None:
          x_len = pred.shape[0]
      if test_pred is None and test_x is not None:
          test_len = test_x.shape[0]
      elif test_pred is not None:
          test_len = test_pred.shape[0]
  
      if self.input_type == "prediction":
          # members
          if pred is None:
              features = self.estimator.predict(x).astype(np.float32)
          else:
              features = pred.astype(np.float32)
          # non-members
          if test_pred is None:
              test_features = self.estimator.predict(test_x).astype(
                  np.float32
              )
          else:
              test_features = test_pred.astype(np.float32)
      # only for models with loss
      elif self.input_type == "loss":
          if y is None:
              raise ValueError("Cannot compute loss values without y.")
          if x is not None:
              # members
              features = (
                  self.estimator.compute_loss(x, y)
                  .astype(np.float32)
                  .reshape(-1, 1)
              )
          else:
              try:
                  features = (
                      self.estimator.compute_loss_from_predictions(
                          pred, y
                      )
                      .astype(np.float32)
                      .reshape(-1, 1)
                  )
              except NotImplementedError as err:
                  raise ValueError(
                      "For loss input type and no x, the estimator must implement 'compute_loss_from_predictions' "
                      "method"
                  ) from err
          if test_x is not None:
              # non-members
              test_features = (
                  self.estimator.compute_loss(test_x, test_y)
                  .astype(np.float32)
                  .reshape(-1, 1)
              )
          else:
              try:
                  test_features = (
                      self.estimator.compute_loss_from_predictions(
                          test_pred, test_y
                      )
                      .astype(np.float32)
                      .reshape(-1, 1)
                  )
              except NotImplementedError as err:
                  raise ValueError(
                      "For loss input type and no test_x, the estimator must implement "
                      "'compute_loss_from_predictions' method"
                  ) from err
      else:  # pragma: no cover
          raise ValueError("Illegal value for parameter `input_type`.")
  
      # members
      labels = np.ones(x_len)
      # non-members
      test_labels = np.zeros(test_len)
  
      x_1 = np.concatenate((features, test_features))
      x_2: Optional[np.ndarray] = None
      if y is not None and test_y is not None:
          x_2 = np.concatenate((y, test_y))
          if self._regressor_model and x_2 is not None:
              x_2 = x_2.astype(np.float32).reshape(-1, 1)
      y_new = np.concatenate((labels, test_labels))
      if x_2 is None:
          self.use_label = False
  
      if self.default_model and self.attack_model_type == "nn":
          import torch
          from torch import nn
          from torch import optim
          from torch.utils.data import DataLoader
          from art.utils import to_cuda
  
          if x_2 is not None:
  
              class MembershipInferenceAttackModel(nn.Module):
                  """
                  Implementation of a pytorch model for learning a membership inference attack.
  
                  The features used are probabilities/logits or losses for the attack training data along with
                  its true labels.
                  """
  
                  def __init__(self, num_classes, num_features=None):
                      self.num_classes = num_classes
                      if num_features:
                          self.num_features = num_features
                      else:
                          self.num_features = num_classes
  
                      super().__init__()
  
                      self.features = nn.Sequential(
                          nn.Linear(self.num_features, 512),
                          nn.ReLU(),
                          nn.Linear(512, 100),
                          nn.ReLU(),
                          nn.Linear(100, 64),
                          nn.ReLU(),
                      )
  
                      self.labels = nn.Sequential(
                          nn.Linear(self.num_classes, 256),
                          nn.ReLU(),
                          nn.Linear(256, 64),
                          nn.ReLU(),
                      )
  
                      self.combine = nn.Sequential(
                          nn.Linear(64 * 2, 1),
                      )
  
                      self.output = nn.Sigmoid()
  
                  def forward(self, x_1, label):
                      """Forward the model."""
                      out_x1 = self.features(x_1)
                      out_l = self.labels(label)
                      is_member = self.combine(
                          torch.cat((out_x1, out_l), 1)
                      )
                      return self.output(is_member)
  
              if self.input_type == "prediction":
                  num_classes = self.estimator.nb_classes  # type: ignore
                  self.attack_model = MembershipInferenceAttackModel(
                      num_classes
                  )
              else:  # loss
                  if self._regressor_model:
                      self.attack_model = (
                          MembershipInferenceAttackModel(
                              1, num_features=1
                          )
                      )
                  else:
                      num_classes = self.estimator.nb_classes  # type: ignore
                      self.attack_model = (
                          MembershipInferenceAttackModel(
                              num_classes, num_features=1
                          )
                      )
  
              loss_fn = nn.BCELoss()
              optimizer = optim.Adam(self.attack_model.parameters(), lr=self.learning_rate)  # type: ignore
  
              attack_train_set = self._get_attack_dataset(
                  f_1=x_1, f_2=x_2, label=y_new
              )
              train_loader = DataLoader(
                  attack_train_set,
                  batch_size=self.batch_size,
                  shuffle=True,
                  num_workers=0,
              )
  
              self.attack_model = to_cuda(self.attack_model)  # type: ignore
              self.attack_model.train()  # type: ignore
  
              for _ in range(self.epochs):
                  for input1, input2, targets in train_loader:
                      input1, input2, targets = (
                          to_cuda(input1),
                          to_cuda(input2),
                          to_cuda(targets),
                      )
                      _, input2 = torch.autograd.Variable(
                          input1
                      ), torch.autograd.Variable(input2)
                      targets = torch.autograd.Variable(targets)
  
                      optimizer.zero_grad()
                      outputs = self.attack_model(input1, input2)  # type: ignore
                      loss = loss_fn(outputs, targets.unsqueeze(1))
  
                      loss.backward()
                      optimizer.step()
          else:  # no label
  
              class MembershipInferenceAttackModelNoLabel(nn.Module):
                  """
                  Implementation of a pytorch model for learning a membership inference attack.
  
                  The features used are probabilities/logits or losses for the attack training data along with
                  its true labels.
                  """
  
                  def __init__(self, num_features):
                      self.num_features = num_features
  
                      super().__init__()
  
                      self.features = nn.Sequential(
                          nn.Linear(self.num_features, 512),
                          nn.ReLU(),
                          nn.Linear(512, 100),
                          nn.ReLU(),
                          nn.Linear(100, 64),
                          nn.ReLU(),
                          nn.Linear(64, 1),
                      )
  
                      self.output = nn.Sigmoid()
  
                  def forward(self, x_1):
                      """Forward the model."""
                      out_x1 = self.features(x_1)
                      return self.output(out_x1)
  
              num_classes = self.estimator.nb_classes  # type: ignore
              self.attack_model = MembershipInferenceAttackModelNoLabel(
                  num_classes
              )
  
              loss_fn = nn.BCELoss()
              optimizer = optim.Adam(self.attack_model.parameters(), lr=self.learning_rate)  # type: ignore
  
              attack_train_set = self._get_attack_dataset_no_label(
                  f_1=x_1, label=y_new
              )
              train_loader = DataLoader(
                  attack_train_set,
                  batch_size=self.batch_size,
                  shuffle=True,
                  num_workers=0,
              )
  
              self.attack_model = to_cuda(self.attack_model)  # type: ignore
              self.attack_model.train()  # type: ignore
  
              for _ in range(self.epochs):
                  for input1, targets in train_loader:
                      input1, targets = to_cuda(input1), to_cuda(
                          targets
                      )
                      input1 = torch.autograd.Variable(input1)
                      targets = torch.autograd.Variable(targets)
  
                      optimizer.zero_grad()
                      outputs = self.attack_model(input1)  # type: ignore
                      loss = loss_fn(outputs, targets.unsqueeze(1))
  
                      loss.backward()
                      optimizer.step()
  
      else:  # not nn
          y_ready = check_and_transform_label_format(
              y_new, nb_classes=2, return_one_hot=False
          )
          if x_2 is not None:
              self.attack_model.fit(np.c_[x_1, x_2], y_ready.ravel())  # type: ignore
          else:
              self.attack_model.fit(x_1, y_ready.ravel())
  
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import logging
  from typing import Any, Optional, Union, TYPE_CHECKING
  import numpy
  from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
  from sklearn.linear_model import LogisticRegression
  from sklearn.neighbors import KNeighborsClassifier
  from sklearn.tree import DecisionTreeClassifier
  from sklearn.svm import SVC
  from art.attacks.attack import MembershipInferenceAttack
  from art.estimators.estimator import BaseEstimator
  from art.estimators.classification.classifier import ClassifierMixin
  from art.estimators.regression import RegressorMixin
  from art.utils import check_and_transform_label_format
label_desc: Use image node_id 2 for calling the MembershipInferenceBlackBox obj's underlying member method code with example usage: obj.fit(x, y, test_x, test_y, pred, test_pred) and returns: self, self