Example #1
0
 def __init__(self,
              network,
              eps=0.07,
              alpha=None,
              bounds=None,
              loss_fn=None):
     super(GradientMethod, self).__init__()
     self._network = check_model('network', network, Cell)
     self._eps = check_value_positive('eps', eps)
     self._dtype = None
     if bounds is not None:
         self._bounds = check_param_multi_types('bounds', bounds,
                                                [list, tuple])
         for b in self._bounds:
             _ = check_param_multi_types('bound', b, [int, float])
     else:
         self._bounds = bounds
     if alpha is not None:
         self._alpha = check_value_positive('alpha', alpha)
     else:
         self._alpha = alpha
     if loss_fn is None:
         loss_fn = SoftmaxCrossEntropyWithLogits(is_grad=False,
                                                 sparse=False)
     with_loss_cell = WithLossCell(self._network, loss_fn)
     self._grad_all = GradWrapWithLoss(with_loss_cell)
     self._grad_all.set_train()
class IterativeGradientMethod(Attack):
    """
    Abstract base class for all iterative gradient based attacks.

    Args:
        network (Cell): Target model.
        eps (float): Proportion of adversarial perturbation generated by the
            attack to data range. Default: 0.3.
        eps_iter (float): Proportion of single-step adversarial perturbation
            generated by the attack to data range. Default: 0.1.
        bounds (tuple): Upper and lower bounds of data, indicating the data range.
            In form of (clip_min, clip_max). Default: (0.0, 1.0).
        nb_iter (int): Number of iteration. Default: 5.
        loss_fn (Loss): Loss function for optimization. If None, the input network \
            is already equipped with loss function. Default: None.
    """
    def __init__(self, network, eps=0.3, eps_iter=0.1, bounds=(0.0, 1.0), nb_iter=5,
                 loss_fn=None):
        super(IterativeGradientMethod, self).__init__()
        self._network = check_model('network', network, Cell)
        self._eps = check_value_positive('eps', eps)
        self._eps_iter = check_value_positive('eps_iter', eps_iter)
        self._nb_iter = check_int_positive('nb_iter', nb_iter)
        self._bounds = None
        if bounds is not None:
            self._bounds = check_param_multi_types('bounds', bounds, [list, tuple])
            for b in self._bounds:
                _ = check_param_multi_types('bound', b, [int, float])
        if loss_fn is None:
            self._loss_grad = network
        else:
            self._loss_grad = GradWrapWithLoss(WithLossCell(self._network, loss_fn))
        self._loss_grad.set_train()

    @abstractmethod
    def generate(self, inputs, labels):
        """
        Generate adversarial examples based on input samples and original/target labels.

        Args:
            inputs (Union[numpy.ndarray, tuple]): Benign input samples used as references to create
                adversarial examples.
            labels (Union[numpy.ndarray, tuple]): Original/target labels. \
                For each input if it has more than one label, it is wrapped in a tuple.
        Raises:
            NotImplementedError: This function is not available in
                IterativeGradientMethod.

        Examples:
            >>> adv_x = attack.generate([[0.1, 0.9, 0.6],
            >>>                          [0.3, 0, 0.3]],
            >>>                         [[0, , 1, 0, 0, 0, 0, 0, 0, 0],
            >>>                          [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]])
        """
        msg = 'The function generate() is an abstract method in class ' \
              '`IterativeGradientMethod`, and should be implemented ' \
              'in child class.'
        LOGGER.error(TAG, msg)
        raise NotImplementedError(msg)
Example #3
0
 def __init__(self,
              network,
              eps=1e-5,
              bounds=(0.0, 1.0),
              is_targeted=True,
              nb_iter=150,
              search_iters=30,
              loss_fn=None,
              sparse=False):
     super(LBFGS, self).__init__()
     self._network = check_model('network', network, Cell)
     self._eps = check_value_positive('eps', eps)
     self._is_targeted = check_param_type('is_targeted', is_targeted, bool)
     self._nb_iter = check_int_positive('nb_iter', nb_iter)
     self._search_iters = check_int_positive('search_iters', search_iters)
     if loss_fn is None:
         loss_fn = SoftmaxCrossEntropyWithLogits(is_grad=False,
                                                 sparse=False)
     with_loss_cell = WithLossCell(self._network, loss_fn)
     self._grad_all = GradWrapWithLoss(with_loss_cell)
     self._dtype = None
     self._bounds = check_param_multi_types('bounds', bounds, [list, tuple])
     self._sparse = check_param_type('sparse', sparse, bool)
     for b in self._bounds:
         _ = check_param_multi_types('bound', b, [int, float])
     box_max, box_min = bounds
     if box_max < box_min:
         self._box_min = box_max
         self._box_max = box_min
     else:
         self._box_min = box_min
         self._box_max = box_max
 def __init__(self, network, eps=0.3, eps_iter=0.1, bounds=(0.0, 1.0), nb_iter=5,
              loss_fn=None):
     super(IterativeGradientMethod, self).__init__()
     self._network = check_model('network', network, Cell)
     self._eps = check_value_positive('eps', eps)
     self._eps_iter = check_value_positive('eps_iter', eps_iter)
     self._nb_iter = check_int_positive('nb_iter', nb_iter)
     self._bounds = None
     if bounds is not None:
         self._bounds = check_param_multi_types('bounds', bounds, [list, tuple])
         for b in self._bounds:
             _ = check_param_multi_types('bound', b, [int, float])
     if loss_fn is None:
         self._loss_grad = network
     else:
         self._loss_grad = GradWrapWithLoss(WithLossCell(self._network, loss_fn))
     self._loss_grad.set_train()
    def generate(self, target_features, iters=100):
        """
        Reconstruct images based on target_features.

        Args:
            target_features (numpy.ndarray): Deep representations of original images. The first dimension of
                target_features should be img_num. It should be noted that the shape of target_features should be
                (1, dim2, dim3, ...) if img_num equals 1.
            iters (int): iteration times of inversion attack, which should be positive integers. Default: 100.

        Returns:
            numpy.ndarray, reconstructed images, which are expected to be similar to original images.

        Raises:
            TypeError: If the type of target_features is not numpy.ndarray.
            ValueError: If any value of iters is not positive int.Z

        Examples:
            >>> net = LeNet5()
            >>> inversion_attack = ImageInversionAttack(net, input_shape=(1, 32, 32), input_bound=(0, 1),
            >>> loss_weights=[1, 0.2, 5])
            >>> features = np.random.random((2, 10)).astype(np.float32)
            >>> images = inversion_attack.generate(features, iters=10)
            >>> print(images.shape)
            (2, 1, 32, 32)
        """
        target_features = check_numpy_param('target_features', target_features)
        iters = check_int_positive('iters', iters)

        # shape checking
        img_num = target_features.shape[0]
        test_input = np.random.random((img_num, ) + self._input_shape).astype(
            np.float32)
        test_out = self._network(Tensor(test_input)).asnumpy()
        if test_out.shape != target_features.shape:
            msg = "The shape of target_features ({}) is not in accordance with the shape" \
                  " of network output({})".format(target_features.shape, test_out.shape)
            raise ValueError(msg)
        loss_net = self._loss
        loss_grad = GradWrapWithLoss(loss_net)

        inversion_images = []
        for i in range(img_num):
            target_feature_n = target_features[i]
            inversion_image_n = np.random.random(
                (1, ) + self._input_shape).astype(np.float32) * 0.05
            for s in range(iters):
                x_grad = loss_grad(Tensor(inversion_image_n),
                                   Tensor(target_feature_n)).asnumpy()
                x_grad_sign = np.sign(x_grad)
                inversion_image_n -= x_grad_sign * 0.01
                inversion_image_n = np.clip(inversion_image_n,
                                            self._input_bound[0],
                                            self._input_bound[1])
                current_loss = loss_net(Tensor(inversion_image_n),
                                        Tensor(target_feature_n))
                LOGGER.info(
                    TAG,
                    'iteration step: {}, loss is {}'.format(s, current_loss))
            inversion_images.append(inversion_image_n)
        return np.concatenate(np.array(inversion_images))
Example #6
0
class GradientMethod(Attack):
    """
    Abstract base class for all single-step gradient-based attacks.

    Args:
        network (Cell): Target model.
        eps (float): Proportion of single-step adversarial perturbation generated
            by the attack to data range. Default: 0.07.
        alpha (float): Proportion of single-step random perturbation to data range.
            Default: None.
        bounds (tuple): Upper and lower bounds of data, indicating the data range.
            In form of (clip_min, clip_max). Default: None.
        loss_fn (Loss): Loss function for optimization. Default: None.

    Examples:
        >>> inputs = np.array([[0.1, 0.2, 0.6], [0.3, 0, 0.4]])
        >>> labels = np.array([[0, 1, 0, 0, 0], [0, 0, 1, 0, 0]])
        >>> attack = FastGradientMethod(network)
        >>> adv_x = attack.generate(inputs, labels)
    """
    def __init__(self,
                 network,
                 eps=0.07,
                 alpha=None,
                 bounds=None,
                 loss_fn=None):
        super(GradientMethod, self).__init__()
        self._network = check_model('network', network, Cell)
        self._eps = check_value_positive('eps', eps)
        self._dtype = None
        if bounds is not None:
            self._bounds = check_param_multi_types('bounds', bounds,
                                                   [list, tuple])
            for b in self._bounds:
                _ = check_param_multi_types('bound', b, [int, float])
        else:
            self._bounds = bounds
        if alpha is not None:
            self._alpha = check_value_positive('alpha', alpha)
        else:
            self._alpha = alpha
        if loss_fn is None:
            loss_fn = SoftmaxCrossEntropyWithLogits(is_grad=False,
                                                    sparse=False)
        with_loss_cell = WithLossCell(self._network, loss_fn)
        self._grad_all = GradWrapWithLoss(with_loss_cell)
        self._grad_all.set_train()

    def generate(self, inputs, labels):
        """
        Generate adversarial examples based on input samples and original/target labels.

        Args:
            inputs (numpy.ndarray): Benign input samples used as references to create
                    adversarial examples.
            labels (numpy.ndarray): Original/target labels.

        Returns:
            numpy.ndarray, generated adversarial examples.
        """
        inputs, labels = check_pair_numpy_param('inputs', inputs, 'labels',
                                                labels)
        self._dtype = inputs.dtype
        gradient = self._gradient(inputs, labels)
        # use random method or not
        if self._alpha is not None:
            random_part = self._alpha * np.sign(
                np.random.normal(size=inputs.shape)).astype(self._dtype)
            perturbation = (self._eps - self._alpha) * gradient + random_part
        else:
            perturbation = self._eps * gradient

        if self._bounds is not None:
            clip_min, clip_max = self._bounds
            perturbation = perturbation * (clip_max - clip_min)
            adv_x = inputs + perturbation
            adv_x = np.clip(adv_x, clip_min, clip_max)
        else:
            adv_x = inputs + perturbation
        return adv_x

    @abstractmethod
    def _gradient(self, inputs, labels):
        """
        Calculate gradients based on input samples and original/target labels.

        Args:
            inputs (numpy.ndarray): Benign input samples used as references to
                create adversarial examples.
            labels (numpy.ndarray): Original/target labels.

        Raises:
            NotImplementedError: It is an abstract method.
        """
        msg = 'The function _gradient() is an abstract method in class ' \
              '`GradientMethod`, and should be implemented in child class.'
        LOGGER.error(TAG, msg)
        raise NotImplementedError(msg)