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 _loss_fn_spatial(self, grid, x, y, const, grid_ori):
      imgs = x.clone()
      grid = (
          torch.from_numpy(grid.reshape(grid_ori.shape))
          .float()
          .to(x.device)
          .requires_grad_()
      )
      delta = grid_ori - grid
  
      adv_img = F.grid_sample(imgs, grid)
      output = self.predict(adv_img)
      real = (y * output).sum(dim=1)
      other = ((1.0 - y) * output - (y * TARGET_MULT)).max(1)[0]
      if self.targeted:
          loss1 = clamp(other - real + self.confidence, min=0.0)
      else:
          loss1 = clamp(real - other + self.confidence, min=0.0)
      loss2 = self.initial_const * (
          torch.sqrt(
              (((delta[:, :, 1:] - delta[:, :, :-1] + 1e-10) ** 2))
              .view(delta.shape[0], -1)
              .sum(1)
          )
          + torch.sqrt(
              ((delta[:, 1:, :] - delta[:, :-1, :] + 1e-10) ** 2)
              .view(delta.shape[0], -1)
              .sum(1)
          )
      )
      loss = torch.sum(loss1) + torch.sum(loss2)
      loss.backward()
      grad_ret = grid.grad.data.cpu().numpy().flatten().astype(float)
      grid.grad.data.zero_()
      return loss.data.cpu().numpy().astype(float), grad_ret
  
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 2 for calling the SpatialTransformAttack obj's underlying member method code with example usage: obj._loss_fn_spatial(grid, x, y, const, grid_ori) and returns: loss,  grad_ret