Esempio n. 1
0
    def test_optimize_linear_l1_ties(self):
        grad = torch.tensor([[2.0, -2.0]])
        eta = utils.optimize_linear(grad, eps=1.0, norm=1)
        objective = torch.sum(grad * eta)

        self.assertEqual(grad.size(), eta.size())
        self.assertClose(objective, 2.0)
        self.assertClose(eta.abs().sum(), 1.0)
Esempio n. 2
0
    def test_optimize_linear_l2(self):
        grad = torch.tensor([[0.5**0.5, -(0.5**0.5)]])
        eta = utils.optimize_linear(grad, eps=1.0, norm=2)
        objective = torch.sum(grad * eta)

        self.assertEqual(grad.size(), eta.size())
        self.assertClose(objective, 1.0)
        self.assertClose(eta.pow(2).sum().sqrt(), 1.0)
Esempio n. 3
0
def get_mc_P_adv(prob_net, P_adv, eps_iter, norm, loss_fn, N_MC):
    g = 0.0
    for j in range(N_MC):
        g_j = get_grad(prob_net, P_adv, eps_iter, norm, model_pred, loss_fn)
        g += 1/N_MC * g_j
    eta = optimize_linear(g, eps, norm)    
    P_adv = P_adv + eta    
    return P_adv
Esempio n. 4
0
    def test_optimize_linear_linf(self):
        grad = torch.tensor([[1., -2.]])
        eta = utils.optimize_linear(grad, eps=1., norm=np.inf)
        objective = torch.sum(grad * eta)

        self.assertEqual(grad.size(), eta.size())
        self.assertClose(objective, grad.abs().sum())
        self.assertClose(eta.abs(), 1.)
Esempio n. 5
0
def fast_gradient_method(
    model_fn,
    x,
    eps,
    norm,
    clip_min=None,
    clip_max=None,
    y=None,
    targeted=False,
    sanity_checks=False,
):
    """
    PyTorch implementation of the Fast Gradient Method.
    :param model_fn: a callable that takes an input tensor and returns the model logits.
    :param x: input tensor.
    :param eps: epsilon (input variation parameter); see https://arxiv.org/abs/1412.6572.
    :param norm: Order of the norm (mimics NumPy). Possible values: np.inf, 1 or 2.
    :param clip_min: (optional) float. Minimum float value for adversarial example components.
    :param clip_max: (optional) float. Maximum float value for adversarial example components.
    :param y: (optional) Tensor with true labels. If targeted is true, then provide the
              target label. Otherwise, only provide this parameter if you'd like to use true
              labels when crafting adversarial samples. Otherwise, model predictions are used
              as labels to avoid the "label leaking" effect (explained in this paper:
              https://arxiv.org/abs/1611.01236). Default is None.
    :param targeted: (optional) bool. Is the attack targeted or untargeted?
              Untargeted, the default, will try to make the label incorrect.
              Targeted will instead try to move in the direction of being more like y.
    :param sanity_checks: bool, if True, include asserts (Turn them off to use less runtime /
              memory or for unit tests that intentionally pass strange input)
    :return: a tensor for the adversarial example
    """
    x_grad = _fast_gradient_method_grad(model_fn=model_fn,
                                        x=x,
                                        eps=eps,
                                        norm=norm,
                                        clip_min=clip_min,
                                        clip_max=clip_max,
                                        y=y,
                                        targeted=targeted,
                                        sanity_checks=sanity_checks)
    optimal_perturbation = optimize_linear(x_grad, eps, norm)

    # Add perturbation to original example to obtain adversarial example
    adv_x = x + optimal_perturbation

    # If clipping is needed, reset all values outside of [clip_min, clip_max]
    if (clip_min is not None) or (clip_max is not None):
        if clip_min is None or clip_max is None:
            raise ValueError(
                "One of clip_min and clip_max is None but we don't currently support one-sided clipping"
            )
        adv_x = torch.clamp(adv_x, clip_min, clip_max)

    return adv_x
Esempio n. 6
0
 def test_optimize_linear_l2_satisfies_norm_constraint(self):
     for eps in self.eps_list:
         eta = utils.optimize_linear(self.rand_grad, eps=eps, norm=2)
         # optimize_linear uses avoid_zero_div as the divisor for
         # gradients with overly small l2 norms when performing norm
         # normalizations on the gradients so as to safeguard against
         # zero division error. Therefore, the replaced gradient vectors
         # will not be l2-unit vectors after normalization. In this test,
         # these gradients are filtered out by the one_mask
         # below and are not tested.
         # NOTE the value of avoid_zero_div should be the same as the
         # avoid_zero_div used in the optimize_linear function
         avoid_zero_div = torch.tensor(1e-12)
         square = torch.max(
             avoid_zero_div,
             torch.sum(self.rand_grad**2, self.red_ind, keepdim=True))
         norm = eta.pow(2).sum(dim=self.red_ind, keepdim=True).sqrt()
         one_mask = ((square <= avoid_zero_div).to(torch.float) * norm +
                     (square > avoid_zero_div).to(torch.float))
         self.assertTrue(torch.allclose(norm, eps * one_mask))
Esempio n. 7
0
def fast_gradient_method(
    model_fn,
    x,
    eps,
    norm,
    clip_min=None,
    clip_max=None,
    y=None,
    targeted=False,
    sanity_checks=False,
):
    """
    PyTorch implementation of the Fast Gradient Method.
    :param model_fn: a callable that takes an input tensor and returns the model logits.
    :param x: input tensor.
    :param eps: epsilon (input variation parameter); see https://arxiv.org/abs/1412.6572.
    :param norm: Order of the norm (mimics NumPy). Possible values: np.inf, 1 or 2.
    :param clip_min: (optional) float. Minimum float value for adversarial example components.
    :param clip_max: (optional) float. Maximum float value for adversarial example components.
    :param y: (optional) Tensor with true labels. If targeted is true, then provide the
              target label. Otherwise, only provide this parameter if you'd like to use true
              labels when crafting adversarial samples. Otherwise, model predictions are used
              as labels to avoid the "label leaking" effect (explained in this paper:
              https://arxiv.org/abs/1611.01236). Default is None.
    :param targeted: (optional) bool. Is the attack targeted or untargeted?
              Untargeted, the default, will try to make the label incorrect.
              Targeted will instead try to move in the direction of being more like y.
    :param sanity_checks: bool, if True, include asserts (Turn them off to use less runtime /
              memory or for unit tests that intentionally pass strange input)
    :return: a tensor for the adversarial example
    """
    if norm not in [np.inf, 1, 2]:
        raise ValueError(
            "Norm order must be either np.inf, 1, or 2, got {} instead.".
            format(norm))
    if eps < 0:
        raise ValueError(
            "eps must be greater than or equal to 0, got {} instead".format(
                eps))
    if eps == 0:
        return x
    if clip_min is not None and clip_max is not None:
        if clip_min > clip_max:
            raise ValueError(
                "clip_min must be less than or equal to clip_max, got clip_min={} and clip_max={}"
                .format(clip_min, clip_max))

    asserts = []

    # If a data range was specified, check that the input was in that range
    if clip_min is not None:
        assert_ge = torch.all(
            torch.ge(x, torch.tensor(clip_min, device=x.device,
                                     dtype=x.dtype)))
        asserts.append(assert_ge)

    if clip_max is not None:
        assert_le = torch.all(
            torch.le(x, torch.tensor(clip_max, device=x.device,
                                     dtype=x.dtype)))
        asserts.append(assert_le)

    # x needs to be a leaf variable, of floating point type and have requires_grad being True for
    # its grad to be computed and stored properly in a backward call
    x = x.clone().detach().to(torch.float).requires_grad_(True)
    if y is None:
        # Using model predictions as ground truth to avoid label leaking
        _, y = torch.max(model_fn(x), 1)

    # Compute loss
    loss_fn = torch.nn.CrossEntropyLoss()
    loss = loss_fn(model_fn(x), y)
    # If attack is targeted, minimize loss of target label rather than maximize loss of correct label
    if targeted:
        loss = -loss

    # Define gradient of loss wrt input
    loss.backward()
    optimal_perturbation = optimize_linear(x.grad, eps, norm)

    # Add perturbation to original example to obtain adversarial example
    adv_x = x + optimal_perturbation

    # If clipping is needed, reset all values outside of [clip_min, clip_max]
    if (clip_min is not None) or (clip_max is not None):
        if clip_min is None or clip_max is None:
            raise ValueError(
                "One of clip_min and clip_max is None but we don't currently support one-sided clipping"
            )
        adv_x = torch.clamp(adv_x, clip_min, clip_max)

    if sanity_checks:
        assert np.all(asserts)
    return adv_x
Esempio n. 8
0
 def test_optimize_linear_l1_satisfies_norm_constraint(self):
     for eps in self.eps_list:
         eta = utils.optimize_linear(self.rand_grad, eps=eps, norm=1)
         norm = eta.abs().sum(dim=self.red_ind)
         self.assertTrue(torch.allclose(norm, eps * torch.ones_like(norm)))
Esempio n. 9
0
 def test_optimize_linear_linf_satisfies_norm_constraint(self):
     for eps in self.eps_list:
         eta = utils.optimize_linear(self.rand_grad, eps=eps, norm=np.inf)
         self.assertClose(eta.abs(), eps)