class_docstr: Implementation of the Knockoff Nets attack from Orekondy et al. (2018).
  
  | Paper link: https://arxiv.org/abs/1812.02766
docstr: Extract with the adaptive sampling strategy.
  
  :param x: An array with the source input to the victim classifier.
  :param y: Target values (class labels) one-hot-encoded of shape (nb_samples, nb_classes) or indices of shape
            (nb_samples,).
  :param thieved_classifier: A thieved classifier to be stolen.
  :return: The stolen classifier.
docstr_tok: ["Extract","with","the","adaptive","sampling","strategy",".",":","param","x",":","An","array","with","the","source","input","to","the","victim","classifier",".",":","param","y",":","Target","values","(","class","labels",")","one-hot-encoded","of","shape","(","nb_samples",",","nb_classes",")","or","indices","of","shape","(","nb_samples",",",")",".",":","param","thieved_classifier",":","A","thieved","classifier","to","be","stolen",".",":","return",":","The","stolen","classifier","."]
code: def _adaptive_extraction(
      self,
      x: np.ndarray,
      y: np.ndarray,
      thieved_classifier: "CLASSIFIER_TYPE",
  ) -> "CLASSIFIER_TYPE":
      """
      Extract with the adaptive sampling strategy.
  
      :param x: An array with the source input to the victim classifier.
      :param y: Target values (class labels) one-hot-encoded of shape (nb_samples, nb_classes) or indices of shape
                (nb_samples,).
      :param thieved_classifier: A thieved classifier to be stolen.
      :return: The stolen classifier.
      """
      # Compute number of actions
      if len(y.shape) == 2:
          nb_actions = len(np.unique(np.argmax(y, axis=1)))
      elif len(y.shape) == 1:
          nb_actions = len(np.unique(y))
      else:
          raise ValueError("Target values `y` has a wrong shape.")
  
      # We need to keep an average version of the victim output
      if self.reward in ("div", "all"):
          self.y_avg = np.zeros(self.estimator.nb_classes)
  
      # We need to keep an average and variance version of rewards
      if self.reward == "all":
          self.reward_avg = np.zeros(3)
          self.reward_var = np.zeros(3)
  
      # Implement the bandit gradients algorithm
      h_func = np.zeros(nb_actions)
      learning_rate = np.zeros(nb_actions)
      probs = np.ones(nb_actions) / nb_actions
      selected_x = []
      queried_labels = []
  
      avg_reward = 0.0
      for iteration in trange(
          1,
          self.nb_stolen + 1,
          desc="Knock-off nets",
          disable=not self.verbose,
      ):
          # Sample an action
          action = np.random.choice(np.arange(0, nb_actions), p=probs)
  
          # Sample data to attack
          sampled_x = self._sample_data(x, y, action)
          selected_x.append(sampled_x)
  
          # Query the victim classifier
          y_output = self.estimator.predict(
              x=np.array([sampled_x]), batch_size=self.batch_size_query
          )
          fake_label = np.argmax(y_output, axis=1)
          fake_label = to_categorical(
              labels=fake_label, nb_classes=self.estimator.nb_classes
          )
          queried_labels.append(fake_label[0])
  
          # Train the thieved classifier
          thieved_classifier.fit(
              x=np.array([sampled_x]),
              y=fake_label,
              batch_size=self.batch_size_fit,
              nb_epochs=1,
              verbose=False,
          )
  
          # Test new labels
          y_hat = thieved_classifier.predict(
              x=np.array([sampled_x]), batch_size=self.batch_size_query
          )
  
          # Compute rewards
          reward = self._reward(y_output, y_hat, iteration)
          avg_reward = avg_reward + (1.0 / iteration) * (
              reward - avg_reward
          )
  
          # Update learning rate
          learning_rate[action] += 1
  
          # Update H function
          for i_action in range(nb_actions):
              if i_action != action:
                  h_func[i_action] = (
                      h_func[i_action]
                      - 1.0
                      / learning_rate[action]
                      * (reward - avg_reward)
                      * probs[i_action]
                  )
              else:
                  h_func[i_action] = h_func[
                      i_action
                  ] + 1.0 / learning_rate[action] * (
                      reward - avg_reward
                  ) * (
                      1 - probs[i_action]
                  )
  
          # Update probs
          aux_exp = np.exp(h_func)
          probs = aux_exp / np.sum(aux_exp)
  
      # Train the thieved classifier the final time
      thieved_classifier.fit(
          x=np.array(selected_x),
          y=np.array(queried_labels),
          batch_size=self.batch_size_fit,
          nb_epochs=self.nb_epochs,
      )
  
      return thieved_classifier
  
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import logging
  from typing import Optional, TYPE_CHECKING, Union
  import numpy
  from tqdm.auto import trange
  from art.config import ART_NUMPY_DTYPE
  from art.attacks.attack import ExtractionAttack
  from art.estimators.estimator import BaseEstimator
  from art.estimators.classification.classifier import ClassifierMixin
  from art.utils import to_categorical
label_desc: Use image node_id 6 for calling the KnockoffNets obj's underlying member method code with example usage: obj._adaptive_extraction(x, y, thieved_classifier) and returns: thieved_classifier