class_docstr: Close implementation of Feature Collision Poisoning Attack by Shafahi, Huang, et al 2018.
  "Poison Frogs! Targeted Clean-Label Poisoning Attacks on Neural Networks"
  
  This implementation dynamically calculates the dimension of the feature layer, and doesn't hardcode this
  value to 2048 as done in the paper. Thus we recommend using larger values for the similarity_coefficient.
  
  | Paper link: https://arxiv.org/abs/1804.00792
class_docstr_tok: ["Close","implementation","of","Feature","Collision","Poisoning","Attack","by","Shafahi",",","Huang",",","et","al","2018",".","``","Poison","Frogs","!","Targeted","Clean-Label","Poisoning","Attacks","on","Neural","Networks","''","This","implementation","dynamically","calculates","the","dimension","of","the","feature","layer",",","and","does","n't","hardcode","this","value","to","2048","as","done","in","the","paper",".","Thus","we","recommend","using","larger","values","for","the","similarity_coefficient",".","|","Paper","link",":","https",":","\/\/arxiv.org\/abs\/1804.00792"]
docstr: Iteratively finds optimal attack points starting at values at x
  
  :param x: The base images to begin the poison process.
  :param y: Not used in this attack (clean-label).
  :return: An tuple holding the (poisoning examples, poisoning labels).
docstr_tok: ["Iteratively","finds","optimal","attack","points","starting","at","values","at","x",":","param","x",":","The","base","images","to","begin","the","poison","process",".",":","param","y",":","Not","used","in","this","attack","(","clean-label",")",".",":","return",":","An","tuple","holding","the","(","poisoning","examples",",","poisoning","labels",")","."]
code: def poison(
      self, x: np.ndarray, y: Optional[np.ndarray] = None, **kwargs
  ) -> Tuple[np.ndarray, np.ndarray]:
      """
      Iteratively finds optimal attack points starting at values at x
  
      :param x: The base images to begin the poison process.
      :param y: Not used in this attack (clean-label).
      :return: An tuple holding the (poisoning examples, poisoning labels).
      """
      num_poison = len(x)
      final_attacks = []
      if num_poison == 0:  # pragma: no cover
          raise ValueError("Must input at least one poison point")
      target_features = self.estimator.get_activations(
          self.target, self.feature_layer, 1
      )
      for init_attack in x:
          old_attack = np.expand_dims(np.copy(init_attack), axis=0)
          poison_features = self.estimator.get_activations(
              old_attack, self.feature_layer, 1
          )
          old_objective = self.objective(
              poison_features, target_features, init_attack, old_attack
          )
          last_m_objectives = [old_objective]
          for i in trange(
              self.max_iter,
              desc="Feature collision",
              disable=not self.verbose,
          ):
              # forward step
              new_attack = self.forward_step(old_attack)
  
              # backward step
              new_attack = self.backward_step(
                  np.expand_dims(init_attack, axis=0),
                  poison_features,
                  new_attack,
              )
  
              rel_change_val = np.linalg.norm(
                  new_attack - old_attack
              ) / np.linalg.norm(new_attack)
              if (  # pragma: no cover
                  rel_change_val < self.stopping_tol
                  or self.obj_threshold
                  and old_objective <= self.obj_threshold
              ):
                  logger.info(
                      "stopped after %d iterations due to small changes",
                      i,
                  )
                  break
  
              np.expand_dims(new_attack, axis=0)
              new_feature_rep = self.estimator.get_activations(
                  new_attack, self.feature_layer, 1
              )
              new_objective = self.objective(
                  new_feature_rep,
                  target_features,
                  init_attack,
                  new_attack,
              )
  
              avg_of_last_m = sum(last_m_objectives) / float(
                  min(self.num_old_obj, i + 1)
              )
  
              # Increasing objective means then learning rate is too big.  Chop it, and throw out the latest iteration
              if new_objective >= avg_of_last_m and (
                  i % self.num_old_obj / 2 == 0
              ):
                  self.learning_rate *= self.decay_coeff
              else:  # pragma: no cover
                  old_attack = new_attack
                  old_objective = new_objective
  
              if i < self.num_old_obj - 1:
                  last_m_objectives.append(new_objective)
              else:  # pragma: no cover
                  # first remove the oldest obj then append the new obj
                  del last_m_objectives[0]
                  last_m_objectives.append(new_objective)
  
          # Watermarking
          watermark = (
              self.watermark * self.target if self.watermark else 0
          )
          final_poison = np.clip(
              old_attack + watermark, *self.estimator.clip_values
          )
          final_attacks.append(final_poison)
  
      return np.vstack(final_attacks), self.estimator.predict(x)
  
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  from functools import reduce
  import logging
  from typing import Optional, Tuple, Union, TYPE_CHECKING
  import numpy
  from tqdm.auto import trange
  from art.attacks.attack import PoisoningAttackWhiteBox
  from art.estimators import BaseEstimator, NeuralNetworkMixin
  from art.estimators.classification.classifier import ClassifierMixin
  from art.estimators.classification.keras import KerasClassifier
  from art.estimators.classification.pytorch import PyTorchClassifier
label_desc: Use image node_id 2 for calling the FeatureCollisionAttack obj's underlying member method code with example usage: obj.poison(x, y) and returns: np,  self