示例#1
0
    def _verify_and_process_inputs(self, x, y):
        if self.targeted:
            assert y is not None

        if not self.targeted:
            if y is None:
                y = self._get_predicted_label(x)

        x = replicate_input(x)
        y = replicate_input(y)
        return x, y
示例#2
0
 def perturb_single(self, x, y):
     # x shape [C * H * W]
     if self.comply_with_foolbox is True:
         np.random.seed(233333)
         rand_np = np.random.permutation(x.shape[1] * x.shape[2])
         pixels = torch.from_numpy(rand_np)
     else:
         pixels = torch.randperm(x.shape[1] * x.shape[2])
     pixels = pixels.to(x.device)
     pixels = pixels[:self.max_pixels]
     for ii in range(self.max_pixels):
         row = pixels[ii] % x.shape[2]
         col = pixels[ii] // x.shape[2]
         for val in [self.clip_min, self.clip_max]:
             adv = replicate_input(x)
             for mm in range(x.shape[0]):
                 adv[mm, row, col] = val
             out_label = self._get_predicted_label(adv.unsqueeze(0))
             if self.targeted is True:
                 if int(out_label[0]) == int(y):
                     return adv
             else:
                 if int(out_label[0]) != int(y):
                     return adv
     return x
示例#3
0
 def _perturb_seed_pixel(self, x, p, row, col):
     x_pert = replicate_input(x)
     for ii in range(x.shape[0]):
         if x[ii, row, col] > 0:
             x_pert[ii, row, col] = p
         elif x[ii, row, col] < 0:
             x_pert[ii, row, col] = -1 * p
         else:
             x_pert[ii, row, col] = 0
     return x_pert
    def perturb(self, source, guide, delta=None):
        """
        Given source, returns their adversarial counterparts
        with representations close to that of the guide.

        :param source: input tensor which we want to perturb.
        :param guide: targeted input.
        :param delta: tensor contains the random initialization.
        :return: tensor containing perturbed inputs.
        """
        # Initialization
        if delta is None:
            delta = torch.zeros_like(source)
            if self.rand_init:
                delta = delta.uniform_(-self.eps, self.eps)
        else:
            delta = delta.detach()

        delta.requires_grad_()

        source = replicate_input(source)
        guide = replicate_input(guide)
        guide_ftr = self.predict(guide).detach()

        xadv = perturb_iterative(source,
                                 guide_ftr,
                                 self.predict,
                                 self.nb_iter,
                                 eps_iter=self.eps_iter,
                                 loss_fn=self.loss_fn,
                                 minimize=True,
                                 ord=np.inf,
                                 eps=self.eps,
                                 clip_min=self.clip_min,
                                 clip_max=self.clip_max,
                                 delta_init=delta)

        xadv = clamp(xadv, self.clip_min, self.clip_max)

        return xadv.data
示例#5
0
    def perturb(self, x, y=None):
        x, y = self._verify_and_process_inputs(x, y)

        # Initialization
        if y is None:
            y = self._get_predicted_label(x)
        x = replicate_input(x)
        batch_size = len(x)
        coeff_lower_bound = x.new_zeros(batch_size)
        coeff_upper_bound = x.new_ones(batch_size) * CARLINI_COEFF_UPPER
        loss_coeffs = torch.ones_like(y).float() * self.initial_const
        final_l2distsqs = [CARLINI_L2DIST_UPPER] * batch_size
        final_labels = [INVALID_LABEL] * batch_size
        final_advs = x
        x_atanh = self._get_arctanh_x(x)
        y_onehot = to_one_hot(y, self.num_classes).float()

        final_l2distsqs = torch.FloatTensor(final_l2distsqs).to(x.device)
        final_labels = torch.LongTensor(final_labels).to(x.device)

        # Start binary search
        for outer_step in range(self.binary_search_steps):
            delta = nn.Parameter(torch.zeros_like(x))
            optimizer = optim.Adam([delta], lr=self.learning_rate)
            cur_l2distsqs = [CARLINI_L2DIST_UPPER] * batch_size
            cur_labels = [INVALID_LABEL] * batch_size
            cur_l2distsqs = torch.FloatTensor(cur_l2distsqs).to(x.device)
            cur_labels = torch.LongTensor(cur_labels).to(x.device)
            prevloss = PREV_LOSS_INIT

            if (self.repeat and outer_step == (self.binary_search_steps - 1)):
                loss_coeffs = coeff_upper_bound
            for ii in range(self.max_iterations):
                loss, l2distsq, output, adv_img = \
                    self._forward_and_update_delta(
                        optimizer, x_atanh, delta, y_onehot, loss_coeffs)
                if self.abort_early:
                    if ii % (self.max_iterations // NUM_CHECKS or 1) == 0:
                        if loss > prevloss * ONE_MINUS_EPS:
                            break
                        prevloss = loss

                self._update_if_smaller_dist_succeed(
                    adv_img, y, output, l2distsq, batch_size,
                    cur_l2distsqs, cur_labels,
                    final_l2distsqs, final_labels, final_advs)

            self._update_loss_coeffs(
                y, cur_labels, batch_size,
                loss_coeffs, coeff_upper_bound, coeff_lower_bound)

        return final_advs
示例#6
0
    def perturb(self, x, y=None):

        x, y = self._verify_and_process_inputs(x, y)

        # Initialization
        if y is None:
            y = self._get_predicted_label(x)

        x = replicate_input(x)
        batch_size = len(x)
        coeff_lower_bound = x.new_zeros(batch_size)
        coeff_upper_bound = x.new_ones(batch_size) * COEFF_UPPER
        loss_coeffs = torch.ones_like(y).float() * self.initial_const

        final_dist = [DIST_UPPER] * batch_size
        final_labels = [INVALID_LABEL] * batch_size

        final_advs = x.clone()
        y_onehot = to_one_hot(y, self.num_classes).float()

        final_dist = torch.FloatTensor(final_dist).to(x.device)
        final_labels = torch.LongTensor(final_labels).to(x.device)

        # Start binary search
        for outer_step in range(self.binary_search_steps):

            self.global_step = 0

            # slack vector from the paper
            yy_k = nn.Parameter(x.clone())
            xx_k = x.clone()

            cur_dist = [DIST_UPPER] * batch_size
            cur_labels = [INVALID_LABEL] * batch_size

            cur_dist = torch.FloatTensor(cur_dist).to(x.device)
            cur_labels = torch.LongTensor(cur_labels).to(x.device)

            prevloss = PREV_LOSS_INIT

            if (self.repeat and outer_step == (self.binary_search_steps - 1)):
                loss_coeffs = coeff_upper_bound

            lr = self.learning_rate

            for ii in range(self.max_iterations):

                # reset gradient
                if yy_k.grad is not None:
                    yy_k.grad.detach_()
                    yy_k.grad.zero_()

                # loss over yy_k with only L2 same as C&W
                # we don't update L1 loss with SGD because we use ISTA
                output = self.predict(yy_k)
                l2distsq = calc_l2distsq(yy_k, x)
                loss_opt = self._loss_fn(output,
                                         y_onehot,
                                         None,
                                         l2distsq,
                                         loss_coeffs,
                                         opt=True)
                loss_opt.backward()

                # gradient step
                yy_k.data.add_(-lr, yy_k.grad.data)
                self.global_step += 1

                # ploynomial decay of learning rate
                lr = self.init_learning_rate * \
                    (1 - self.global_step / self.max_iterations)**0.5

                yy_k, xx_k = self._fast_iterative_shrinkage_thresholding(
                    x, yy_k, xx_k)

                # loss ElasticNet or L1 over xx_k
                output = self.predict(xx_k)
                l2distsq = calc_l2distsq(xx_k, x)
                l1dist = calc_l1dist(xx_k, x)

                if self.decision_rule == 'EN':
                    dist = l2distsq + (l1dist * self.beta)
                elif self.decision_rule == 'L1':
                    dist = l1dist
                loss = self._loss_fn(output, y_onehot, l1dist, l2distsq,
                                     loss_coeffs)

                if self.abort_early:
                    if ii % (self.max_iterations // NUM_CHECKS or 1) == 0:
                        if loss > prevloss * ONE_MINUS_EPS:
                            break
                        prevloss = loss

                self._update_if_smaller_dist_succeed(xx_k.data, y, output,
                                                     dist, batch_size,
                                                     cur_dist, cur_labels,
                                                     final_dist, final_labels,
                                                     final_advs)

            self._update_loss_coeffs(y, cur_labels, batch_size, loss_coeffs,
                                     coeff_upper_bound, coeff_lower_bound)

        return final_advs
示例#7
0
    def perturb_single(self, x, y):
        # x shape C * H * W
        rescaled_x = replicate_input(x)
        best_img = None
        best_dist = np.inf
        rescaled_x, lb, ub = self._rescale_to_m0d5_to_0d5(rescaled_x,
                                                          vmin=self.clip_min,
                                                          vmax=self.clip_max)

        if self.comply_with_foolbox is True:
            np.random.seed(233333)
            init_rand = np.random.permutation(x.shape[1] * x.shape[2])
        else:
            init_rand = None

        # Algorithm 3 in v1

        pxy = self._random_sample_seeds(x.shape[1],
                                        x.shape[2],
                                        seed_ratio=self.seed_ratio,
                                        max_nb_seeds=self.max_nb_seeds,
                                        init_rand=init_rand)
        pxy = pxy.to(x.device)
        ii = 0
        if self.comply_with_foolbox:
            adv = rescaled_x
        while ii < self.round_ub:
            if not self.comply_with_foolbox:
                adv = replicate_input(rescaled_x)
            # Computing the function g using the neighbourhood
            if self.comply_with_foolbox:
                rand_np = np.random.permutation(len(pxy))[:self.max_nb_seeds]
                pxy = pxy[torch.from_numpy(rand_np)]
            else:
                pxy = pxy[torch.randperm(len(pxy))[:self.max_nb_seeds]]

            pert_lst = [
                self._perturb_seed_pixel(adv, self.p, int(row), int(col))
                for row, col in pxy
            ]
            # Compute the score for each pert in the list
            scores, curr_best_img, curr_best_dist = self._rescale_x_score(
                self.predict, pert_lst, y, x, best_dist)
            if curr_best_img is not None:
                best_img = curr_best_img
                best_dist = curr_best_dist
            _, indices = torch.sort(scores)
            indices = indices[:self.t]
            pxy_star = pxy[indices.data.cpu()]
            # Generation of the perturbed image adv
            for row, col in pxy_star:
                for b in range(x.shape[0]):
                    adv[b, int(row),
                        int(col)] = self._cyclic(self.r, lb, ub, adv[b,
                                                                     int(row),
                                                                     int(col)])
            # Check whether the perturbed image is an adversarial image
            revert_adv = self._revert_rescale(adv)
            curr_lb = self._get_predicted_label(revert_adv.unsqueeze(0))
            curr_dist = torch.sum((x - revert_adv)**2)
            if (is_successful(int(curr_lb), y, self.targeted)
                    and curr_dist < best_dist):
                best_img = revert_adv
                best_dist = curr_dist
                return best_img
            elif is_successful(curr_lb, y, self.targeted):
                return best_img
            pxy = [(row, col) for rowcenter, colcenter in pxy_star
                   for row in range(
                       int(rowcenter) - self.d,
                       int(rowcenter) + self.d + 1) for col in range(
                           int(colcenter) - self.d,
                           int(colcenter) + self.d + 1)]
            pxy = list(
                set((row, col) for row, col in pxy
                    if (0 <= row < x.shape[2] and 0 <= col < x.shape[1])))
            pxy = torch.FloatTensor(pxy)
            ii += 1
        if best_img is None:
            return x
        return best_img