class_docstr: Method from Chen et al., 2018 performing poisoning detection based on activations clustering.
  
  | Paper link: https://arxiv.org/abs/1811.03728
  
  | Please keep in mind the limitations of defences. For more information on the limitations of this
      defence, see https://arxiv.org/abs/1905.13409 . For details on how to evaluate classifier security
      in general, see https://arxiv.org/abs/1902.06705
docstr: Returns poison detected and a report.
  
  :param clustering_method: clustering algorithm to be used. Currently `KMeans` is the only method supported
  :type clustering_method: `str`
  :param nb_clusters: number of clusters to find. This value needs to be greater or equal to one
  :type nb_clusters: `int`
  :param reduce: method used to reduce dimensionality of the activations. Supported methods include  `PCA`,
                 `FastICA` and `TSNE`
  :type reduce: `str`
  :param nb_dims: number of dimensions to be reduced
  :type nb_dims: `int`
  :param cluster_analysis: heuristic to automatically determine if a cluster contains poisonous data. Supported
                           methods include `smaller` and `distance`. The `smaller` method defines as poisonous the
                           cluster with less number of data points, while the `distance` heuristic uses the
                           distance between the clusters.
  :type cluster_analysis: `str`
  :return: (report, is_clean_lst):
          where a report is a dict object that contains information specified by the clustering analysis technique
          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",".",":","param","clustering_method",":","clustering","algorithm","to","be","used",".","Currently","`","KMeans","`","is","the","only","method","supported",":","type","clustering_method",":","`","str","`",":","param","nb_clusters",":","number","of","clusters","to","find",".","This","value","needs","to","be","greater","or","equal","to","one",":","type","nb_clusters",":","`","int","`",":","param","reduce",":","method","used","to","reduce","dimensionality","of","the","activations",".","Supported","methods","include","`","PCA","`",",","`","FastICA","`","and","`","TSNE","`",":","type","reduce",":","`","str","`",":","param","nb_dims",":","number","of","dimensions","to","be","reduced",":","type","nb_dims",":","`","int","`",":","param","cluster_analysis",":","heuristic","to","automatically","determine","if","a","cluster","contains","poisonous","data",".","Supported","methods","include","`","smaller","`","and","`","distance","`",".","The","`","smaller","`","method","defines","as","poisonous","the","cluster","with","less","number","of","data","points",",","while","the","`","distance","`","heuristic","uses","the","distance","between","the","clusters",".",":","type","cluster_analysis",":","`","str","`",":","return",":","(","report",",","is_clean_lst",")",":","where","a","report","is","a","dict","object","that","contains","information","specified","by","the","clustering","analysis","technique","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[str, Any], List[int]]:
      """
      Returns poison detected and a report.
  
      :param clustering_method: clustering algorithm to be used. Currently `KMeans` is the only method supported
      :type clustering_method: `str`
      :param nb_clusters: number of clusters to find. This value needs to be greater or equal to one
      :type nb_clusters: `int`
      :param reduce: method used to reduce dimensionality of the activations. Supported methods include  `PCA`,
                     `FastICA` and `TSNE`
      :type reduce: `str`
      :param nb_dims: number of dimensions to be reduced
      :type nb_dims: `int`
      :param cluster_analysis: heuristic to automatically determine if a cluster contains poisonous data. Supported
                               methods include `smaller` and `distance`. The `smaller` method defines as poisonous the
                               cluster with less number of data points, while the `distance` heuristic uses the
                               distance between the clusters.
      :type cluster_analysis: `str`
      :return: (report, is_clean_lst):
              where a report is a dict object that contains information specified by the clustering analysis technique
              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.
      """
      old_nb_clusters = self.nb_clusters
      self.set_params(**kwargs)
      if self.nb_clusters != old_nb_clusters:
          self.clusterer = MiniBatchKMeans(n_clusters=self.nb_clusters)
  
      if self.generator is not None:
          (
              self.clusters_by_class,
              self.red_activations_by_class,
          ) = self.cluster_activations()
          report, self.assigned_clean_by_class = self.analyze_clusters()
  
          batch_size = self.generator.batch_size
          num_samples = self.generator.size
          self.is_clean_lst = []
  
          # loop though the generator to generator a report
          for _ in range(num_samples // batch_size):  # type: ignore
              _, y_batch = self.generator.get_batch()
              indices_by_class = self._segment_by_class(
                  np.arange(batch_size), y_batch
              )
              is_clean_lst = [0] * batch_size
              for class_idx, idxs in enumerate(indices_by_class):
                  for idx_in_class, idx in enumerate(idxs):
                      is_clean_lst[idx] = self.assigned_clean_by_class[
                          class_idx
                      ][idx_in_class]
              self.is_clean_lst += is_clean_lst
          return report, self.is_clean_lst
  
      if not self.activations_by_class:
          activations = self._get_activations()
          self.activations_by_class = self._segment_by_class(
              activations, self.y_train
          )
      (
          self.clusters_by_class,
          self.red_activations_by_class,
      ) = self.cluster_activations()
      report, self.assigned_clean_by_class = self.analyze_clusters()
      # Here, assigned_clean_by_class[i][j] is 1 if the jth data point in the ith class was
      # determined to be clean by activation cluster
  
      # Build an array that matches the original indexes of x_train
      n_train = len(self.x_train)
      indices_by_class = self._segment_by_class(
          np.arange(n_train), self.y_train
      )
      self.is_clean_lst = [0] * n_train
  
      for assigned_clean, indices_dp in zip(
          self.assigned_clean_by_class, indices_by_class
      ):
          for assignment, index_dp in zip(assigned_clean, indices_dp):
              if assignment == 1:
                  self.is_clean_lst[index_dp] = 1
  
      if self.ex_re_threshold is not None:
          if self.generator is not None:
              raise RuntimeError(
                  "Currently, exclusionary reclassification cannot be used with generators"
              )
          if hasattr(self.classifier, "clone_for_refitting"):
              report = self.exclusionary_reclassification(report)
          else:
              logger.warning(
                  "Classifier does not have clone_for_refitting method defined. Skipping"
              )
  
      return report, self.is_clean_lst
  
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import logging
  import os
  import pickle
  import time
  from typing import Any, Dict, List, Optional, Tuple, TYPE_CHECKING
  import numpy
  from sklearn.cluster import KMeans, MiniBatchKMeans
  from art import config
  from art.data_generators import DataGenerator
  from art.defences.detector.poison.clustering_analyzer import ClusteringAnalyzer
  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
  from art.visualization import create_sprite, save_image, plot_3d
label_desc: Use image node_id 3 for calling the ActivationDefence obj's underlying member method code with example usage: obj.detect_poison() and returns: report,  self, report,  self