class_docstr: DeepFool: a simple and accurate method to fool deep neural networks",
  Seyed-Mohsen Moosavi-Dezfooli, Alhussein Fawzi, Pascal Frossard,
  https://arxiv.org/abs/1511.04599
docstr: Apply the deep fool attack.
  
  Args:
      adversary(Adversary): The Adversary object.
      iterations(int): The iterations.
      overshoot(float): We add (1+overshoot)*pert every iteration.
  Return:
      adversary: The Adversary object.
code: def _apply(self, adversary, iterations=100, overshoot=0.02):
      """
      Apply the deep fool attack.
  
      Args:
          adversary(Adversary): The Adversary object.
          iterations(int): The iterations.
          overshoot(float): We add (1+overshoot)*pert every iteration.
      Return:
          adversary: The Adversary object.
      """
      assert adversary is not None
  
      pre_label = adversary.original_label
      min_, max_ = self.model.bounds()
  
      logging.info("min_={0}, max_={1}".format(min_, max_))
  
      f = self.model.predict(adversary.original)
  
      if adversary.is_targeted_attack:
          labels = [adversary.target_label]
      else:
          max_class_count = 10
          class_count = self.model.num_classes()
          if class_count > max_class_count:
              # labels = np.argsort(f)[-(max_class_count + 1):-1]
              logging.info(
                  "selec top-{0} class".format(max_class_count)
              )
              labels = np.argsort(f)[::-1]
              labels = labels[:max_class_count]
          else:
              labels = np.arange(class_count)
  
      t = [str(i) for i in labels]
  
      logging.info("select label:" + " ".join(t))
  
      gradient = self.model.gradient(adversary.original, pre_label)
      x = np.copy(adversary.original)
  
      for iteration in range(iterations):
          w = np.inf
          w_norm = np.inf
          pert = np.inf
          for k in labels:
              if k == pre_label:
                  continue
              # 标签k对应的梯度
              gradient_k = self.model.gradient(x, k)
              # 标签k对应的梯度和现有便签的梯度的差
              w_k = gradient_k - gradient
              # 标签k和现有标签在logit层面的差距
              f_k = f[k] - f[pre_label]
              # 保证非0 避免计算时除以0 梯度差距除以l2范式值
              w_k_norm = np.linalg.norm(w_k.flatten()) + 1e-8
              # 标签k和现有标签在logit层面的差距除以l2范式的值
              pert_k = (np.abs(f_k) + 1e-8) / w_k_norm
  
              # 对应论文中的选择最小的l
              if pert_k < pert:
                  pert = pert_k
                  w = w_k
                  w_norm = w_k_norm
                  # logging.info("k={0} pert={1} w_norm={2}".format(k,pert, w_norm))
  
          # 论文中为+  advbox老版本实现成了- l2实现
          r_i = w * pert / w_norm
  
          # logging.info(r_i)
  
          # 放大系数 在原论文上的创新 提高攻击速度 论文中相当于overshoot=0
          x = x + (1 + overshoot) * r_i
  
          x = np.clip(x, min_, max_)
  
          f = self.model.predict(x)
          gradient = self.model.gradient(x, pre_label)
          adv_label = np.argmax(f)
          logging.info(
              "iteration={}, f[pre_label]={}, f[target_label]={}"
              ", f[adv_label]={}, pre_label={}, adv_label={}"
              "".format(
                  iteration,
                  f[pre_label],
                  (
                      f[adversary.target_label]
                      if adversary.is_targeted_attack
                      else "NaN"
                  ),
                  f[adv_label],
                  pre_label,
                  adv_label,
              )
          )
          if adversary.try_accept_the_example(x, adv_label):
              return adversary
  
      return adversary
  
file_path: AdvBox/adversarialbox/attacks/deepfool.py
imports: from __future__ import division
  from builtins import str
  from builtins import range
  import logging
  import numpy
  from .base import Attack
label_desc: Use image node_id 1 for calling the DeepFoolAttack obj's underlying member method code with example usage: obj._apply(adversary, iterations, overshoot) and returns: adversary, adversary