class_docstr: Attacker class, used to make adversarial examples.
  
  This is primarily an internal class, you probably want to be looking at
  :class:`robustness.attacker.AttackerModel`, which is how models are actually
  served (AttackerModel uses this Attacker class).
  
  However, the :meth:`robustness.Attacker.forward` function below
  documents the arguments supported for adversarial attacks specifically.
class_docstr_tok: ["Attacker","class",",","used","to","make","adversarial","examples",".","This","is","primarily","an","internal","class",",","you","probably","want","to","be","looking","at",":","class",":","`","robustness.attacker.AttackerModel","`",",","which","is","how","models","are","actually","served","(","AttackerModel","uses","this","Attacker","class",")",".","However",",","the",":","meth",":","`","robustness.Attacker.forward","`","function","below","documents","the","arguments","supported","for","adversarial","attacks","specifically","."]
docstr: Implementation of forward (finds adversarial examples). Note that
  this does **not** perform inference and should not be called
  directly; refer to :meth:`robustness.attacker.AttackerModel.forward`
  for the function you should actually be calling.
  
  Args:
      x, target (ch.tensor) : see :meth:`robustness.attacker.AttackerModel.forward`
      constraint
          ("2"|"inf"|"unconstrained"|"fourier"|:class:`~robustness.attack_steps.AttackerStep`)
          : threat model for adversarial attacks (:math:`\ell_2` ball,
          :math:`\ell_\infty` ball, :math:`[0, 1]^n`, Fourier basis, or
          custom AttackerStep subclass).
      eps (float) : radius for threat model.
      step_size (float) : step size for adversarial attacks.
      iterations (int): number of steps for adversarial attacks.
      random_start (bool) : if True, start the attack with a random step.
      random_restarts (bool) : if True, do many random restarts and
          take the worst attack (in terms of loss) per input.
      do_tqdm (bool) : if True, show a tqdm progress bar for the attack.
      targeted (bool) : if True (False), minimize (maximize) the loss.
      custom_loss (function|None) : if provided, used instead of the
          criterion as the loss to maximize/minimize during
          adversarial attack. The function should take in
          :samp:`model, x, target` and return a tuple of the form
          :samp:`loss, None`, where loss is a tensor of size N
          (per-element loss).
      should_normalize (bool) : If False, don't normalize the input
          (not recommended unless normalization is done in the
          custom_loss instead).
      orig_input (ch.tensor|None) : If not None, use this as the
          center of the perturbation set, rather than :samp:`x`.
      use_best (bool) : If True, use the best (in terms of loss)
          iterate of the attack process instead of just the last one.
      return_image (bool) : If True (default), then return the adversarial
          example as an image, otherwise return it in its parameterization
          (for example, the Fourier coefficients if 'constraint' is
          'fourier')
      est_grad (tuple|None) : If not None (default), then these are
          :samp:`(query_radius [R], num_queries [N])` to use for estimating the
          gradient instead of autograd. We use the spherical gradient
          estimator, shown below, along with antithetic sampling [#f1]_
          to reduce variance:
          :math:`\nabla_x f(x) \approx \sum_{i=0}^N f(x + R\cdot
          \vec{\delta_i})\cdot \vec{\delta_i}`, where
          :math:`\delta_i` are randomly sampled from the unit ball.
      mixed_precision (bool) : if True, use mixed-precision calculations
          to compute the adversarial examples / do the inference.
  Returns:
      An adversarial example for x (i.e. within a feasible set
      determined by `eps` and `constraint`, but classified as:
  
      * `target` (if `targeted == True`)
      *  not `target` (if `targeted == False`)
  
  .. [#f1] This means that we actually draw :math:`N/2` random vectors
      from the unit ball, and then use :math:`\delta_{N/2+i} =
      -\delta_{i}`.
docstr_tok: ["Implementation","of","forward","(","finds","adversarial","examples",")",".","Note","that","this","does","*","*","not","*","*","perform","inference","and","should","not","be","called","directly",";","refer","to",":","meth",":","`","robustness.attacker.AttackerModel.forward","`","for","the","function","you","should","actually","be","calling",".","Args",":","x",",","target","(","ch.tensor",")",":","see",":","meth",":","`","robustness.attacker.AttackerModel.forward","`","constraint","(","``","2","''","|","''","inf","''","|","''","unconstrained","''","|","''","fourier","''","|",":","class",":","`","~robustness.attack_steps.AttackerStep","`",")",":","threat","model","for","adversarial","attacks","(",":","math",":","`","\\ell_2","`","ball",",",":","math",":","`","\\ell_\\infty","`","ball",",",":","math",":","`","[","0",",","1","]","^n","`",",","Fourier","basis",",","or","custom","AttackerStep","subclass",")",".","eps","(","float",")",":","radius","for","threat","model",".","step_size","(","float",")",":","step","size","for","adversarial","attacks",".","iterations","(","int",")",":","number","of","steps","for","adversarial","attacks",".","random_start","(","bool",")",":","if","True",",","start","the","attack","with","a","random","step",".","random_restarts","(","bool",")",":","if","True",",","do","many","random","restarts","and","take","the","worst","attack","(","in","terms","of","loss",")","per","input",".","do_tqdm","(","bool",")",":","if","True",",","show","a","tqdm","progress","bar","for","the","attack",".","targeted","(","bool",")",":","if","True","(","False",")",",","minimize","(","maximize",")","the","loss",".","custom_loss","(","function|None",")",":","if","provided",",","used","instead","of","the","criterion","as","the","loss","to","maximize\/minimize","during","adversarial","attack",".","The","function","should","take","in",":","samp",":","`","model",",","x",",","target","`","and","return","a","tuple","of","the","form",":","samp",":","`","loss",",","None","`",",","where","loss","is","a","tensor","of","size","N","(","per-element","loss",")",".","should_normalize","(","bool",")",":","If","False",",","do","n't","normalize","the","input","(","not","recommended","unless","normalization","is","done","in","the","custom_loss","instead",")",".","orig_input","(","ch.tensor|None",")",":","If","not","None",",","use","this","as","the","center","of","the","perturbation","set",",","rather","than",":","samp",":","`","x","`",".","use_best","(","bool",")",":","If","True",",","use","the","best","(","in","terms","of","loss",")","iterate","of","the","attack","process","instead","of","just","the","last","one",".","return_image","(","bool",")",":","If","True","(","default",")",",","then","return","the","adversarial","example","as","an","image",",","otherwise","return","it","in","its","parameterization","(","for","example",",","the","Fourier","coefficients","if","'constraint","'","is","'fourier","'",")","est_grad","(","tuple|None",")",":","If","not","None","(","default",")",",","then","these","are",":","samp",":","`","(","query_radius","[","R","]",",","num_queries","[","N","]",")","`","to","use","for","estimating","the","gradient","instead","of","autograd",".","We","use","the","spherical","gradient","estimator",",","shown","below",",","along","with","antithetic","sampling","[","#","f1","]","_","to","reduce","variance",":",":","math",":","`","\\nabla_x","f","(","x",")","\\approx","\\sum_","{","i=0","}","^N","f","(","x","+","R\\cdot","\\vec","{","\\delta_i","}",")","\\cdot","\\vec","{","\\delta_i","}","`",",","where",":","math",":","`","\\delta_i","`","are","randomly","sampled","from","the","unit","ball",".","mixed_precision","(","bool",")",":","if","True",",","use","mixed-precision","calculations","to","compute","the","adversarial","examples","\/","do","the","inference",".","Returns",":","An","adversarial","example","for","x","(","i.e",".","within","a","feasible","set","determined","by","`","eps","`","and","`","constraint","`",",","but","classified","as",":","*","`","target","`","(","if","`","targeted","==","True","`",")","*","not","`","target","`","(","if","`","targeted","==","False","`",")","..","[","#","f1","]","This","means","that","we","actually","draw",":","math",":","`","N\/2","`","random","vectors","from","the","unit","ball",",","and","then","use",":","math",":","`","\\delta_","{","N\/2+i","}","=","-\\delta_","{","i","}","`","."]
code: def forward(
      self,
      x,
      target,
      *_,
      constraint,
      eps,
      step_size,
      iterations,
      random_start=False,
      random_restarts=False,
      do_tqdm=False,
      targeted=False,
      custom_loss=None,
      should_normalize=True,
      orig_input=None,
      use_best=True,
      return_image=True,
      est_grad=None,
      mixed_precision=False,
  ):
      """
      Implementation of forward (finds adversarial examples). Note that
      this does **not** perform inference and should not be called
      directly; refer to :meth:`robustness.attacker.AttackerModel.forward`
      for the function you should actually be calling.
  
      Args:
          x, target (ch.tensor) : see :meth:`robustness.attacker.AttackerModel.forward`
          constraint
              ("2"|"inf"|"unconstrained"|"fourier"|:class:`~robustness.attack_steps.AttackerStep`)
              : threat model for adversarial attacks (:math:`\ell_2` ball,
              :math:`\ell_\infty` ball, :math:`[0, 1]^n`, Fourier basis, or
              custom AttackerStep subclass).
          eps (float) : radius for threat model.
          step_size (float) : step size for adversarial attacks.
          iterations (int): number of steps for adversarial attacks.
          random_start (bool) : if True, start the attack with a random step.
          random_restarts (bool) : if True, do many random restarts and
              take the worst attack (in terms of loss) per input.
          do_tqdm (bool) : if True, show a tqdm progress bar for the attack.
          targeted (bool) : if True (False), minimize (maximize) the loss.
          custom_loss (function|None) : if provided, used instead of the
              criterion as the loss to maximize/minimize during
              adversarial attack. The function should take in
              :samp:`model, x, target` and return a tuple of the form
              :samp:`loss, None`, where loss is a tensor of size N
              (per-element loss).
          should_normalize (bool) : If False, don't normalize the input
              (not recommended unless normalization is done in the
              custom_loss instead).
          orig_input (ch.tensor|None) : If not None, use this as the
              center of the perturbation set, rather than :samp:`x`.
          use_best (bool) : If True, use the best (in terms of loss)
              iterate of the attack process instead of just the last one.
          return_image (bool) : If True (default), then return the adversarial
              example as an image, otherwise return it in its parameterization
              (for example, the Fourier coefficients if 'constraint' is
              'fourier')
          est_grad (tuple|None) : If not None (default), then these are
              :samp:`(query_radius [R], num_queries [N])` to use for estimating the
              gradient instead of autograd. We use the spherical gradient
              estimator, shown below, along with antithetic sampling [#f1]_
              to reduce variance:
              :math:`\\nabla_x f(x) \\approx \\sum_{i=0}^N f(x + R\\cdot
              \\vec{\\delta_i})\\cdot \\vec{\\delta_i}`, where
              :math:`\delta_i` are randomly sampled from the unit ball.
          mixed_precision (bool) : if True, use mixed-precision calculations
              to compute the adversarial examples / do the inference.
      Returns:
          An adversarial example for x (i.e. within a feasible set
          determined by `eps` and `constraint`, but classified as:
  
          * `target` (if `targeted == True`)
          *  not `target` (if `targeted == False`)
  
      .. [#f1] This means that we actually draw :math:`N/2` random vectors
          from the unit ball, and then use :math:`\delta_{N/2+i} =
          -\delta_{i}`.
      """
      # Can provide a different input to make the feasible set around
      # instead of the initial point
      if orig_input is None:
          orig_input = x.detach()
      orig_input = orig_input.cuda()
  
      # Multiplier for gradient ascent [untargeted] or descent [targeted]
      m = -1 if targeted else 1
  
      # Initialize step class and attacker criterion
      criterion = ch.nn.CrossEntropyLoss(reduction="none")
      step_class = (
          STEPS[constraint]
          if isinstance(constraint, str)
          else constraint
      )
      step = step_class(
          eps=eps, orig_input=orig_input, step_size=step_size
      )
  
      def calc_loss(inp, target):
          """
          Calculates the loss of an input with respect to target labels
          Uses custom loss (if provided) otherwise the criterion
          """
          if should_normalize:
              inp = self.normalize(inp)
          output = self.model(inp)
          if custom_loss:
              return custom_loss(self.model, inp, target)
  
          return criterion(output, target), output
  
      # Main function for making adversarial examples
      def get_adv_examples(x):
          # Random start (to escape certain types of gradient masking)
          if random_start:
              x = step.random_perturb(x)
  
          iterator = range(iterations)
          if do_tqdm:
              iterator = tqdm(iterator)
  
          # Keep track of the "best" (worst-case) loss and its
          # corresponding input
          best_loss = None
          best_x = None
  
          # A function that updates the best loss and best input
          def replace_best(loss, bloss, x, bx):
              if bloss is None:
                  bx = x.clone().detach()
                  bloss = loss.clone().detach()
              else:
                  replace = m * bloss < m * loss
                  bx[replace] = x[replace].clone().detach()
                  bloss[replace] = loss[replace]
  
              return bloss, bx
  
          # PGD iterates
          for _ in iterator:
              x = x.clone().detach().requires_grad_(True)
              losses, out = calc_loss(step.to_image(x), target)
              assert (
                  losses.shape[0] == x.shape[0]
              ), "Shape of losses must match input!"
  
              loss = ch.mean(losses)
  
              if step.use_grad:
                  if (est_grad is None) and mixed_precision:
                      with amp.scale_loss(loss, []) as sl:
                          sl.backward()
                      grad = x.grad.detach()
                      x.grad.zero_()
                  elif est_grad is None:
                      (grad,) = ch.autograd.grad(m * loss, [x])
                  else:
                      f = (
                          lambda _x, _y: m
                          * calc_loss(step.to_image(_x), _y)[0]
                      )
                      grad = helpers.calc_est_grad(
                          f, x, target, *est_grad
                      )
              else:
                  grad = None
  
              with ch.no_grad():
                  args = [losses, best_loss, x, best_x]
                  best_loss, best_x = (
                      replace_best(*args) if use_best else (losses, x)
                  )
  
                  x = step.step(x, grad)
                  x = step.project(x)
                  if do_tqdm:
                      iterator.set_description(
                          "Current loss: {l}".format(l=loss)
                      )
  
          # Save computation (don't compute last loss) if not use_best
          if not use_best:
              ret = x.clone().detach()
              return step.to_image(ret) if return_image else ret
  
          losses, _ = calc_loss(step.to_image(x), target)
          args = [losses, best_loss, x, best_x]
          best_loss, best_x = replace_best(*args)
          return step.to_image(best_x) if return_image else best_x
  
      # Random restarts: repeat the attack and find the worst-case
      # example for each input in the batch
      if random_restarts:
          to_ret = None
  
          orig_cpy = x.clone().detach()
          for _ in range(random_restarts):
              adv = get_adv_examples(orig_cpy)
  
              if to_ret is None:
                  to_ret = adv.detach()
  
              _, output = calc_loss(adv, target)
              (corr,) = helpers.accuracy(
                  output, target, topk=(1,), exact=True
              )
              corr = corr.byte()
              misclass = ~corr
              to_ret[misclass] = adv[misclass]
  
          adv_ret = to_ret
      else:
          adv_ret = get_adv_examples(x)
  
      return adv_ret
  
file_path: robustness/robustness/attacker.py
imports: import torch
  import dill
  import os
  from .tools import helpers
  from .None import attack_steps
label_desc: Use image node_id 2 for calling the Attacker obj's underlying member method code with example usage: obj.forward(x, target) and returns: adv_ret, criterion,  output, unknown, custom_loss, bloss,  bx, unknown