class_docstr: The attack that uses L-BFGS to minimize the distance of the original
  and perturbed images
  
  :param predict: forward pass function.
  :param num_classes: number of clasess.
  :param batch_size: number of samples in the batch
  :param binary_search_steps: number of binary search times to find the
      optimum
  :param max_iterations: the maximum number of iterations
  :param initial_const: initial value of the constant c
  :param clip_min: mininum value per input dimension.
  :param clip_max: maximum value per input dimension.
  :param loss_fn: loss function
  :param targeted: if the attack is targeted.
class_docstr_tok: ["The","attack","that","uses","L-BFGS","to","minimize","the","distance","of","the","original","and","perturbed","images",":","param","predict",":","forward","pass","function",".",":","param","num_classes",":","number","of","clasess",".",":","param","batch_size",":","number","of","samples","in","the","batch",":","param","binary_search_steps",":","number","of","binary","search","times","to","find","the","optimum",":","param","max_iterations",":","the","maximum","number","of","iterations",":","param","initial_const",":","initial","value","of","the","constant","c",":","param","clip_min",":","mininum","value","per","input","dimension",".",":","param","clip_max",":","maximum","value","per","input","dimension",".",":","param","loss_fn",":","loss","function",":","param","targeted",":","if","the","attack","is","targeted","."]
code: def perturb(self, x, y=None):
      from scipy.optimize import fmin_l_bfgs_b
  
      def _loss_fn(adv_x_np, self, x, target, const):
          adv_x = (
              torch.from_numpy(adv_x_np.reshape(x.shape))
              .float()
              .to(x.device)
              .requires_grad_()
          )
          output = self.predict(adv_x)
          loss2 = torch.sum((x - adv_x) ** 2)
          loss_fn = F.cross_entropy(output, target, reduction="none")
          loss1 = torch.sum(const * loss_fn)
          loss = loss1 + loss2
          loss.backward()
          grad_ret = (
              adv_x.grad.data.cpu().numpy().flatten().astype(float)
          )
          loss = loss.data.cpu().numpy().flatten().astype(float)
          if not self.targeted:
              loss = -loss
          return loss, grad_ret
  
      x, y = self._verify_and_process_inputs(x, y)
      batch_size = len(x)
      coeff_lower_bound = x.new_zeros(batch_size)
      coeff_upper_bound = x.new_ones(batch_size) * COEFF_UPPER
      loss_coeffs = x.new_ones(batch_size) * self.initial_const
      final_l2dists = [L2DIST_UPPER] * batch_size
      final_labels = [INVALID_LABEL] * batch_size
      final_advs = x.clone()
      clip_min = self.clip_min * np.ones(x.shape[:]).astype(float)
      clip_max = self.clip_max * np.ones(x.shape[:]).astype(float)
      clip_bound = list(zip(clip_min.flatten(), clip_max.flatten()))
  
      for outer_step in range(self.binary_search_steps):
          init_guess = x.clone().cpu().numpy().flatten().astype(float)
          adv_x, f, _ = fmin_l_bfgs_b(
              _loss_fn,
              init_guess,
              args=(self, x.clone(), y, loss_coeffs),
              bounds=clip_bound,
              maxiter=self.max_iterations,
              iprint=0,
          )
  
          adv_x = (
              torch.from_numpy(adv_x.reshape(x.shape))
              .float()
              .to(x.device)
          )
          l2s = calc_l2distsq(x, adv_x)
          output = self.predict(adv_x)
          self._update_if_better(
              adv_x,
              y,
              output.data,
              l2s,
              batch_size,
              final_l2dists,
              final_labels,
              final_advs,
          )
          self._update_loss_coeffs(
              y,
              batch_size,
              loss_coeffs,
              coeff_upper_bound,
              coeff_lower_bound,
              output.data,
          )
      return final_advs
  
file_path: advertorch/advertorch/attacks/lbfgs.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 .base import Attack
  from .base import LabelMixin
label_desc: Use image node_id 4 for calling the LBFGSAttack obj's underlying member method code with example usage: obj.perturb(x, y) and returns: final_advs, loss,  grad_ret