@call_decorator<EOL><INDENT>def __call__(self, input_or_adv, label=None, unpack=True,<EOL>steps=<NUM_LIT:100>, subsample=<NUM_LIT:10>, p=None):<DEDENT>
a = input_or_adv<EOL>del input_or_adv<EOL>del label<EOL>del unpack<EOL>if not a.has_gradient():<EOL><INDENT>return<EOL><DEDENT>if a.target_class() is not None:<EOL><INDENT>logging.fatal('<STR_LIT>')<EOL>return<EOL><DEDENT>if p is None:<EOL><INDENT>if a._distance == MeanSquaredDistance:<EOL><INDENT>p = <NUM_LIT:2><EOL><DEDENT>elif a._distance == Linfinity:<EOL><INDENT>p = np.inf<EOL><DEDENT>else:<EOL><INDENT>raise NotImplementedError('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>')<EOL><DEDENT><DEDENT>if not (<NUM_LIT:1> <= p <= np.inf):<EOL><INDENT>raise ValueError<EOL><DEDENT>if p not in [<NUM_LIT:2>, np.inf]:<EOL><INDENT>raise NotImplementedError<EOL><DEDENT>_label = a.original_class<EOL>logits, _ = a.predictions(a.original_image)<EOL>labels = np.argsort(logits)[::-<NUM_LIT:1>]<EOL>if subsample:<EOL><INDENT>logging.info('<STR_LIT>'.format(subsample))<EOL>assert isinstance(subsample, int)<EOL>labels = labels[:subsample]<EOL><DEDENT>def get_residual_labels(logits):<EOL><INDENT>"""<STR_LIT>"""<EOL>return [<EOL>k for k in labels<EOL>if logits[k] < logits[_label]]<EOL><DEDENT>perturbed = a.original_image<EOL>min_, max_ = a.bounds()<EOL>for step in range(steps):<EOL><INDENT>logits, grad, is_adv = a.predictions_and_gradient(perturbed)<EOL>if is_adv:<EOL><INDENT>return<EOL><DEDENT>loss = -crossentropy(logits=logits, label=_label)<EOL>residual_labels = get_residual_labels(logits)<EOL>losses = [<EOL>-crossentropy(logits=logits, label=k)<EOL>for k in residual_labels]<EOL>grads = [a.gradient(perturbed, label=k) for k in residual_labels]<EOL>diffs = [(l - loss, g - grad) for l, g in zip(losses, grads)]<EOL>if p == <NUM_LIT:2>:<EOL><INDENT>distances = [abs(dl) / (np.linalg.norm(dg) + <NUM_LIT>)<EOL>for dl, dg in diffs]<EOL><DEDENT>elif p == np.inf:<EOL><INDENT>distances = [abs(dl) / (np.sum(np.abs(dg)) + <NUM_LIT>)<EOL>for dl, dg in diffs]<EOL><DEDENT>else:  <EOL><INDENT>assert False<EOL><DEDENT>optimal = np.argmin(distances)<EOL>df, dg = diffs[optimal]<EOL>if p == <NUM_LIT:2>:<EOL><INDENT>perturbation = abs(df) / (np.linalg.norm(dg) + <NUM_LIT>)**<NUM_LIT:2> * (-dg)<EOL><DEDENT>elif p == np.inf:<EOL><INDENT>perturbation = abs(df) / (np.sum(np.abs(dg)) + <NUM_LIT>)* np.sign(-dg)<EOL><DEDENT>else:  <EOL><INDENT>assert False<EOL><DEDENT>perturbed = perturbed + <NUM_LIT> * perturbation<EOL>perturbed = np.clip(perturbed, min_, max_)<EOL><DEDENT>a.predictions(perturbed)<EOL>
Simple and close to optimal gradient-based
        adversarial attack.

        Parameters
        ----------
        input_or_adv : `numpy.ndarray` or :class:`Adversarial`
            The original, unperturbed input as a `numpy.ndarray` or
            an :class:`Adversarial` instance.
        label : int
            The reference label of the original input. Must be passed
            if `a` is a `numpy.ndarray`, must not be passed if `a` is
            an :class:`Adversarial` instance.
        unpack : bool
            If true, returns the adversarial input, otherwise returns
            the Adversarial object.
        steps : int
            Maximum number of steps to perform.
        subsample : int
            Limit on the number of the most likely classes that should
            be considered. A small value is usually sufficient and much
            faster.
        p : int or float
            Lp-norm that should be minimzed, must be 2 or np.inf.