def exclusionary_reclassification(self, report: dict[str, Any]):
        """
        This function perform exclusionary reclassification. Based on the ex_re_threshold,
        suspicious clusters will be rechecked. If they remain suspicious, the suspected source
        class will be added to the report and the data will be relabelled. The new labels are stored
        in self.y_train_relabelled

        :param report: A dictionary containing defence params as well as the class clusters and their suspiciousness.
        :return: report where the report is a dict object
        """
        self.y_train_relabelled = np.copy(self.y_train)  # Copy the data to avoid overwriting user objects
        # used for relabeling the data
        is_onehot = False
        if len(np.shape(self.y_train)) == 2:
            is_onehot = True

        logger.info("Performing Exclusionary Reclassification with a threshold of %s", self.ex_re_threshold)
        logger.info("Data will be relabelled internally. Access the y_train_relabelled attribute to get new labels")
        # Train a new classifier with the unsuspicious clusters
        cloned_classifier = (
            self.classifier.clone_for_refitting()
        )  # Get a classifier with the same training setup, but new weights
        filtered_x = self.x_train[np.array(self.is_clean_lst) == 1]
        filtered_y = self.y_train[np.array(self.is_clean_lst) == 1]

        if len(filtered_x) == 0:
            logger.warning("All of the data is marked as suspicious. Unable to perform exclusionary reclassification")
            return report

        cloned_classifier.fit(filtered_x, filtered_y)

        # Test on the suspicious clusters
        n_train = len(self.x_train)
        indices_by_class = self._segment_by_class(np.arange(n_train), self.y_train)
        indicies_by_cluster: list[list[list]] = [
            [[] for _ in range(self.nb_clusters)] for _ in range(self.classifier.nb_classes)
        ]

        # Get all data in x_train in the right cluster
        for n_class, cluster_assignments in enumerate(self.clusters_by_class):
            for j, assigned_cluster in enumerate(cluster_assignments):
                indicies_by_cluster[n_class][assigned_cluster].append(indices_by_class[n_class][j])

        for n_class, _ in enumerate(self.poisonous_clusters):
            suspicious_clusters = np.where(np.array(self.poisonous_clusters[n_class]) == 1)[0]
            for cluster in suspicious_clusters:
                cur_indicies = indicies_by_cluster[n_class][cluster]
                predictions = cloned_classifier.predict(self.x_train[cur_indicies])

                predicted_as_class = [
                    np.sum(np.argmax(predictions, axis=1) == i) for i in range(self.classifier.nb_classes)
                ]
                n_class_pred_count = predicted_as_class[n_class]
                predicted_as_class[n_class] = -1 * predicted_as_class[n_class]  # Just to make the max simple
                other_class = np.argmax(predicted_as_class)
                other_class_pred_count = predicted_as_class[other_class]

                # Check if cluster is legit. If so, mark it as such
                if other_class_pred_count == 0 or n_class_pred_count / other_class_pred_count > self.ex_re_threshold:
                    self.poisonous_clusters[n_class][cluster] = 0
                    report["Class_" + str(n_class)]["cluster_" + str(cluster)]["suspicious_cluster"] = False
                    if "suspicious_clusters" in report.keys():
                        report["suspicious_clusters"] = report["suspicious_clusters"] - 1
                    for ind in cur_indicies:
                        self.is_clean_lst[ind] = 1
                # Otherwise, add the exclusionary reclassification info to the report for the suspicious cluster
                else:
                    report["Class_" + str(n_class)]["cluster_" + str(cluster)]["ExRe_Score"] = (
                        n_class_pred_count / other_class_pred_count
                    )
                    report["Class_" + str(n_class)]["cluster_" + str(cluster)]["Suspected_Source_class"] = other_class
                    # Also relabel the data
                    if is_onehot:
                        self.y_train_relabelled[cur_indicies, n_class] = 0
                        self.y_train_relabelled[cur_indicies, other_class] = 1
                    else:
                        self.y_train_relabelled[cur_indicies] = other_class

        return report

        This function perform exclusionary reclassification. Based on the ex_re_threshold,
        suspicious clusters will be rechecked. If they remain suspicious, the suspected source
        class will be added to the report and the data will be relabelled. The new labels are stored
        in self.y_train_relabelled

        :param report: A dictionary containing defence params as well as the class clusters and their suspiciousness.
        :return: report where the report is a dict object
        
art/defences/detector/poison/activation_defence.py