Source code for secml.adv.attacks.evasion.c_attack_evasion

"""
.. module:: CAttackEvasion
   :synopsis: Interface for evasion attacks

.. moduleauthor:: Battista Biggio <battista.biggio@unica.it>
.. moduleauthor:: Ambra Demontis <ambra.demontis@unica.it>
.. moduleauthor:: Marco Melis <marco.melis@unica.it>

"""
from abc import ABCMeta, abstractmethod

from secml.adv.attacks import CAttack
from secml.array import CArray
from secml.data import CDataset


[docs]class CAttackEvasion(CAttack, metaclass=ABCMeta): """Interface for Evasion attacks. Parameters ---------- classifier : CClassifier Target classifier. surrogate_classifier : CClassifier Surrogate classifier, assumed to be already trained. surrogate_data : CDataset or None, optional Dataset on which the the surrogate classifier has been trained on. Is only required if the classifier is nonlinear. y_target : int or None, optional If None an error-generic attack will be performed, else a error-specific attack to have the samples misclassified as belonging to the `y_target` class. """ __super__ = 'CAttackEvasion' def __init__(self, classifier, surrogate_classifier, surrogate_data=None, y_target=None): super(CAttackEvasion, self).__init__( classifier=classifier, surrogate_classifier=surrogate_classifier, surrogate_data=surrogate_data, y_target=y_target) ########################################################################### # PUBLIC METHODS ###########################################################################
[docs] def run(self, x, y, ds_init=None, *args, **kargs): """Runs evasion on a dataset. Parameters ---------- x : CArray Data points. y : CArray True labels. ds_init : CDataset Dataset for warm starts. Returns ------- y_pred : CArray Predicted labels for all ds samples by target classifier. scores : CArray Scores for all ds samples by target classifier. adv_ds : CDataset Dataset of manipulated samples. f_obj : float Mean value of the objective function computed on each data point. """ x = CArray(x).atleast_2d() y = CArray(y).atleast_2d() x_init = None if ds_init is None else CArray(ds_init.X).atleast_2d() # only consider samples that can be manipulated v = self.is_attack_class(y) idx = CArray(v.find(v)).ravel() # print(v, idx) # number of modifiable samples n_mod_samples = idx.size adv_ds = CDataset(x.deepcopy(), y.deepcopy()) # If dataset is sparse, set the proper attribute if x.issparse is True: self._issparse = True # array in which the value of the optimization function are stored fs_opt = CArray.zeros(n_mod_samples, ) for i in range(n_mod_samples): k = idx[i].item() # idx of sample that can be modified xi = x[k, :] if x_init is None else x_init[k, :] x_opt, f_opt = self._run(x[k, :], y[k], x_init=xi, *args, **kargs) self.logger.info( "Point: {:}/{:}, dmax:{:}, f(x):{:}, eval:{:}/{:}".format( k, x.shape[0], self._dmax, f_opt, self.f_eval, self.grad_eval)) adv_ds.X[k, :] = x_opt fs_opt[i] = f_opt y_pred, scores = self.classifier.predict( adv_ds.X, return_decision_function=True) y_pred = CArray(y_pred) # Return the mean objective function value on the evasion points ( # computed from the outputs of the surrogate classifier) f_obj = fs_opt.mean() return y_pred, scores, adv_ds, f_obj
[docs] def objective_function(self, x): """Objective function. Parameters ---------- x : CArray Array with points on which the objective function should be computed. Returns ------- CArray Value of the objective function on each point. """ return self._objective_function(x)
@abstractmethod def _run(self, x0, y0, x_init=None): """Perform evasion on a single pattern. Parameters ---------- x0 : CArray Initial sample. y0 : int or CArray The true label of x0. x_init : CArray or None, optional Initialization point. If None (default), it is set to x0. """ raise NotImplementedError