class_docstr: The Momentum Iterative Fast Gradient Sign Method (Dong et al. 2017).
  This method won the first places in NIPS 2017 Non-targeted Adversarial
  Attacks and Targeted Adversarial Attacks. The original paper used
  hard labels for this attack; no label smoothing. inf norm.
  Paper link: https://arxiv.org/pdf/1710.06081.pdf
class_docstr_tok: ["The","Momentum","Iterative","Fast","Gradient","Sign","Method","(","Dong","et","al",".","2017",")",".","This","method","won","the","first","places","in","NIPS","2017","Non-targeted","Adversarial","Attacks","and","Targeted","Adversarial","Attacks",".","The","original","paper","used","hard","labels","for","this","attack",";","no","label","smoothing",".","inf","norm",".","Paper","link",":","https",":","\/\/arxiv.org\/pdf\/1710.06081.pdf"]
docstr: Apply the momentum iterative gradient attack method.
  :param adversary(Adversary):
      The Adversary object.
  :param norm_ord(int):
      Order of the norm, such as np.inf, 1, 2, etc. It can't be 0.
  :param epsilons(list|tuple|float):
      Attack step size (input variation).
      Largest step size if epsilons is not iterable.
  :param epsilon_steps:
      The number of Epsilons' iteration for each attack iteration.
  :param steps:
      The number of attack iteration.
  :param decay_factor:
      The decay factor for the momentum term.
  :return:
      adversary(Adversary): The Adversary object.
docstr_tok: ["Apply","the","momentum","iterative","gradient","attack","method",".",":","param","adversary","(","Adversary",")",":","The","Adversary","object",".",":","param","norm_ord","(","int",")",":","Order","of","the","norm",",","such","as","np.inf",",","1",",","2",",","etc",".","It","ca","n't","be","0.",":","param","epsilons","(","list|tuple|float",")",":","Attack","step","size","(","input","variation",")",".","Largest","step","size","if","epsilons","is","not","iterable",".",":","param","epsilon_steps",":","The","number","of","Epsilons","'","iteration","for","each","attack","iteration",".",":","param","steps",":","The","number","of","attack","iteration",".",":","param","decay_factor",":","The","decay","factor","for","the","momentum","term",".",":","return",":","adversary","(","Adversary",")",":","The","Adversary","object","."]
code: def _apply(
      self,
      adversary,
      norm_ord=np.inf,
      epsilons=0.1,
      epsilons_max=0.5,
      steps=100,
      epsilon_steps=100,
      decay_factor=1,
  ):
      """
      Apply the momentum iterative gradient attack method.
      :param adversary(Adversary):
          The Adversary object.
      :param norm_ord(int):
          Order of the norm, such as np.inf, 1, 2, etc. It can't be 0.
      :param epsilons(list|tuple|float):
          Attack step size (input variation).
          Largest step size if epsilons is not iterable.
      :param epsilon_steps:
          The number of Epsilons' iteration for each attack iteration.
      :param steps:
          The number of attack iteration.
      :param decay_factor:
          The decay factor for the momentum term.
      :return:
          adversary(Adversary): The Adversary object.
      """
      if norm_ord == 0:
          raise ValueError("L0 norm is not supported!")
  
      if not self.support_targeted:
          if adversary.is_targeted_attack:
              raise ValueError(
                  "This attack method doesn't support targeted attack!"
              )
  
      assert self.model.channel_axis() == adversary.original.ndim
      assert (
          self.model.channel_axis() == 1
          or self.model.channel_axis() == adversary.original.shape[0]
          or self.model.channel_axis() == adversary.original.shape[-1]
      )
  
      if not isinstance(epsilons, Iterable):
          # epsilons = np.linspace(0, epsilons, num=epsilon_steps)
          # 从epsilons到epsilons_max逐步增大
          epsilons = np.linspace(
              epsilons, epsilons_max, num=epsilon_steps
          )
  
      min_, max_ = self.model.bounds()
      pre_label = adversary.original_label
  
      for epsilon in epsilons[:]:
          if epsilon == 0.0:
              continue
          step = 1
          adv_img = adversary.original
          momentum = 0
          for i in range(steps):
              if adversary.is_targeted_attack:
                  gradient = -self.model.gradient(
                      adv_img, adversary.target_label
                  )
              else:
                  gradient = self.model.gradient(adv_img, pre_label)
  
              # normalize gradient
              velocity = gradient / self._norm(gradient, ord=1)
              momentum = decay_factor * momentum + velocity
              if norm_ord == np.inf:
                  normalized_grad = np.sign(momentum)
              else:
                  normalized_grad = self._norm(momentum, ord=norm_ord)
              perturbation = epsilon * normalized_grad
              adv_img = adv_img + perturbation
              adv_img = np.clip(adv_img, min_, max_)
              adv_label = np.argmax(self.model.predict(adv_img))
              logging.info(
                  "step={}, epsilon = {:.5f}, pre_label = {}, adv_label={}".format(
                      step, epsilon, pre_label, adv_label
                  )
              )
              if adversary.try_accept_the_example(adv_img, adv_label):
                  return adversary
              step += 1
  
      return adversary
  
imports: from __future__ import division
  from builtins import range
  import logging
  from collections import Iterable
  import numpy
  from .base import Attack
  from functools import reduce
label_desc: Use image node_id 2 for calling the MomentumIteratorAttack obj's underlying member method code with example usage: obj._apply(adversary, norm_ord, epsilons, epsilons_max, steps, epsilon_steps, decay_factor) and returns: adversary, adversary