class_docstr: The projected gradient descent attack (Madry et al, 2017).
  The attack performs nb_iter steps of size eps_iter, while always staying
  within eps from the initial point.
  Paper: https://arxiv.org/pdf/1706.06083.pdf
  
  :param predict: forward pass function.
  :param loss_fn: loss function.
  :param eps: maximum distortion.
  :param nb_iter: number of iterations.
  :param eps_iter: attack step size.
  :param rand_init: (optional bool) random initialization.
  :param clip_min: mininum value per input dimension.
  :param clip_max: maximum value per input dimension.
  :param ord: (optional) the order of maximum distortion (inf or 2).
  :param targeted: if the attack is targeted.
class_docstr_tok: ["The","projected","gradient","descent","attack","(","Madry","et","al",",","2017",")",".","The","attack","performs","nb_iter","steps","of","size","eps_iter",",","while","always","staying","within","eps","from","the","initial","point",".","Paper",":","https",":","\/\/arxiv.org\/pdf\/1706.06083.pdf",":","param","predict",":","forward","pass","function",".",":","param","loss_fn",":","loss","function",".",":","param","eps",":","maximum","distortion",".",":","param","nb_iter",":","number","of","iterations",".",":","param","eps_iter",":","attack","step","size",".",":","param","rand_init",":","(","optional","bool",")","random","initialization",".",":","param","clip_min",":","mininum","value","per","input","dimension",".",":","param","clip_max",":","maximum","value","per","input","dimension",".",":","param","ord",":","(","optional",")","the","order","of","maximum","distortion","(","inf","or","2",")",".",":","param","targeted",":","if","the","attack","is","targeted","."]
docstr: Given examples (x, y), returns their adversarial counterparts with
  an attack length of eps.
  
  :param x: input tensor.
  :param y: label tensor.
            - if None and self.targeted=False, compute y as predicted
              labels.
            - if self.targeted=True, then y must be the targeted labels.
  :return: tensor containing perturbed inputs.
docstr_tok: ["Given","examples","(","x",",","y",")",",","returns","their","adversarial","counterparts","with","an","attack","length","of","eps",".",":","param","x",":","input","tensor",".",":","param","y",":","label","tensor",".","-","if","None","and","self.targeted=False",",","compute","y","as","predicted","labels",".","-","if","self.targeted=True",",","then","y","must","be","the","targeted","labels",".",":","return",":","tensor","containing","perturbed","inputs","."]
code: def perturb(self, x, y=None):
      """
      Given examples (x, y), returns their adversarial counterparts with
      an attack length of eps.
  
      :param x: input tensor.
      :param y: label tensor.
                - if None and self.targeted=False, compute y as predicted
                  labels.
                - if self.targeted=True, then y must be the targeted labels.
      :return: tensor containing perturbed inputs.
      """
      x, y = self._verify_and_process_inputs(x, y)
  
      delta = torch.zeros_like(x)
      delta = nn.Parameter(delta)
      if self.rand_init:
          rand_init_delta(
              delta, x, self.ord, self.eps, self.clip_min, self.clip_max
          )
          delta.data = (
              clamp(
                  x + delta.data, min=self.clip_min, max=self.clip_max
              )
              - x
          )
  
      rval = perturb_iterative(
          x,
          y,
          self.predict,
          nb_iter=self.nb_iter,
          eps=self.eps,
          eps_iter=self.eps_iter,
          loss_fn=self.loss_fn,
          minimize=self.targeted,
          ord=self.ord,
          clip_min=self.clip_min,
          clip_max=self.clip_max,
          delta_init=delta,
          l1_sparsity=self.l1_sparsity,
      )
  
      return rval.data
  
imports: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  from __future__ import unicode_literals
  import numpy
  import torch
  import torch.nn
  from advertorch.utils import clamp
  from advertorch.utils import normalize_by_pnorm
  from advertorch.utils import clamp_by_pnorm
  from advertorch.utils import is_float_or_torch_tensor
  from advertorch.utils import batch_multiply
  from advertorch.utils import batch_clamp
  from advertorch.utils import replicate_input
  from advertorch.utils import batch_l1_proj
  from .base import Attack
  from .base import LabelMixin
  from .utils import rand_init_delta
label_desc: Use image node_id 2 for calling the PGDAttack obj's underlying member method code with example usage: obj.perturb(x, y) and returns: rval