def poison_estimator(
        self, x: np.ndarray, y: np.ndarray, batch_size: int = 64, nb_epochs: int = 10, **kwargs
    ) -> "CLASSIFIER_TYPE":
        """
        Train a poisoned model and return it
        :param x: Training data
        :param y: Training labels
        :param batch_size: The size of the batches used for training
        :param nb_epochs: The number of epochs to train for
        :return: A classifier with embedded backdoors
        """
        train_data = np.copy(x)
        train_labels = np.copy(y)

        # Select indices to poison
        selected_indices = np.zeros(len(x)).astype(bool)

        if len(self.pp_poison) == 1:
            if isinstance(self.target, np.ndarray):
                not_target = np.logical_not(np.all(y == self.target, axis=1))
                selected_indices[not_target] = np.random.uniform(size=sum(not_target)) < self.pp_poison[0]
            else:
                for src, _ in self.target:
                    all_src = np.all(y == src, axis=1)
                    selected_indices[all_src] = np.random.uniform(size=sum(all_src)) < self.pp_poison[0]
        else:
            for p_p, (src, _) in zip(self.pp_poison, self.target):
                all_src = np.all(y == src, axis=1)
                selected_indices[all_src] = np.random.uniform(size=sum(all_src)) < p_p

        # Poison selected indices
        if isinstance(self.target, np.ndarray):
            to_be_poisoned = train_data[selected_indices]
            poison_data, poison_labels = self.poison(to_be_poisoned, y=self.target, broadcast=True)

            poison_idxs = np.arange(len(x))[selected_indices]
            for i, idx in enumerate(poison_idxs):
                train_data[idx] = poison_data[i]
                train_labels[idx] = poison_labels[i]
        else:
            for src, tgt in self.target:
                poison_mask = np.logical_and(selected_indices, np.all(y == src, axis=1))
                to_be_poisoned = train_data[poison_mask]
                src_poison_data, src_poison_labels = self.poison(to_be_poisoned, y=shape_labels(tgt), broadcast=True)
                train_data[poison_mask] = src_poison_data
                train_labels[poison_mask] = src_poison_labels

        # label 1 if is backdoor 0 otherwise
        is_backdoor = selected_indices.astype(int)

        # convert to one-hot
        is_backdoor = np.fromfunction(lambda b_idx: np.eye(2)[is_backdoor[b_idx]], shape=(len(x),), dtype=int)

        # Save current training data
        self.train_data = train_data
        self.train_labels = train_labels
        self.is_backdoor = is_backdoor

        if isinstance(self.estimator, KerasClassifier):
            # Call fit with both y and is_backdoor labels
            self.embed_model.fit(
                train_data, y=[train_labels, is_backdoor], batch_size=batch_size, epochs=nb_epochs, **kwargs
            )
            params = self.estimator.get_params()
            del params["model"]
            del params["nb_classes"]
            return KerasClassifier(self.orig_model, **params)

        raise NotImplementedError("Currently only Keras is supported")

        Train a poisoned model and return it
        :param x: Training data
        :param y: Training labels
        :param batch_size: The size of the batches used for training
        :param nb_epochs: The number of epochs to train for
        :return: A classifier with embedded backdoors
        
art/attacks/poisoning/adversarial_embedding_attack.py