def __init__(
        self,
        classifier: "CLASSIFIER_LOSS_GRADIENTS_TYPE",
        attacks: "EvasionAttack" | list["EvasionAttack"],
        ratio: float = 0.5,
    ) -> None:
        """
        Create an :class:`.AdversarialTrainer` instance.

        :param classifier: Model to train adversarially.
        :param attacks: attacks to use for data augmentation in adversarial training
        :param ratio: The proportion of samples in each batch to be replaced with their adversarial counterparts.
                      Setting this value to 1 allows to train only on adversarial samples.
        """
        from art.attacks.attack import EvasionAttack

        super().__init__(classifier=classifier)
        if isinstance(attacks, EvasionAttack):
            self.attacks = [attacks]
        elif isinstance(attacks, list):
            self.attacks = attacks
        else:
            raise ValueError("Only EvasionAttack instances or list of attacks supported.")

        if ratio <= 0 or ratio > 1:
            raise ValueError("The `ratio` of adversarial samples in each batch has to be between 0 and 1.")
        self.ratio = ratio

        self._precomputed_adv_samples: list[np.ndarray | None] = []
        self.x_augmented: np.ndarray | None = None
        self.y_augmented: np.ndarray | None = None

        Create an :class:`.AdversarialTrainer` instance.

        :param classifier: Model to train adversarially.
        :param attacks: attacks to use for data augmentation in adversarial training
        :param ratio: The proportion of samples in each batch to be replaced with their adversarial counterparts.
                      Setting this value to 1 allows to train only on adversarial samples.
        
art/defences/trainer/adversarial_trainer.py