class_docstr: Spatially Transformed Attack (Xiao et al. 2018)
  https://openreview.net/forum?id=HyydRMZC-
  
  :param predict: forward pass function.
  :param num_classes: number of clasess.
  :param confidence: confidence of the adversarial examples.
  :param initial_const: initial value of the constant c
  :param max_iterations: the maximum number of iterations
  :param search_steps: number of search times to find the optimum
  :param loss_fn: loss function
  :param clip_min: mininum value per input dimension.
  :param clip_max: maximum value per input dimension.
  :param abort_early: if set to true, abort early if getting stuck in local
      min
  :param targeted: if the attack is targeted
class_docstr_tok: ["Spatially","Transformed","Attack","(","Xiao","et","al",".","2018",")","https",":","\/\/openreview.net\/forum","?","id=HyydRMZC-",":","param","predict",":","forward","pass","function",".",":","param","num_classes",":","number","of","clasess",".",":","param","confidence",":","confidence","of","the","adversarial","examples",".",":","param","initial_const",":","initial","value","of","the","constant","c",":","param","max_iterations",":","the","maximum","number","of","iterations",":","param","search_steps",":","number","of","search","times","to","find","the","optimum",":","param","loss_fn",":","loss","function",":","param","clip_min",":","mininum","value","per","input","dimension",".",":","param","clip_max",":","maximum","value","per","input","dimension",".",":","param","abort_early",":","if","set","to","true",",","abort","early","if","getting","stuck","in","local","min",":","param","targeted",":","if","the","attack","is","targeted"]
code: def perturb(self, x, y=None):
      x, y = self._verify_and_process_inputs(x, y)
      batch_size = len(x)
      loss_coeffs = x.new_ones(batch_size) * self.initial_const
      final_l2dists = [L2DIST_UPPER] * batch_size
      final_labels = [INVALID_LABEL] * batch_size
      final_step = [INVALID_LABEL] * batch_size
      final_advs = torch.zeros_like(x)
  
      # TODO: refactor the theta generation
      theta = torch.tensor([[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]]).to(
          x.device
      )
      theta = theta.repeat((x.shape[0], 1, 1))
  
      grid = F.affine_grid(theta, x.size())
  
      grid_ori = grid.clone()
      y_onehot = to_one_hot(y, self.num_classes).float()
  
      clip_min = np.ones(grid_ori.shape[:]) * -1
      clip_max = np.ones(grid_ori.shape[:]) * 1
      clip_bound = list(zip(clip_min.flatten(), clip_max.flatten()))
      grid_ret = grid.clone().data.cpu().numpy().flatten().astype(float)
      from scipy.optimize import fmin_l_bfgs_b
  
      for outer_step in range(self.search_steps):
          grid_ret, f, d = fmin_l_bfgs_b(
              self._loss_fn_spatial,
              grid_ret,
              args=(
                  x.clone().detach(),
                  y_onehot,
                  loss_coeffs,
                  grid_ori.clone().detach(),
              ),
              maxiter=self.max_iterations,
              bounds=clip_bound,
              iprint=0,
              maxls=100,
          )
          grid = (
              torch.from_numpy(grid_ret.reshape(grid_ori.shape))
              .float()
              .to(x.device)
          )
          adv_x = F.grid_sample(x.clone(), grid)
          l2s = calc_l2distsq(grid.data, grid_ori.data)
          output = self.predict(adv_x)
          self._update_if_better(
              adv_x.data,
              y,
              output.data,
              l2s,
              batch_size,
              final_l2dists,
              final_labels,
              final_advs,
              outer_step,
              final_step,
          )
  
      return final_advs
  
file_path: advertorch/advertorch/attacks/spatial.py
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.functional
  from advertorch.utils import calc_l2distsq
  from advertorch.utils import clamp
  from advertorch.utils import to_one_hot
  from .base import Attack
  from .base import LabelMixin
  from .utils import is_successful
label_desc: Use image node_id 4 for calling the SpatialTransformAttack obj's underlying member method code with example usage: obj.perturb(x, y) and returns: final_advs