Source code for torchattacks.attacks.autoattack

import time

from ..attack import Attack
from ..wrappers.multiattack import MultiAttack
from .apgd import APGD
from .apgdt import APGDT
from .fab import FAB
from .square import Square


[docs] class AutoAttack(Attack): r""" AutoAttack in the paper 'Reliable evaluation of adversarial robustness with an ensemble of diverse parameter-free attacks' [https://arxiv.org/abs/2003.01690] [https://github.com/fra31/auto-attack] Distance Measure : Linf, L2 Arguments: model (nn.Module): model to attack. norm (str) : Lp-norm to minimize. ['Linf', 'L2'] (Default: 'Linf') eps (float): maximum perturbation. (Default: 0.3) version (bool): version. ['standard', 'plus', 'rand'] (Default: 'standard') n_classes (int): number of classes. (Default: 10) seed (int): random seed for the starting point. (Default: 0) verbose (bool): print progress. (Default: False) Shape: - images: :math:`(N, C, H, W)` where `N = number of batches`, `C = number of channels`, `H = height` and `W = width`. It must have a range [0, 1]. - labels: :math:`(N)` where each value :math:`y_i` is :math:`0 \leq y_i \leq` `number of labels`. - output: :math:`(N, C, H, W)`. Examples:: >>> attack = torchattacks.AutoAttack(model, norm='Linf', eps=8/255, version='standard', n_classes=10, seed=None, verbose=False) >>> adv_images = attack(images, labels) """ def __init__( self, model, norm="Linf", eps=8 / 255, version="standard", n_classes=10, seed=None, verbose=False, ): super().__init__("AutoAttack", model) self.norm = norm self.eps = eps self.version = version self.n_classes = n_classes self.seed = seed self.verbose = verbose self.supported_mode = ["default"] if version == "standard": # ['apgd-ce', 'apgd-t', 'fab-t', 'square'] self._autoattack = MultiAttack( [ APGD( model, eps=eps, norm=norm, seed=self.get_seed(), verbose=verbose, loss="ce", n_restarts=1, ), APGDT( model, eps=eps, norm=norm, seed=self.get_seed(), verbose=verbose, n_classes=n_classes, n_restarts=1, ), FAB( model, eps=eps, norm=norm, seed=self.get_seed(), verbose=verbose, multi_targeted=True, n_classes=n_classes, n_restarts=1, ), Square( model, eps=eps, norm=norm, seed=self.get_seed(), verbose=verbose, n_queries=5000, n_restarts=1, ), ] ) # ['apgd-ce', 'apgd-dlr', 'fab', 'square', 'apgd-t', 'fab-t'] elif version == "plus": self._autoattack = MultiAttack( [ APGD( model, eps=eps, norm=norm, seed=self.get_seed(), verbose=verbose, loss="ce", n_restarts=5, ), APGD( model, eps=eps, norm=norm, seed=self.get_seed(), verbose=verbose, loss="dlr", n_restarts=5, ), FAB( model, eps=eps, norm=norm, seed=self.get_seed(), verbose=verbose, n_classes=n_classes, n_restarts=5, ), Square( model, eps=eps, norm=norm, seed=self.get_seed(), verbose=verbose, n_queries=5000, n_restarts=1, ), APGDT( model, eps=eps, norm=norm, seed=self.get_seed(), verbose=verbose, n_classes=n_classes, n_restarts=1, ), FAB( model, eps=eps, norm=norm, seed=self.get_seed(), verbose=verbose, multi_targeted=True, n_classes=n_classes, n_restarts=1, ), ] ) elif version == "rand": # ['apgd-ce', 'apgd-dlr'] self._autoattack = MultiAttack( [ APGD( model, eps=eps, norm=norm, seed=self.get_seed(), verbose=verbose, loss="ce", eot_iter=20, n_restarts=1, ), APGD( model, eps=eps, norm=norm, seed=self.get_seed(), verbose=verbose, loss="dlr", eot_iter=20, n_restarts=1, ), ] ) else: raise ValueError("Not valid version. ['standard', 'plus', 'rand']")
[docs] def forward(self, images, labels): r""" Overridden. """ images = images.clone().detach().to(self.device) labels = labels.clone().detach().to(self.device) adv_images = self._autoattack(images, labels) return adv_images
def get_seed(self): return time.time() if self.seed is None else self.seed