class_docstr: Method from Tran et al., 2018 performing poisoning detection based on Spectral Signatures
class_docstr_tok: ["Method","from","Tran","et","al.",",","2018","performing","poisoning","detection","based","on","Spectral","Signatures"]
docstr: Returns poison detected and a report.
  
  :return: (report, is_clean_lst):
          where a report is a dictionary containing the index as keys the outlier score of suspected poisons as
          values where is_clean is a list, where is_clean_lst[i]=1 means that x_train[i] there is clean and
          is_clean_lst[i]=0, means that x_train[i] was classified as poison.
docstr_tok: ["Returns","poison","detected","and","a","report",".",":","return",":","(","report",",","is_clean_lst",")",":","where","a","report","is","a","dictionary","containing","the","index","as","keys","the","outlier","score","of","suspected","poisons","as","values","where","is_clean","is","a","list",",","where","is_clean_lst","[","i","]","=1","means","that","x_train","[","i","]","there","is","clean","and","is_clean_lst","[","i","]","=0",",","means","that","x_train","[","i","]","was","classified","as","poison","."]
code: def detect_poison(self, **kwargs) -> Tuple[dict, List[int]]:
      """
      Returns poison detected and a report.
  
      :return: (report, is_clean_lst):
              where a report is a dictionary containing the index as keys the outlier score of suspected poisons as
              values where is_clean is a list, where is_clean_lst[i]=1 means that x_train[i] there is clean and
              is_clean_lst[i]=0, means that x_train[i] was classified as poison.
      """
      self.set_params(**kwargs)
  
      if self.classifier.layer_names is not None:
          nb_layers = len(self.classifier.layer_names)
      else:
          raise ValueError("No layer names identified.")
      features_x_poisoned = self.classifier.get_activations(
          self.x_train, layer=nb_layers - 1, batch_size=self.batch_size
      )
      if not isinstance(features_x_poisoned, np.ndarray):
          raise ValueError("Wrong type detected.")
  
      if features_x_poisoned is not None:
          # flatten activations across batch
          features_x_poisoned = np.reshape(
              features_x_poisoned, (features_x_poisoned.shape[0], -1)
          )
          features_split = segment_by_class(
              features_x_poisoned,
              self.y_train,
              self.classifier.nb_classes,
          )
      else:
          raise ValueError("Activation are `None`.")
      score_by_class = []
      keep_by_class = []
  
      for idx, feature in enumerate(features_split):
          # Check for empty list
          if len(feature):  # pylint: disable=C1801
              score = SpectralSignatureDefense.spectral_signature_scores(np.vstack(feature))  # type: ignore
              score_cutoff = np.quantile(
                  score,
                  max(
                      1 - self.eps_multiplier * self.expected_pp_poison,
                      0.0,
                  ),
              )
              score_by_class.append(score)
              keep_by_class.append(score < score_cutoff)
          else:
              score_by_class.append([0])  # type: ignore
              keep_by_class.append([True])
  
      base_indices_by_class = segment_by_class(
          np.arange(self.y_train.shape[0]),
          self.y_train,
          self.classifier.nb_classes,
      )
      is_clean_lst = [0] * self.y_train.shape[0]
      report = {}
  
      for keep_booleans, all_scores, indices in zip(
          keep_by_class, score_by_class, base_indices_by_class
      ):
          for keep_boolean, all_score, idx in zip(
              keep_booleans, all_scores, indices
          ):
              if keep_boolean:
                  is_clean_lst[idx] = 1
              else:
                  report[idx] = all_score[0]
  
      return report, is_clean_lst
  
file_path: adversarial-robustness-toolbox/art/defences/detector/poison/spectral_signature_defense.py
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  from typing import List, Tuple, TYPE_CHECKING
  import numpy
  from art.defences.detector.poison.ground_truth_evaluator import GroundTruthEvaluator
  from art.defences.detector.poison.poison_filtering_defence import PoisonFilteringDefence
  from art.utils import segment_by_class
label_desc: Use image node_id 3 for calling the SpectralSignatureDefense obj's underlying member method code with example usage: obj.detect_poison() and returns: report,  is_clean_lst