class_docstr: Implementation of the MIFace algorithm from Fredrikson et al. (2015). While in that paper the attack is demonstrated
  specifically against face recognition models, it is applicable more broadly to classifiers with continuous features
  which expose class gradients.
  
  | Paper link: https://dl.acm.org/doi/10.1145/2810103.2813677
class_docstr_tok: ["Implementation","of","the","MIFace","algorithm","from","Fredrikson","et","al",".","(","2015",")",".","While","in","that","paper","the","attack","is","demonstrated","specifically","against","face","recognition","models",",","it","is","applicable","more","broadly","to","classifiers","with","continuous","features","which","expose","class","gradients",".","|","Paper","link",":","https",":","\/\/dl.acm.org\/doi\/10.1145\/2810103.2813677"]
docstr: Extract a thieved classifier.
  
  :param x: An array with the initial input to the victim classifier. If `None`, then initial input will be
            initialized as zero array.
  :param y: Target values (class labels) one-hot-encoded of shape (nb_samples, nb_classes) or indices of shape
            (nb_samples,).
  :return: The inferred training samples.
docstr_tok: ["Extract","a","thieved","classifier",".",":","param","x",":","An","array","with","the","initial","input","to","the","victim","classifier",".","If","`","None","`",",","then","initial","input","will","be","initialized","as","zero","array",".",":","param","y",":","Target","values","(","class","labels",")","one-hot-encoded","of","shape","(","nb_samples",",","nb_classes",")","or","indices","of","shape","(","nb_samples",",",")",".",":","return",":","The","inferred","training","samples","."]
code: def infer(
      self,
      x: Optional[np.ndarray],
      y: Optional[np.ndarray] = None,
      **kwargs,
  ) -> np.ndarray:
      """
      Extract a thieved classifier.
  
      :param x: An array with the initial input to the victim classifier. If `None`, then initial input will be
                initialized as zero array.
      :param y: Target values (class labels) one-hot-encoded of shape (nb_samples, nb_classes) or indices of shape
                (nb_samples,).
      :return: The inferred training samples.
      """
      if x is None and y is None:
          raise ValueError("Either `x` or `y` should be provided.")
  
      if y is None:
          y = get_labels_np_array(
              self.estimator.predict(x, batch_size=self.batch_size)
          )
      else:
          y = check_and_transform_label_format(
              y, nb_classes=self.estimator.nb_classes
          )
  
      if x is None:
          x = np.zeros((len(y),) + self.estimator.input_shape)
  
      x_infer = x.astype(ART_NUMPY_DTYPE)
  
      # Compute inversions with implicit batching
      for batch_id in trange(
          int(np.ceil(x.shape[0] / float(self.batch_size))),
          desc="Model inversion",
          disable=not self.verbose,
      ):
          batch_index_1, batch_index_2 = (
              batch_id * self.batch_size,
              (batch_id + 1) * self.batch_size,
          )
          batch = x_infer[batch_index_1:batch_index_2]
          batch_labels = y[batch_index_1:batch_index_2]
  
          active = np.array([True] * len(batch))
          window = np.inf * np.ones((len(batch), self.window_length))
  
          i = 0
  
          while i < self.max_iter and sum(active) > 0:
              grads = self.estimator.class_gradient(
                  batch[active], np.argmax(batch_labels[active], axis=1)
              )
              grads = np.reshape(
                  grads, (grads.shape[0],) + grads.shape[2:]
              )
              batch[active] = batch[active] + self.learning_rate * grads
  
              if self.estimator.clip_values is not None:
                  clip_min, clip_max = self.estimator.clip_values
                  batch[active] = np.clip(
                      batch[active], clip_min, clip_max
                  )
  
              cost = (
                  1
                  - self.estimator.predict(batch)[
                      np.arange(len(batch)),
                      np.argmax(batch_labels, axis=1),
                  ]
              )
              active = (cost <= self.threshold) + (
                  cost >= np.max(window, axis=1)
              )
  
              i_window = i % self.window_length
              window[::, i_window] = cost
  
              i = i + 1
  
          x_infer[batch_index_1:batch_index_2] = batch
  
      return x_infer
  
file_path: adversarial-robustness-toolbox/art/attacks/inference/model_inversion/mi_face.py
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import logging
  from typing import Optional, TYPE_CHECKING
  import numpy
  from tqdm.auto import trange
  from art.config import ART_NUMPY_DTYPE
  from art.estimators.classification.classifier import ClassifierMixin, ClassGradientsMixin
  from art.estimators.estimator import BaseEstimator
  from art.attacks.attack import InferenceAttack
  from art.utils import get_labels_np_array, check_and_transform_label_format
label_desc: Use image node_id 2 for calling the MIFace obj's underlying member method code with example usage: obj.infer(x, y) and returns: x_infer