Esempio n. 1
0
    def project_params(self, lp, lp_bound):
        """ Projects the params to be within lp_bound (according to an lp)
            of the identity map. First thing we do is clip the params to be
            valid, too
        ARGS:
            lp : int or 'inf' - which LP norm we use. Must be an int or the
                 string 'inf'
            lp_bound : float - how far we're allowed to go in LP land
        RETURNS:
            None, but modifies self.xform_params
        """

        assert isinstance(lp, int) or lp == 'inf'

        # clip first
        self.clip_params()

        # then project back

        if lp == 'inf':
            identity_params = self.identity_params(self.img_shape)
            clamp_params = utils.clamp_ref(self.xform_params.data,
                                           identity_params, lp_bound)
            change_in_params = clamp_params - self.xform_params.data
            self.xform_params.data.add_(change_in_params)
        else:
            raise NotImplementedError(
                "Only L-infinity bounds working for now ")
Esempio n. 2
0
    def project_params(self, lp, lp_bound):
        """
        Projects the params to be within lp_bound (according to an lp)
        of the identity map. First thing we do is clip the params to be
        valid, too.
        ARGS:
            lp : int or 'inf' - which LP norm we use. Must be an int or the
                 string 'inf'.
            lp_bound : float - how far we're allowed to go in LP land. Can be
                 a list to indicate that we can go more in some channels
                 than others.
        RETURNS:
            None, but modifies self.xform_params
        """

        assert isinstance(lp, int) or lp == 'inf'

        # clip first
        self.clip_params()

        # then project back
        if lp == 'inf':
            try:
                # first, assume lp_bound is a vector, and then revert to scalar
                # if it's not
                clamped_channels = []
                for channel_index, bound in enumerate(lp_bound):
                    clamped_channels.append(
                        utils.clamp_ref(
                            self.xform_params[..., channel_index],
                            self.identity_params[..., channel_index],
                            bound,
                        ))
                clamp_params = torch.stack(clamped_channels, 4)
            except TypeError:
                clamp_params = utils.clamp_ref(self.xform_params.data,
                                               self.identity_params, lp_bound)
            change_in_params = clamp_params - self.xform_params.data
        else:
            flattened_params = (self.xform_params.data -
                                self.identity_params).reshape((-1, 3))
            projected_params = flattened_params.renorm(lp, 0, lp_bound)
            flattened_change = projected_params - flattened_params
            change_in_params = flattened_change.reshape(
                self.xform_params.size())
        self.xform_params.data.add_(change_in_params)
    def _do_iteration(self, intermed_images, var_labels, signed, step_size,
                      l_inf_bound, reference_var):

        self.loss_fxn.zero_grad()
        loss = self.loss_fxn.forward(intermed_images, var_labels)
        torch.autograd.backward(loss)

        # Take a step and 'project'
        if signed:
            perturbation = torch.sign(intermed_images.grad.data) * step_size
        else:
            perturbation = intermed_images.grad.data * step_size

        clamp_inf = utils.clamp_ref(intermed_images.data + perturbation,
                                    reference_var.data, l_inf_bound)
        clamp_box = torch.clamp(clamp_inf, 0., 1.)
        intermed_images = Variable(clamp_box, requires_grad=True)
        return Variable(intermed_images.data, requires_grad=True)
    def attack(self,
               examples,
               labels,
               l_inf_bound=0.05,
               step_size=1 / 255.,
               num_iterations=None,
               verbose=True):
        """ Builds BIM examples for the given examples with l_inf bound, and
            given step_size
        ARGS:
            examples: Nxcxwxh tensor for N examples. NOT NORMALIZED (i.e. all
                      vals are between 0.0 and 1.0 )
            labels: single-dimension tensor with labels of examples (in same
                    order)
            l_inf_bound: float between 0.0 and 1.0 of maximum l_infinity bound
            step_size: how much to step each time. 1/256 is a nice value here
            normalizer: DifferentiableNormalize object to prep objects into
                        classifier
            loss_fxn:  RegularizedLoss object - partially applied loss fxn that
                         takes [0.0, 1.0] image Variables and labels and outputs
                         a scalar loss variable. Also has a zero_grad method
            num_iterations: int - if not None should be an integer number of
                                  iterations. Defaults to the default from the
                                  original paper
        RETURNS:
            Nxcxwxh tensor with adversarial examples,
        """

        ######################################################################
        #   Setups and assertions                                            #
        ######################################################################

        assert 0 < l_inf_bound < 1.0

        # use original paper to figure out num_iterations
        # https://arxiv.org/pdf/1607.02533.pdf
        num_iterations = num_iterations or int(
            min([l_inf_bound * 255 + 4, l_inf_bound * 255 * 1.25]) + 1)

        if not verbose:
            self.validator = lambda ex, label, iter_no: None
        else:
            self.validator = self.validation_loop

        self.classifier_net.eval()  # ALWAYS EVAL FOR BUILDING ADV EXAMPLES
        var_examples = Variable(examples, requires_grad=True)
        var_labels = Variable(labels, requires_grad=False)

        # Fix the 'reference' images for the loss function
        self.loss_fxn.setup_attack_batch(var_examples.clone())
        ######################################################################
        #   Build adversarial examples                                       #
        ######################################################################

        intermed_images = var_examples
        self.validator(intermed_images, var_labels, iter_no="START")

        # Start iterating...
        for iter_no in xrange(num_iterations):

            # Reset gradients, then take another gradient
            self.loss_fxn.zero_grad()
            loss = self.loss_fxn.forward(intermed_images, var_labels)

            torch.autograd.backward(loss)

            # Take a step and then clamp
            signs = torch.sign(intermed_images.grad.data) * step_size
            clamp_inf = utils.clamp_ref(intermed_images.data + signs, examples,
                                        l_inf_bound)
            clamp_box = torch.clamp(clamp_inf, 0., 1.)

            # Setup for next
            intermed_images = Variable(clamp_box, requires_grad=True)
            self.validator(intermed_images, var_labels, iter_no=iter_no)

        return intermed_images.data