예제 #1
0
    def __init__(self, num_classes, resnet_backbone='ResNet50', pretrained=True, mode=None):
        super(Saliency_noskip, self).__init__()
        self.mode = mode
        self.num_classes = num_classes
        self.resnet_backbone = resnet_backbone

        if resnet_backbone == 'ResNet18':
            layers = [2, 2, 2, 2]
        elif resnet_backbone == 'ResNet50':
            layers = [3, 4, 6, 3]
        else:
            print('given Resnet backbone does not exist')

        self.pretrained = pretrained

        # build the network architecture
        # encoder --Resnet50 without final pooling and fc
        self.pretrained_resnet = resnet50(pretrained=self.pretrained)
        self._modify_resnet(num_classes)

        # either set to bilinear or nearest and allign corners
        self.upsample = Upsample(scale_factor=8, mode='bilinear', align_corners=True)

        #reduce to num_classes
        self.onexone = torch.nn.Conv2d(in_channels=2048, out_channels=self.num_classes, kernel_size=1)

        # use a softmax if dataset is mutually exclusive.
        self.sigmoid = nn.Sigmoid()
        #todo: make these layers overridable, such that parameters can be set from training script.
        # self.softmax = nn.Softmax(dim=1)

        self.pooling = CustomPooling(beta=1, r_0=10, dim=(-1, -2), mode='Three')

        self.norm = CustomNorm(1)
예제 #2
0
    def __init__(self, num_classes, resnet_backbone='ResNet50', pretrained=True, mode=None):
        super(Saliency_simple, self).__init__()
        self.mode = mode
        self.num_classes = num_classes
        self.resnet_backbone = resnet_backbone

        if resnet_backbone == 'ResNet18':
            layers = [2, 2, 2, 2]
        elif resnet_backbone == 'ResNet50':
            layers = [3, 4, 6, 3]
        else:
            print('given Resnet backbone does not exist')

        self.pretrained = pretrained

        # build the network architecture
        # encoder --Resnet50 without final pooling and fc
        self.pretrained_resnet = resnet50(pretrained=self.pretrained)
        self._modify_resnet(num_classes)

        # either set to bilinear or nearest and allign corners
        self.upsample = Upsample(scale_factor=2, mode='bilinear', align_corners=True)

        #reduce to num_classes
        self.onexone = torch.nn.Conv2d(in_channels=3840, out_channels=self.num_classes, kernel_size=1)

        # Decoder path with skip connections, only upsampling and concatenation
        if self.mode is not None:
            if self.mode == 'mode1':
                # # 1x1 conv2@d to reduce filters from 2048 - 1024
                self.onexone1 = torch.nn.Conv2d(2048, 512, 1)
                self.onexone2 = torch.nn.Conv2d(1024, 256, 1)
                self.onexone3 = torch.nn.Conv2d(512, 128, 1)
                self.onexone4 = torch.nn.Conv2d(256, 64, 1)
                self.activation = torch.nn.ReLU()
                # reduce to num_classes
                self.onexone = torch.nn.Conv2d(in_channels=960, out_channels=self.num_classes, kernel_size=1)

            elif self.mode == 'mode2':
                self.onexone1 = torch.nn.Conv2d(2048, 20, 1)
                self.onexone2 = torch.nn.Conv2d(1024, 20, 1)
                self.onexone3 = torch.nn.Conv2d(512, 20, 1)
                self.onexone4 = torch.nn.Conv2d(256, 20, 1)
                self.activation = torch.nn.ReLU()
                # reduce to num_classes
                self.onexone = torch.nn.Conv2d(in_channels=80, out_channels=self.num_classes, kernel_size=1)

        #upsample to increase spatial resolution from 8x8 to 16x16


        # use a softmax if dataset is mutually exclusive.
        self.sigmoid = nn.Sigmoid()
        #todo: make these layers overridable, such that parameters can be set from training script.
        # self.softmax = nn.Softmax(dim=1)

        self.pooling = CustomPooling(beta=1, r_0=10, dim=(-1, -2), mode='Three')

        self.norm = CustomNorm(1)
예제 #3
0
    def __init__(self, num_classes, resnet_backbone='ResNet50', pretrained=True, mode=None):
        super(SaliencyUNet, self).__init__()

        self.num_classes = num_classes
        self.mode = mode
        self.resnet_backbone = resnet_backbone

        if resnet_backbone == 'ResNet18':
            layers = [2, 2, 2, 2]
        elif resnet_backbone =='ResNet50':
            layers = [3, 4, 6, 3]
        else:
            print('given Resnet backbone does not exist')

        self.pretrained = pretrained

        # build the network architecture
        # encoder --Resnet50 without final pooling and fc
        self.pretrained_resnet = resnet50(pretrained=self.pretrained)
        self._modify_resnet(num_classes)



        # Decoder path with skip connections

        # 1x1 conv2@d to reduce filters from 2048 - 1024
        self.onexone1 = torch.nn.Conv2d(2048, 1024, 1)
        self.activation = torch.nn.ReLU()
        #upsample to increase spatial resolution from 8x8 to 16x16
        # either set to bilinear or nearest and allign corners
        self.upsample = Upsample(scale_factor=2, mode='bilinear', align_corners=True)
        #concat the upsampled featurespace with the encoder feature space at resolution level 16x16
        # convolution with 3x3 filter and reduction of channels 2048 - 512
        self.conv1 = ConvRelu(2048, 512)

        #upsample 16 --> 32
        # concat with 512 res feature space
        # convolution with 3x3 filter and reduction of channels 1024 - 256
        self.conv2 = ConvRelu(1024, 256)

        #upsample 32 --> 64
        # concat with 512 res feature space
        # convolution with 3x3 filter and reduction of channels 1024 - 256
        self.conv3 = ConvRelu(512, 128)

        #reduce to num_classes
        self.onexone = torch.nn.Conv2d(in_channels=128, out_channels=self.num_classes, kernel_size=1)

        # use a softmax if dataset is mutually exclusive.
        self.sigmoid = nn.Sigmoid()
        #todo: make these layers overridable, such that parameters can be set from training script.
        # self.softmax = nn.Softmax(dim=1)

        self.pooling = CustomPooling(beta=1, r_0=10, dim=(-1, -2), mode='Three')

        self.norm = CustomNorm(1)
 def _perturb_image(self, image, noise):
     """Given an image and a noise, generate a perturbed image.
     First, resize the noise with the size of the image.
     Then, add the resized noise to the image.
     Args:
       image: numpy array of size [1, 299, 299, 3], an original image
       noise: numpy array of size [1, 256, 256, 3], a noise
     Returns:
       adv_iamge: numpy array with size [1, 299, 299, 3], a perturbed image
     """
     upsampler = Upsample(size=(self.width, self.height))
     noise = upsampler(torch.tensor(noise))
     adv_image = np.clip(image + noise, 0., 1.)
     return adv_image
예제 #5
0
def upsample_maker(target_h, target_w):
    """
    makes an upsampler which takes a numpy tensor of the form
    minibatch x channels x h x w and casts to
    minibatch x channels x target_h x target_w
    :param target_h: int to specify the desired height
    :param target_w: int to specify the desired width
    :return:
    """
    _upsampler = Upsample(size=(target_h, target_w))

    def upsample_fct(xs):
        if ch.is_tensor(xs):
            return _upsampler(xs)
        else:
            return _upsampler(ch.from_numpy(xs)).numpy()

    return upsample_fct
예제 #6
0
    def bandit(self, input_xi, label, epsilon, eta, TARGETED):
        img_dim = input_xi.size(-1)
        #channel = input_xi.size(0)
        batch_size = input_xi.size(0)
        upsampler = Upsample(size=(img_dim, img_dim))
        prior = torch.zeros(input_xi.size()).cuda()
        dim = prior.numel() / batch_size
        prior_step = gd_prior_step if self.mode == 'l2' else eg_step
        image_step = l2_image_step if self.mode == 'l2' else linf_step
        proj_maker = l2_proj if self.mode == 'l2' else linf_proj
        image = input_xi.detach().clone()
        print(image.max(), image.min())
        proj_step = proj_maker(image, epsilon)

        orig_classes = self.model.predict_prob(input_xi).argmax(1).cuda()
        correct_classified_mask = (orig_classes == label).float()

        for _ in range(1000):
            exp_noise = self.exploration * torch.randn_like(prior) / (dim**0.5)
            exp_noise = exp_noise.cuda()
            # Query deltas for finite difference estimator
            q1 = upsampler(prior + exp_noise).cuda()
            q2 = upsampler(prior - exp_noise).cuda()
            # Loss points for finite difference estimator
            #print(q1.size())
            l1 = self.get_loss(image + self.fd_eta * q1 / norm(q1), label)
            l2 = self.get_loss(image + self.fd_eta * q2 / norm(q2), label)
            #print(l1.data.item())
            #l1 = L(image + args.fd_eta*q1/norm(q1)) # L(prior + c*noise)
            #l2 = L(image + args.fd_eta*q2/norm(q2)) # L(prior - c*noise)
            # Finite differences estimate of directional derivative
            est_deriv = (l1 - l2) / (self.fd_eta * self.exploration)
            # 2-query gradient estimate
            est_grad = est_deriv.view(-1, 1, 1, 1) * exp_noise
            # Update the prior with the estimated gradient
            prior = prior_step(prior, est_grad, self.online_lr)
            new_im = image_step(
                image,
                upsampler(prior * correct_classified_mask.view(-1, 1, 1, 1)),
                eta)
            image = proj_step(new_im)
            image = torch.clamp(image, 0, 1)

        return image
def make_adversarial_examples(image,
                              true_label,
                              model_to_fool,
                              nes=False,
                              loss="xent",
                              mode="linf",
                              epsilon=8. / 256,
                              max_queries=50000,
                              gradient_iters=1,
                              fd_eta=0.1,
                              image_lr=0.0001,
                              online_lr=100,
                              exploration=0.01,
                              prior_size=15,
                              targeted=False,
                              log_progress=True,
                              device='cpu'):
    '''
    The main process for generating adversarial examples with priors.
    '''

    with torch.no_grad():
        # Initial setup
        batch_size = image.size(0)
        total_queries = torch.zeros(batch_size).to(device)
        upsampler = Upsample(size=(image.size(2), image.size(2)))
        prior = torch.zeros(batch_size, 3, prior_size, prior_size).to(device)

        dim = prior.nelement() / batch_size
        prior_step = gd_prior_step if mode == 'l2' else eg_step
        image_step = l2_image_step if mode == 'l2' else linf_step
        proj_maker = l2_proj if mode == 'l2' else linf_proj
        proj_step = proj_maker(image, epsilon)

        # Loss function
        if targeted:
            criterion = -torch.nn.CrossEntropyLoss(reduction='none')
        else:
            criterion = torch.nn.CrossEntropyLoss(reduction='none')

        losses = criterion(model_to_fool(image), true_label)

        # Original classifications
        orig_images = image.clone()
        orig_classes = model_to_fool(image).argmax(1).to(device)
        correct_classified_mask = (
            orig_classes == true_label).to(device).float()
        total_ims = correct_classified_mask.to(device).sum()
        not_dones_mask = correct_classified_mask.to(device).clone()

        t = 0

        while not torch.any(total_queries > max_queries):
            t += gradient_iters * 2
            if t >= max_queries:
                break
            if not nes:
                # Updating the prior:
                # Create noise for exporation, estimate the gradient, and take a PGD step
                exp_noise = exploration * torch.randn_like(prior) / (dim**0.5)
                exp_noise = exp_noise.to(device)
                # Query deltas for finite difference estimator
                q1 = upsampler(prior + exp_noise)
                q2 = upsampler(prior - exp_noise)
                # Loss points for finite difference estimator
                l1 = criterion(model_to_fool(image + fd_eta * q1 / norm(q1)),
                               true_label)  # L(prior + c*noise)
                l2 = criterion(model_to_fool(image + fd_eta * q2 / norm(q2)),
                               true_label)  # L(prior - c*noise)
                # Finite differences estimate of directional derivative
                est_deriv = (l1 - l2) / (fd_eta * exploration)
                # 2-query gradient estimate
                est_grad = est_deriv.view(-1, 1, 1, 1) * exp_noise
                # Update the prior with the estimated gradient

                prior = prior_step(prior, est_grad, online_lr)

            else:
                prior = torch.zeros_like(image)
                for _ in range(gradient_iters):
                    exp_noise = torch.randn_like(image) / (dim**0.5)
                    exp_noise = exp_noise.to(device)
                    est_deriv = (
                        criterion(model_to_fool(image + fd_eta * exp_noise),
                                  true_label) -
                        criterion(model_to_fool(image - fd_eta * exp_noise),
                                  true_label)) / fd_eta
                    prior += est_deriv.view(-1, 1, 1, 1) * exp_noise

                # Preserve images that are already done,
                # Unless we are specifically measuring gradient estimation
                prior = prior * not_dones_mask.view(-1, 1, 1, 1)

            # Update the image:
            # take a pgd step using the prior
            new_im = image_step(
                image,
                upsampler(
                    prior *
                    correct_classified_mask.to(device).view(-1, 1, 1, 1)),
                image_lr)
            image = proj_step(new_im)

            image = torch.clamp(image, 0, 1)

            # Continue query count
            total_queries += 2 * gradient_iters * not_dones_mask
            not_dones_mask = not_dones_mask * (
                (model_to_fool(image).argmax(1)
                 == true_label).to(device).float())

            # Logging stuff
            if loss == "xent":
                new_losses = criterion(model_to_fool(image),
                                       true_label).to(device)
            elif loss == "cw":
                output = model_to_fool(image)
                output = torch.nn.functional.softmax(output)
                y_onehot = to_one_hot(true_label, num_classes=image.shape[1])
                real = (y_onehot.float().to(device) *
                        output.float().to(device))
                real = real.sum(dim=1)
                other = ((1.0 - y_onehot.float().to(device)) *
                         output.float().to(device) -
                         (y_onehot.float().to(device) * 10000000)).max(1)[0]

                new_losses = torch.log(real + 1e-10) - torch.log(other + 1e-10)
            success_mask = (1 - not_dones_mask) * correct_classified_mask
            num_success = success_mask.to(device).sum()
            current_success_rate = (
                num_success / correct_classified_mask.sum()).to(device).item()
            success_queries = ((success_mask * total_queries).sum() /
                               num_success).to(device).item()
            not_done_loss = ((new_losses * not_dones_mask).to(device).sum() /
                             not_dones_mask.sum()).item()
            max_curr_queries = total_queries.max().to(device).item()
            if log_progress:
                print(
                    "Queries: %d | Success rate: %f | Average queries: %f" %
                    (max_curr_queries, current_success_rate, success_queries))

            if current_success_rate == 1.0:
                break
        if batch_size == 1:
            return {
                "image_adv": image.cpu().numpy(),
                "prediction": model_to_fool(image).argmax(1),
                "elapsed_budget": total_queries.cpu().numpy()[0],
                "success": success_mask.cpu().numpy()[0] == True
            }
        return {
            'average_queries': success_queries,
            'num_correctly_classified':
            correct_classified_mask.sum().cpu().item(),
            'success_rate': current_success_rate,
            'images_orig': orig_images.cpu().numpy(),
            'images_adv': image.cpu().numpy(),
            'all_queries': total_queries.cpu().numpy(),
            'correctly_classified': correct_classified_mask.cpu().numpy(),
            'success': list(success_mask.cpu().numpy()),
            "elapsed_budget": list(total_queries.cpu().numpy()),
        }
예제 #8
0
def make_adversarial_examples(image, true_label, args, model_to_fool,
                              IMAGENET_SL):
    '''
    The main process for generating adversarial examples with priors.
    '''
    # Initial setup
    prior_size = IMAGENET_SL if not args.tiling else args.tile_size
    upsampler = Upsample(size=(IMAGENET_SL, IMAGENET_SL))
    total_queries = ch.zeros(args.batch_size)
    prior = ch.zeros(args.batch_size, 3, prior_size, prior_size)
    dim = prior.nelement() / args.batch_size
    prior_step = gd_prior_step if args.mode == 'l2' else eg_step
    image_step = l2_image_step if args.mode == 'l2' else linf_step
    proj_maker = l2_proj if args.mode == 'l2' else linf_proj
    proj_step = proj_maker(image, args.epsilon)
    print(image.max(), image.min())

    # Loss function
    criterion = ch.nn.CrossEntropyLoss(reduction='none')

    def normalized_eval(x):
        x_copy = x.clone()
        x_copy = ch.stack([F.normalize(x_copy[i], [0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) \
                        for i in range(args.batch_size)])
        return model_to_fool(x_copy)

    L = lambda x: criterion(normalized_eval(x), true_label)
    losses = L(image)

    # Original classifications
    orig_images = image.clone()
    orig_classes = model_to_fool(image).argmax(1).cuda()
    correct_classified_mask = (orig_classes == true_label).float()
    total_ims = correct_classified_mask.sum()
    not_dones_mask = correct_classified_mask.clone()

    t = 0
    while not ch.any(total_queries > args.max_queries):
        t += args.gradient_iters * 2
        if t >= args.max_queries:
            break
        if not args.nes:
            ## Updating the prior:
            # Create noise for exporation, estimate the gradient, and take a PGD step
            exp_noise = args.exploration * ch.randn_like(prior) / (dim**0.5)
            # Query deltas for finite difference estimator
            q1 = upsampler(prior + exp_noise)
            q2 = upsampler(prior - exp_noise)
            # Loss points for finite difference estimator
            l1 = L(image + args.fd_eta * q1 / norm(q1))  # L(prior + c*noise)
            l2 = L(image + args.fd_eta * q2 / norm(q2))  # L(prior - c*noise)
            # Finite differences estimate of directional derivative
            est_deriv = (l1 - l2) / (args.fd_eta * args.exploration)
            # 2-query gradient estimate
            est_grad = est_deriv.view(-1, 1, 1, 1) * exp_noise
            # Update the prior with the estimated gradient
            prior = prior_step(prior, est_grad, args.online_lr)
        else:
            prior = ch.zeros_like(image)
            for _ in range(args.gradient_iters):
                exp_noise = ch.randn_like(image) / (dim**0.5)
                est_deriv = (L(image + args.fd_eta * exp_noise) -
                             L(image - args.fd_eta * exp_noise)) / args.fd_eta
                prior += est_deriv.view(-1, 1, 1, 1) * exp_noise

            # Preserve images that are already done,
            # Unless we are specifically measuring gradient estimation
            prior = prior * not_dones_mask.view(-1, 1, 1, 1)

        ## Update the image:
        # take a pgd step using the prior
        new_im = image_step(
            image,
            upsampler(prior * correct_classified_mask.view(-1, 1, 1, 1)),
            args.image_lr)
        image = proj_step(new_im)
        image = ch.clamp(image, 0, 1)
        if args.mode == 'l2':
            if not ch.all(norm(image - orig_images) <= args.epsilon + 1e-3):
                pdb.set_trace()
        else:
            if not (image - orig_images).max() <= args.epsilon + 1e-3:
                pdb.set_trace()

        ## Continue query count
        total_queries += 2 * args.gradient_iters * not_dones_mask
        not_dones_mask = not_dones_mask * (
            (normalized_eval(image).argmax(1) == true_label).float())

        ## Logging stuff
        new_losses = L(image)
        success_mask = (1 - not_dones_mask) * correct_classified_mask
        num_success = success_mask.sum()
        current_success_rate = (num_success /
                                correct_classified_mask.sum()).cpu().item()
        success_queries = ((success_mask * total_queries).sum() /
                           num_success).cpu().item()
        not_done_loss = ((new_losses * not_dones_mask).sum() /
                         not_dones_mask.sum()).cpu().item()
        max_curr_queries = total_queries.max().cpu().item()
        if args.log_progress:
            print("Queries: %d | Success rate: %f | Average queries: %f" %
                  (max_curr_queries, current_success_rate, success_queries))

        if current_success_rate == 1.0:
            break

    return {
        'average_queries': success_queries,
        'num_correctly_classified': correct_classified_mask.sum().cpu().item(),
        'success_rate': current_success_rate,
        'images_orig': orig_images.cpu().numpy(),
        'images_adv': image.cpu().numpy(),
        'all_queries': total_queries.cpu().numpy(),
        'correctly_classified': correct_classified_mask.cpu().numpy(),
        'success': success_mask.cpu().numpy()
    }
def make_adversarial_examples(image, true_label, args):
    '''
    The main process for generating adversarial examples with priors.
    '''
    # Initial setup
    prior_size = IMAGENET_SL if not args.tiling else args.tile_size
    upsampler = Upsample(size=(IMAGENET_SL, IMAGENET_SL))
    total_queries = ch.zeros(args.batch_size)
    prior = ch.zeros(args.batch_size, 3, prior_size, prior_size)
    dim = prior.nelement() / args.batch_size
    prior_step = gd_prior_step if args.mode == 'l2' else eg_step
    image_step = l2_image_step if args.mode == 'l2' else linf_step
    proj_maker = l2_proj if args.mode == 'l2' else linf_proj
    proj_step = proj_maker(image, args.epsilon)

    # Loss function
    criterion = ch.nn.CrossEntropyLoss(reduction='none')
    L = lambda x: criterion(model_to_fool(x), true_label)
    losses = L(image)

    # Original classifications
    orig_images = image.clone()
    orig_classes = model_to_fool(image).argmax(1).cuda()
    correct_classified_mask = (orig_classes == true_label).float()
    total_ims = correct_classified_mask.sum()
    not_dones_mask = correct_classified_mask.clone()

    while not ch.any(total_queries > args.max_queries):
        if not args.nes:
            ## Updating the prior:
            # Create noise for exporation, estimate the gradient, and take a PGD step
            exp_noise = args.exploration * ch.randn_like(prior) / (dim**0.5)
            # Query deltas for finite difference estimator
            q1 = upsampler(prior + exp_noise)
            q2 = upsampler(prior - exp_noise)
            # Loss points for finite difference estimator
            l1 = L(image + args.fd_eta * q1 / norm(q1))  # L(prior + c*noise)
            l2 = L(image + args.fd_eta * q2 / norm(q2))  # L(prior - c*noise)
            # Finite differences estimate of directional derivative
            est_deriv = (l1 - l2) / (args.fd_eta * args.exploration)
            # 2-query gradient estimate
            est_grad = est_deriv.view(-1, 1, 1, 1) * exp_noise
            # Update the prior with the estimated gradient
            prior = prior_step(prior, est_grad, args.online_lr)
        else:
            prior = ch.zeros_like(image)
            for _ in range(args.gradient_iters):
                exp_noise = ch.randn_like(image) / (dim**0.5)
                est_deriv = (L(image + args.fd_eta * exp_noise) -
                             L(image - args.fd_eta * exp_noise)) / args.fd_eta
                prior += est_deriv.view(-1, 1, 1, 1) * exp_noise

        # Preserve images that are already done
        prior = prior * not_dones_mask.view(-1, 1, 1, 1)

        ## Update the image:
        # take a pgd step using the prior
        new_im = image_step(image, upsampler(prior), args.image_lr)
        image = proj_step(new_im)
        image = ch.clamp(image, 0, 1)
        if args.mode == 'l2':
            if not ch.all(norm(image - orig_images) <= args.epsilon + 1e-3):
                raise ValueError("OOB")
        else:
            if not (image - orig_images).max() <= args.epsilon + 1e-3:
                raise ValueError("OOB")

        ## Continue query count
        not_dones_mask = not_dones_mask * (
            (model_to_fool(image).argmax(1) == true_label).float())
        total_queries += 2 * args.gradient_iters * not_dones_mask

        ## Logging stuff
        new_losses = L(image)
        success_mask = (1 - not_dones_mask) * correct_classified_mask
        num_success = success_mask.sum()
        current_success_rate = (num_success /
                                correct_classified_mask.sum()).cpu().item()
        success_queries = ((success_mask * total_queries).sum() /
                           num_success).cpu().item()
        not_done_loss = ((new_losses * not_dones_mask).sum() /
                         not_dones_mask.sum()).cpu().item()
        max_curr_queries = total_queries.max().cpu().item()
        if args.log_progress:
            print("Queries: %d | Success rate: %f | Average queries: %f" %
                  (max_curr_queries, current_success_rate, success_queries))
        if current_success_rate == 1.0:
            break

    # Return results
    return {
        'average_queries': success_queries,  # Average queries for this batch
        'num_correctly_classified': correct_classified_mask.sum().cpu().item(
        ),  # Number of originally correctly classified images
        'success_rate': current_success_rate,  # Success rate
        'images_orig': orig_images.cpu().numpy(),  # Original images
        'images_adv': image.cpu().numpy(),  # Adversarial images
        'all_queries':
        total_queries.cpu().numpy(),  # Number of queries used for each image
        'correctly_classified': correct_classified_mask.cpu().numpy(
        ),  # 0/1 mask for whether image was originally classified
        'success': success_mask.cpu().numpy(
        )  # 0/1 mask for whether the attack succeeds on each image
    }
예제 #10
0
def DFOattack(net,
              x,
              y,
              criterion=F.cross_entropy,
              eps=0.1,
              optimizer="DE",
              budget=10000,
              prior_size=5):

    x = x.cuda()
    upsampler = Upsample(size=(224, 224))
    s = prior_size

    def convert_individual_to_image(individual):
        perturbation = torch.from_numpy(eps * individual.astype(numpy.float32))
        perturbation = perturbation.view(1, 3, s, s)
        perturbation = upsampler(perturbation)
        perturbation = perturbation.cuda()
        x_adv = x + perturbation
        x_adv = torch.clamp(x_adv, 0, 1)
        return x_adv

    def loss(abc):
        if optimizer in ['cGA', 'PBIL']:
            individual = 2 * abc - 1
        else:
            abc = abc.reshape((-1, 2))
            abc = softmax(abc, axis=1)
            individual = 2 * (numpy.random.uniform(size=abc.shape[0]) <
                              abc[:, 0]) - 1
        x_adv = convert_individual_to_image(individual)

        netx_adv = net(x_adv)
        _, predicted = torch.max(netx_adv.data, 1)
        result = (-criterion(netx_adv, y)).detach().cpu().numpy()
        return result, predicted, x_adv

    # def loss(a):
    #     a=1/(1+numpy.exp(a))
    #     individual = 2*(numpy.random.uniform(size=a.shape)<a)-1
    #     x_adv = convert_individual_to_image(individual)
    #     netx_adv = net(x_adv)
    #     _,predicted = torch.max(netx_adv.data, 1)
    #     result = (-criterion(netx_adv,y)).detach().cpu().numpy()
    #     return result, predicted,x_adv

    done = False
    if optimizer in ['cGA', 'PBIL']:
        optimizerer = optimizerlib.registry[optimizer](instrumentation=s * s *
                                                       3,
                                                       budget=budget)
    else:
        optimizerer = optimizerlib.registry[optimizer](instrumentation=s * s *
                                                       3 * 2,
                                                       budget=budget)

    ebudget = 0
    for u in range(budget):
        if u % 100 == 0:
            print(u, "/", budget)

        curr_value = optimizerer.ask()
        values, predicted, x_adv = loss(numpy.array(curr_value.args[0]))
        ebudget += 1
        if predicted != y:
            # print(y,predicted)
            print('win', ebudget)
            done = True
            break
        optimizerer.tell(curr_value, float(values))

    return {
        "image_adv": x_adv.cpu().numpy(),
        "prediction": predicted,
        "elapsed_budget": ebudget,
        "success": done
    }
    def attack_all_images(self, args, arch, tmp_dump_path, result_dump_path):
        # subset_pos用于回调函数汇报汇总统计结果

        model = StandardModel(args.dataset, arch, no_grad=True)
        model.cuda()
        model.eval()
        # 带有缩减功能的,攻击成功的图片自动删除掉
        for data_idx, data_tuple in enumerate(self.dataset_loader):
            if os.path.exists(tmp_dump_path):
                with open(tmp_dump_path, "r") as file_obj:
                    json_content = json.load(file_obj)
                    resume_batch_idx = int(json_content["batch_idx"])  # resume
                    for key in [
                            'query_all', 'correct_all', 'not_done_all',
                            'success_all', 'success_query_all'
                    ]:
                        if key in json_content:
                            setattr(
                                self, key,
                                torch.from_numpy(np.asarray(
                                    json_content[key])).float())
                    if data_idx < resume_batch_idx:  # resume
                        continue

            if args.dataset == "ImageNet":
                if model.input_size[-1] >= 299:
                    images, true_labels = data_tuple[1], data_tuple[2]
                else:
                    images, true_labels = data_tuple[0], data_tuple[2]
            else:
                images, true_labels = data_tuple[0], data_tuple[1]
            if images.size(-1) != model.input_size[-1]:
                images = F.interpolate(images,
                                       size=model.input_size[-1],
                                       mode='bilinear',
                                       align_corners=True)
            # skip_batch_index_list = np.nonzero(np.asarray(chunk_skip_indexes[data_idx]))[0].tolist()
            selected = torch.arange(
                data_idx * args.batch_size,
                min((data_idx + 1) * args.batch_size,
                    self.total_images))  # 选择这个batch的所有图片的index
            img_idx_to_batch_idx = ImageIdxToOrigBatchIdx(args.batch_size)
            images, true_labels = images.cuda(), true_labels.cuda()
            first_finetune = True
            finetune_queue = FinetuneQueue(args.batch_size, args.meta_seq_len,
                                           img_idx_to_batch_idx)
            prior_size = model.input_size[
                -1] if not args.tiling else args.tile_size
            assert args.tiling == (args.dataset == "ImageNet")
            if args.tiling:
                upsampler = Upsample(size=(model.input_size[-2],
                                           model.input_size[-1]))
            else:
                upsampler = lambda x: x
            with torch.no_grad():
                logit = model(images)
            pred = logit.argmax(dim=1)
            query = torch.zeros(images.size(0)).cuda()
            correct = pred.eq(true_labels).float()  # shape = (batch_size,)
            not_done = correct.clone()  # shape = (batch_size,)

            if args.targeted:
                if args.target_type == 'random':
                    target_labels = torch.randint(
                        low=0,
                        high=CLASS_NUM[args.dataset],
                        size=true_labels.size()).long().cuda()
                    invalid_target_index = target_labels.eq(true_labels)
                    while invalid_target_index.sum().item() > 0:
                        target_labels[invalid_target_index] = torch.randint(
                            low=0,
                            high=logit.shape[1],
                            size=target_labels[invalid_target_index].shape
                        ).long().cuda()
                        invalid_target_index = target_labels.eq(true_labels)
                elif args.target_type == 'least_likely':
                    target_labels = logit.argmin(dim=1)
                elif args.target_type == "increment":
                    target_labels = torch.fmod(true_labels + 1,
                                               CLASS_NUM[args.dataset])
                else:
                    raise NotImplementedError('Unknown target_type: {}'.format(
                        args.target_type))
            else:
                target_labels = None
            prior = torch.zeros(images.size(0), IN_CHANNELS[args.dataset],
                                prior_size, prior_size).cuda()
            prior_step = self.gd_prior_step if args.norm == 'l2' else self.eg_prior_step
            image_step = self.l2_image_step if args.norm == 'l2' else self.linf_step
            proj_step = self.l2_proj_step if args.norm == 'l2' else self.linf_proj_step  # 调用proj_maker返回的是一个函数
            criterion = self.cw_loss if args.data_loss == "cw" else self.xent_loss
            adv_images = images.clone()
            for step_index in range(1, args.max_queries + 1):
                # Create noise for exporation, estimate the gradient, and take a PGD step
                dim = prior.nelement() / images.size(
                    0)  # nelement() --> total number of elements
                exp_noise = args.exploration * torch.randn_like(prior) / (
                    dim**0.5
                )  # parameterizes the exploration to be done around the prior
                exp_noise = exp_noise.cuda()
                q1 = upsampler(
                    prior + exp_noise
                )  # 这就是Finite Difference算法, prior相当于论文里的v,这个prior也会更新,把梯度累积上去
                q2 = upsampler(
                    prior -
                    exp_noise)  # prior 相当于累积的更新量,用这个更新量,再去修改image,就会变得非常准
                # Loss points for finite difference estimator
                q1_images = adv_images + args.fd_eta * q1 / self.norm(q1)
                q2_images = adv_images + args.fd_eta * q2 / self.norm(q2)
                predict_by_target_model = False
                if (step_index <= args.warm_up_steps or
                    (step_index - args.warm_up_steps) % args.meta_predict_steps
                        == 0):
                    log.info("predict from target model")
                    predict_by_target_model = True
                    with torch.no_grad():
                        q1_logits = model(q1_images)
                        q2_logits = model(q2_images)
                        q1_logits = q1_logits / torch.norm(
                            q1_logits, p=2, dim=-1,
                            keepdim=True)  # 加入normalize
                        q2_logits = q2_logits / torch.norm(
                            q2_logits, p=2, dim=-1, keepdim=True)

                    finetune_queue.append(q1_images.detach(),
                                          q2_images.detach(),
                                          q1_logits.detach(),
                                          q2_logits.detach())

                    if step_index >= args.warm_up_steps:
                        q1_images_seq, q2_images_seq, q1_logits_seq, q2_logits_seq = finetune_queue.stack_history_track(
                        )
                        finetune_times = args.finetune_times if first_finetune else random.randint(
                            3, 5)  # FIXME
                        log.info("begin finetune for {} times".format(
                            finetune_times))
                        self.meta_finetuner.finetune(
                            q1_images_seq, q2_images_seq, q1_logits_seq,
                            q2_logits_seq, finetune_times, first_finetune,
                            img_idx_to_batch_idx)
                        first_finetune = False
                else:
                    with torch.no_grad():
                        q1_logits, q2_logits = self.meta_finetuner.predict(
                            q1_images, q2_images, img_idx_to_batch_idx)
                        q1_logits = q1_logits / torch.norm(
                            q1_logits, p=2, dim=-1, keepdim=True)
                        q2_logits = q2_logits / torch.norm(
                            q2_logits, p=2, dim=-1, keepdim=True)

                l1 = criterion(q1_logits, true_labels, target_labels)
                l2 = criterion(q2_logits, true_labels, target_labels)
                # Finite differences estimate of directional derivative
                est_deriv = (l1 - l2) / (args.fd_eta * args.exploration
                                         )  # 方向导数 , l1和l2是loss
                # 2-query gradient estimate
                est_grad = est_deriv.view(-1, 1, 1,
                                          1) * exp_noise  # B, C, H, W,
                # Update the prior with the estimated gradient
                prior = prior_step(
                    prior, est_grad,
                    args.online_lr)  # 注意,修正的是prior,这就是bandit算法的精髓
                grad = upsampler(prior)  # prior相当于梯度
                ## Update the image:
                adv_images = image_step(
                    adv_images,
                    grad * correct.view(-1, 1, 1, 1),  # 注意correct也是删减过的
                    args.image_lr)  # prior放大后相当于累积的更新量,可以用来更新
                adv_images = proj_step(images, args.epsilon, adv_images)
                adv_images = torch.clamp(adv_images, 0, 1)

                with torch.no_grad():
                    adv_logit = model(adv_images)  #
                adv_pred = adv_logit.argmax(dim=1)
                adv_prob = F.softmax(adv_logit, dim=1)
                adv_loss = criterion(adv_logit, true_labels, target_labels)
                ## Continue query count
                if predict_by_target_model:
                    query = query + 2 * not_done
                if args.targeted:
                    not_done = not_done * (
                        1 - adv_pred.eq(target_labels).float()
                    ).float()  # not_done初始化为 correct, shape = (batch_size,)
                else:
                    not_done = not_done * adv_pred.eq(
                        true_labels).float()  # 只要是跟原始label相等的,就还需要query,还没有成功
                success = (1 - not_done) * correct
                success_query = success * query
                not_done_loss = adv_loss * not_done
                not_done_prob = adv_prob[torch.arange(adv_images.size(0)),
                                         true_labels] * not_done

                log.info('Attacking image {} - {} / {}, step {}'.format(
                    data_idx * args.batch_size,
                    (data_idx + 1) * args.batch_size, self.total_images,
                    step_index))
                log.info('       not_done: {:.4f}'.format(
                    len(
                        np.where(not_done.detach().cpu().numpy().astype(
                            np.int32) == 1)[0]) / float(args.batch_size)))
                log.info('      fd_scalar: {:.9f}'.format(
                    (l1 - l2).mean().item()))
                if success.sum().item() > 0:
                    log.info('     mean_query: {:.4f}'.format(
                        success_query[success.byte()].mean().item()))
                    log.info('   median_query: {:.4f}'.format(
                        success_query[success.byte()].median().item()))
                if not_done.sum().item() > 0:
                    log.info('  not_done_loss: {:.4f}'.format(
                        not_done_loss[not_done.byte()].mean().item()))
                    log.info('  not_done_prob: {:.4f}'.format(
                        not_done_prob[not_done.byte()].mean().item()))

                not_done_np = not_done.detach().cpu().numpy().astype(np.int32)
                done_img_idx_list = np.where(not_done_np == 0)[0].tolist()
                delete_all = False
                if done_img_idx_list:
                    for skip_index in done_img_idx_list:  # 两次循环,第一次循环先汇报出去,第二次循环删除
                        batch_idx = img_idx_to_batch_idx[skip_index]
                        pos = selected[batch_idx].item()
                        # 先汇报被删减的值self.query_all
                        for key in [
                                'query', 'correct', 'not_done', 'success',
                                'success_query', 'not_done_loss',
                                'not_done_prob'
                        ]:
                            value_all = getattr(self, key + "_all")
                            value = eval(key)[skip_index].item()
                            value_all[pos] = value

                    images, adv_images, prior, query, true_labels, target_labels, correct, not_done = \
                        self.delete_tensor_by_index_list(done_img_idx_list, images, adv_images, prior, query,
                                                         true_labels, target_labels, correct, not_done)
                    img_idx_to_batch_idx.del_by_index_list(done_img_idx_list)
                    delete_all = images is None

                if delete_all:
                    break

            # report to all stats the rest unsuccess
            for key in [
                    'query', 'correct', 'not_done', 'success', 'success_query',
                    'not_done_loss', 'not_done_prob'
            ]:
                for img_idx, batch_idx in img_idx_to_batch_idx.proj_dict.items(
                ):
                    pos = selected[batch_idx].item()
                    value_all = getattr(self, key + "_all")
                    value = eval(key)[img_idx].item()
                    value_all[
                        pos] = value  # 由于value_all是全部图片都放在一个数组里,当前batch选择出来
            img_idx_to_batch_idx.proj_dict.clear()

            tmp_info_dict = {
                "batch_idx": data_idx + 1,
                "batch_size": args.batch_size
            }
            for key in [
                    'query_all', 'correct_all', 'not_done_all', 'success_all',
                    'success_query_all'
            ]:
                value_all = getattr(self, key).detach().cpu().numpy().tolist()
                tmp_info_dict[key] = value_all
            with open(tmp_dump_path, "w") as result_file_obj:
                json.dump(tmp_info_dict, result_file_obj, sort_keys=True)

        log.info('Saving results to {}'.format(result_dump_path))
        meta_info_dict = {
            "avg_correct":
            self.correct_all.mean().item(),
            "avg_not_done":
            self.not_done_all[self.correct_all.byte()].mean().item(),
            "mean_query":
            self.success_query_all[self.success_all.byte()].mean().item(),
            "median_query":
            self.success_query_all[self.success_all.byte()].median().item(),
            "max_query":
            self.success_query_all[self.success_all.byte()].max().item(),
            "correct_all":
            self.correct_all.detach().cpu().numpy().astype(np.int32).tolist(),
            "not_done_all":
            self.not_done_all.detach().cpu().numpy().astype(np.int32).tolist(),
            "query_all":
            self.query_all.detach().cpu().numpy().astype(np.int32).tolist(),
            "not_done_loss":
            self.not_done_loss_all[self.not_done_all.byte()].mean().item(),
            "not_done_prob":
            self.not_done_prob_all[self.not_done_all.byte()].mean().item(),
            "args":
            vars(args)
        }
        with open(result_dump_path, "w") as result_file_obj:
            json.dump(meta_info_dict, result_file_obj, sort_keys=True)
        log.info("done, write stats info to {}".format(result_dump_path))
        self.query_all.fill_(0)
        self.correct_all.fill_(0)
        self.not_done_all.fill_(0)
        self.success_all.fill_(0)
        self.success_query_all.fill_(0)
        self.not_done_loss_all.fill_(0)
        self.not_done_prob_all.fill_(0)
        model.cpu()
예제 #12
0
    def __init__(self, num_classes, gr=32, resnet_backbone='ResNet50', dense_config='normal', pretrained=True):
        super(SaliencyMapNet, self).__init__()

        self.num_classes = num_classes
        self.resnet_backbone = resnet_backbone
        self.gr = gr
        if resnet_backbone == 'ResNet18':
            layers = [2, 2, 2, 2]
        elif resnet_backbone =='ResNet50':
            layers = [3, 4, 6, 3]
        else:
            print('given Resnet backbone does not exist')

        if dense_config == 'normal':
            block_config = [6, 12, 24, 16]

        self.pretrained = pretrained

        self.pretrained_resnet = resnet50(pretrained=self.pretrained)
        self._modify_resnet(num_classes)

        # added resnet Block to downsample to 8x 8
        # todo: fix the last layer so that it only downsamples once. done in _modifyresnet
        # too many weights in last layer, reduce planes, and use more blacks.
        # self.layer5 = self._make_layer(inplanes=2048, block=resnet.Bottleneck, planes=1024, blocks=1, stride=2,
        #                                dilate=False)

        ## normal pretrainable resnet:

        # model prior to Unet shape:

        self.d1 = DenseNet(growth_rate=self.gr, block_config=6,
                           num_init_features=256, num_output=256)

        self.d2 = DenseNet(growth_rate=self.gr, block_config=12,
                           num_init_features=512, num_output=512)

        self.d3 = DenseNet(growth_rate=self.gr, block_config=24,
                           num_init_features=1024, num_output=1024)

        # self.d4 = DenseNet(growth_rate=self.gr, block_config=12,
        #                    num_init_features=2048, num_output=2048)


        # upwards path
        # self.upsample0 = Upsample(scale_factor=2, mode='nearest')
        # # self.upsample1 = MyUpsampler(num_init_features =8*self.num_classes, num_out_features=4*self.num_classes) # from [bs, 8k, 8, 8] --> [bs, 4k, 16, 16]
        #
        # self.updense0 = DenseNet(growth_rate=self.gr, block_config=12,
        #                          num_init_features=4096+2048,
        #                          num_output=2048)
        # self.mixdense0 = DenseNet(growth_rate=self.gr, block_config=12,
        #                           num_init_features=2048, num_output=2048)
        self.upsample = Upsample(scale_factor=2, mode='bilinear', align_corners=True)
        # self.upsample1 = MyUpsampler(num_init_features =8*self.num_classes, num_out_features=4*self.num_classes) # from [bs, 8k, 8, 8] --> [bs, 4k, 16, 16]

        self.updense1 = DenseNet(growth_rate=self.gr, block_config=2,
                                 num_init_features=2048+1024,
                                 num_output=1024)
        self.mixdense1 = DenseNet(growth_rate=self.gr, block_config=2,
                                  num_init_features=1024, num_output=1024)

        self.updense2 = DenseNet(growth_rate=self.gr, block_config=2,
                                 num_init_features=1024+512,
                                 num_output=512)
        self.mixdense2 = DenseNet(growth_rate=self.gr, block_config=2,
                                  num_init_features=512, num_output=512)

        self.updense3 = DenseNet(growth_rate=self.gr, block_config=2,
                                 num_init_features=512+256,
                                 num_output=256)
        self.mixdense3 = DenseNet(growth_rate=self.gr, block_config=2,
                                  num_init_features=256, num_output=256)

        self.onexone = torch.nn.Conv2d(in_channels=256, out_channels=self.num_classes, kernel_size=1)

        # use a softmax if dataset is mutually exclusive.
        self.sigmoid = nn.Sigmoid()
        # self.softmax = nn.Softmax(dim=1)

        self.pooling = CustomPooling(beta=1, r_0=10, dim=(-1, -2), mode=None)

        self.norm = CustomNorm(1)
예제 #13
0
    def __init__(self, args, nor_type = 'sp', img_size=256,recursive_num=4,fusion_strategy = 0, upsample_strategy = 0 ,res_par_tag = False, depthwise_tag = False, att_tag = True):
        super(DenseMODEL, self).__init__()
        # hyper-params
        self.args = args
        self.res_par_tag = res_par_tag
        self.lstm_tags = True

        self.fusion_strategy = fusion_strategy
        self.upsample_strategy = upsample_strategy


        self.recursive_num = recursive_num
        self.img_size = img_size

        if res_par_tag:
            self.res_scale = nn.Parameter(torch.ones(1))
        else :
            self.res_scale = 1

        scale = args.upscale_factor
        n_resblocks = args.n_resblocks
        n_feats = args.n_feats
        # n_feats = 64
        kernel_size = 3
        act = nn.ReLU(True)
        
        if nor_type == 'sp':
            wn = SpectralNorm
        elif nor_type == 'wn':
            wn = lambda x: torch.nn.utils.weight_norm(x)
        elif nor_type == 'none':
            wn = lambda x: x
        
        if args.n_colors == 3:
            self.rgb_mean = nn.Parameter(torch.FloatTensor([args.r_mean, args.g_mean, args.b_mean])).view([1, 3, 1, 1]).cuda()
        else:
            self.rgb_mean = nn.Parameter(torch.FloatTensor([args.r_mean])).view([1, 1, 1, 1]).cuda()

        # define head module
        head = []
        # head.append(wn(nn.Conv2d(args.n_colors, n_feats, 3, padding=3//2)))
        head.append(wn(nn.Conv2d(args.n_colors, n_feats, 3, padding=3//2)))

        # define body module
        body = []
        for i in range(n_resblocks):
            body.append(
                Block(n_feats, kernel_size, act=act, res_scale=args.res_scale, wn=wn, res_par=res_par_tag, depthwise_tag=depthwise_tag))

        # define LSTM
        height = self.img_size//scale
        width = self.img_size//scale
        self.converge = BiConvLSTM(input_size=(height, width),
                 input_dim=n_feats,
                 hidden_dim=[ n_feats//2, n_feats//2],
                 kernel_size=(1, 1),
                 num_layers=2,
                 bias=True,
                 return_all_layers=False, return_fl = False)



        # define tail module
        tail = []
        out_feats = scale*scale*args.n_colors
        if self.fusion_strategy == 2:
            tail.append(
                wn(nn.Conv2d(n_feats*self.recursive_num, out_feats, 1)))
        elif self.fusion_strategy == 0:
            tail.append(
                wn(nn.Conv2d(self.recursive_num*n_feats//2, out_feats, 1)))
        else:
            tail.append(
                wn(nn.Conv2d(n_feats, out_feats, 1)))

        tail.append(nn.PixelShuffle(scale))
        self.tail = nn.Sequential(*tail)



        # make object members
        self.head = nn.Sequential(*head)
        # self.body = nn.Sequential(*body)

        self.body1 = DenseBlock(n_feats, kernel_size, act=act, res_scale=args.res_scale, wn=wn, res_par=res_par_tag, depthwise_tag=depthwise_tag).cuda()
        # self.body1 = Block(n_feats, kernel_size, act=act, res_scale=args.res_scale, wn=wn, res_par=res_par_tag, depthwise_tag=depthwise_tag).cuda()
        # self.body2 = DenseBlock(n_feats, kernel_size, act=act, res_scale=args.res_scale, wn=wn, res_par=res_par_tag, depthwise_tag=depthwise_tag).cuda()
        # self.body3 = DenseBlock(n_feats, kernel_size, act=act, res_scale=args.res_scale, wn=wn, res_par=res_par_tag, depthwise_tag=depthwise_tag).cuda()
        # self.body4 = DenseBlock(n_feats, kernel_size, act=act, res_scale=args.res_scale, wn=wn, res_par=res_par_tag, depthwise_tag=depthwise_tag).cuda()

        # self.skip = nn.Sequential(*skip)
        skip = []
        skip.append(
            wn(nn.Conv2d(args.n_colors, out_feats, 5, padding=5//2))
        )
        skip.append(nn.PixelShuffle(scale))

        if self.upsample_strategy == 0:
            self.skip = Upsample(scale_factor=scale)
        elif self.upsample_strategy == 1:
            self.skip = nn.Sequential(*skip)

        self.att_tag = att_tag
    def make_adversarial_examples(cls, image, true_label, target_label, args,
                                  attack_norm, model_to_fool):
        '''
        The attack process for generating adversarial examples with priors.
        '''
        # Initial setup
        orig_images = image.clone()
        prior_size = IMAGE_SIZE[
            args.dataset][0] if not args.tiling else args.tile_size
        assert args.tiling == (args.dataset == "ImageNet")
        if args.tiling:
            upsampler = Upsample(size=(IMAGE_SIZE[args.dataset][0],
                                       IMAGE_SIZE[args.dataset][1]))
        else:
            upsampler = lambda x: x
        total_queries = torch.zeros(args.batch_size).cuda()
        prior = torch.zeros(args.batch_size, IN_CHANNELS[args.dataset],
                            prior_size, prior_size).cuda()
        dim = prior.nelement(
        ) / args.batch_size  # nelement() --> total number of elements
        prior_step = BanditAttack.gd_prior_step if attack_norm == 'l2' else BanditAttack.eg_step
        image_step = BanditAttack.l2_image_step if attack_norm == 'l2' else BanditAttack.linf_step
        proj_maker = BanditAttack.l2_proj if attack_norm == 'l2' else BanditAttack.linf_proj  # 调用proj_maker返回的是一个函数
        proj_step = proj_maker(orig_images, args.epsilon)
        # Loss function
        criterion = BanditAttack.cw_loss if args.loss == "cw" else BanditAttack.xent_loss
        # Original classifications
        orig_classes = model_to_fool(image).argmax(1).cuda()
        correct_classified_mask = (orig_classes == true_label).float()
        not_dones_mask = correct_classified_mask.clone()  # 分类分对的mask
        log.info("correct ratio : {:.3f}".format(
            correct_classified_mask.mean()))
        normalized_q1 = deque(maxlen=100)
        normalized_q2 = deque(maxlen=100)
        images = deque(maxlen=100)
        logits_q1_list = deque(maxlen=100)
        logits_q2_list = deque(maxlen=100)

        # 有选择的选择一个段落,比如说从中间开始截取一个段落
        assert args.max_queries // 2 >= 100
        slice_iteration_end = random.randint(100, args.max_queries // 2)
        for i in range(slice_iteration_end):
            if not args.nes:
                ## Updating the prior:
                # Create noise for exporation, estimate the gradient, and take a PGD step
                exp_noise = args.exploration * torch.randn_like(prior) / (
                    dim**0.5
                )  # parameterizes the exploration to be done around the prior
                exp_noise = exp_noise.cuda()
                # Query deltas for finite difference estimator
                q1 = upsampler(
                    prior + exp_noise
                )  # 这就是Finite Difference算法, prior相当于论文里的v,这个prior也会更新,把梯度累积上去
                q2 = upsampler(
                    prior -
                    exp_noise)  # prior 相当于累积的更新量,用这个更新量,再去修改image,就会变得非常准
                # Loss points for finite difference estimator
                logits_q1 = model_to_fool(image + args.fd_eta * q1 /
                                          BanditAttack.norm(q1))
                logits_q2 = model_to_fool(image + args.fd_eta * q2 /
                                          BanditAttack.norm(q2))
                l1 = criterion(logits_q1, true_label, target_label)
                l2 = criterion(logits_q2, true_label, target_label)
                if i >= slice_iteration_end - 100:
                    images.append(image.detach().cpu().numpy())
                    normalized_q1.append(
                        (args.fd_eta * q1 /
                         BanditAttack.norm(q1)).detach().cpu().numpy())
                    normalized_q2.append(
                        (args.fd_eta * q2 /
                         BanditAttack.norm(q2)).detach().cpu().numpy())
                    logits_q1_list.append(logits_q1.detach().cpu().numpy())
                    logits_q2_list.append(logits_q2.detach().cpu().numpy())

                # Finite differences estimate of directional derivative
                est_deriv = (l1 - l2) / (args.fd_eta * args.exploration
                                         )  # 方向导数 , l1和l2是loss
                # 2-query gradient estimate
                est_grad = est_deriv.view(-1, 1, 1,
                                          1) * exp_noise  # B, C, H, W,
                # Update the prior with the estimated gradient
                prior = prior_step(
                    prior, est_grad,
                    args.online_lr)  # 注意,修正的是prior,这就是bandit算法的精髓
            else:  # NES方法
                prior = torch.zeros_like(image).cuda()
                for grad_iter_t in range(args.gradient_iters):
                    exp_noise = torch.randn_like(image) / (dim**0.5)
                    logits_q1 = model_to_fool(image + args.fd_eta * exp_noise)
                    logits_q2 = model_to_fool(image - args.fd_eta * exp_noise)
                    l1 = criterion(logits_q1, true_label, target_label)
                    l2 = criterion(logits_q2, true_label, target_label)
                    est_deriv = (l1 - l2) / args.fd_eta
                    prior += est_deriv.view(-1, 1, 1, 1) * exp_noise
                    if i * args.gradient_iters + grad_iter_t >= slice_iteration_end - 100:
                        images.append(image.detach().cpu().numpy())
                        normalized_q1.append(
                            (args.fd_eta * exp_noise).detach().cpu().numpy())
                        normalized_q2.append(
                            (-args.fd_eta * exp_noise).detach().cpu().numpy())
                        logits_q1_list.append(logits_q1.detach().cpu().numpy())
                        logits_q2_list.append(logits_q2.detach().cpu().numpy())
                # Preserve images that are already done,
                # Unless we are specifically measuring gradient estimation
                prior = prior * not_dones_mask.view(-1, 1, 1, 1).cuda()

            ## Update the image:
            # take a pgd step using the prior
            new_im = image_step(
                image,
                upsampler(prior * correct_classified_mask.view(-1, 1, 1, 1)),
                args.image_lr)  # prior放大后相当于累积的更新量,可以用来更新
            image = proj_step(new_im)
            image = torch.clamp(image, 0, 1)

            ## Continue query count
            total_queries += 2 * args.gradient_iters * not_dones_mask  # gradient_iters是一个int值
            with torch.no_grad():
                adv_pred = model_to_fool(image).argmax(1)
            if args.targeted:
                not_dones_mask = not_dones_mask * (
                    1 - adv_pred.eq(target_label).float()
                ).float()  # not_done初始化为 correct, shape = (batch_size,)
            else:
                not_dones_mask = not_dones_mask * adv_pred.eq(
                    true_label).float()  # 只要是跟原始label相等的,就还需要query,还没有成功

            ## Logging stuff
            success_mask = (1 - not_dones_mask) * correct_classified_mask
            num_success = success_mask.sum()
            current_success_rate = (
                num_success.detach().cpu() /
                correct_classified_mask.detach().cpu().sum()).cpu().item()
            if num_success == 0:
                success_queries = 0
            else:
                success_queries = ((success_mask * total_queries).sum() /
                                   num_success).cpu().item()
            max_curr_queries = total_queries.max().cpu().item()
            # log.info("%d-th: Queries: %d | Success rate: %f | Average queries: %f" % (i, max_curr_queries, current_success_rate, success_queries))
            # if current_success_rate == 1.0:
            #     break

        normalized_q1 = np.ascontiguousarray(
            np.transpose(np.stack(list(normalized_q1)), axes=(1, 0, 2, 3, 4)))
        normalized_q2 = np.ascontiguousarray(
            np.transpose(np.stack(list(normalized_q2)), axes=(1, 0, 2, 3, 4)))
        images = np.ascontiguousarray(
            np.transpose(np.stack(list(images)), axes=(1, 0, 2, 3, 4)))
        logits_q1_list = np.ascontiguousarray(
            np.transpose(np.stack(list(logits_q1_list)),
                         axes=(1, 0, 2)))  # B,T,#class
        logits_q2_list = np.ascontiguousarray(
            np.transpose(np.stack(list(logits_q2_list)),
                         axes=(1, 0, 2)))  # B,T,#class

        return {
            'average_queries': success_queries,
            'num_correctly_classified':
            correct_classified_mask.sum().cpu().item(),
            'success_rate': current_success_rate,
            'images_orig': orig_images.cpu().numpy(),
            'images_adv': image.cpu().numpy(),
            'all_queries': total_queries.cpu().numpy(),
            'correctly_classified': correct_classified_mask.cpu().numpy(),
            'success': success_mask.cpu().numpy(),
            "q1": normalized_q1,
            "q2": normalized_q2,
            "images": images,
            "logits_q1": logits_q1_list,
            "logits_q2": logits_q2_list
        }
예제 #15
0
def make_adversarial_examples(image, true_label, args):
    '''
    The main process for generating adversarial examples with priors.
    '''

    # added. initialize adam
    adam_step = 1
    adam_first = ch.zeros_like(image)
    adam_second = ch.zeros_like(image)
    beta1, beta2 = 0.9, 0.999

    # initialize image lr
    image_lr = args.image_lr * np.ones_like(true_label.cpu().numpy())
    image_lr_ch = ch.from_numpy(image_lr).view(-1, 1, 1,
                                               1).type(ch.FloatTensor).cuda()
    last_losses = []
    plateau_length = args.plateau_length
    min_lr = args.image_lr / args.min_ratio

    # Initial setup
    batch_size = list(image.size())[0]
    prior_size = IMAGENET_SL if not args.tiling else args.tile_size
    print("prior size:", prior_size)
    upsampler = Upsample(size=(IMAGENET_SL, IMAGENET_SL))
    total_queries = ch.zeros(batch_size)
    prior = ch.zeros(batch_size, 3, prior_size, prior_size)
    dim = prior.nelement() / batch_size
    prior_step = gd_prior_step if args.mode == 'l2' else eg_step
    image_step = l2_image_step if args.mode == 'l2' else linf_step
    proj_maker = l2_proj if args.mode == 'l2' else linf_proj
    proj_step = proj_maker(image, args.epsilon)

    # Loss function
    criterion = ch.nn.CrossEntropyLoss(reduction='none')
    L = lambda x: criterion(model_to_fool(batch_norm(x)), true_label)

    losses = L(image)

    # Original classifications
    orig_images = image.clone()
    orig_classes = model_to_fool(batch_norm(image)).argmax(1).cuda()
    if args.targeted:
        correct_classified_mask = (orig_classes != true_label).float()
    else:
        correct_classified_mask = (orig_classes == true_label).float()
    total_ims = correct_classified_mask.sum()
    print('initially correct images:', total_ims.cpu().numpy())
    not_dones_mask = correct_classified_mask.clone()

    if args.targeted:
        max_queries = 100000
    else:
        max_queries = args.max_queries
    while not ch.any(total_queries > max_queries):
        if not args.nes:
            ## Updating the prior:
            # Create noise for exporation, estimate the gradient, and take a PGD step
            exp_noise = args.exploration * ch.randn_like(prior) / (dim**0.5)
            # Query deltas for finite difference estimator
            q1 = upsampler(prior + exp_noise)
            q2 = upsampler(prior - exp_noise)
            # Loss points for finite difference estimator
            l1 = L(image + args.fd_eta * q1 / norm(q1))  # L(prior + c*noise)
            l2 = L(image + args.fd_eta * q2 / norm(q2))  # L(prior - c*noise)
            # Finite differences estimate of directional derivative
            est_deriv = (l1 - l2) / (args.fd_eta * args.exploration)
            # 2-query gradient estimate
            est_grad = est_deriv.view(-1, 1, 1, 1) * exp_noise
            # Update the prior with the estimated gradient
            prior = prior_step(prior, est_grad, args.online_lr)

        else:
            prior = ch.zeros_like(image)
            for _ in range(args.gradient_iters):
                exp_noise = ch.randn_like(image) / (dim**0.5)
                est_deriv = (L(image + args.fd_eta * exp_noise) -
                             L(image - args.fd_eta * exp_noise)) / args.fd_eta
                prior += est_deriv.view(-1, 1, 1, 1) * exp_noise

        # Preserve images that are already done
        prior = prior * not_dones_mask.view(-1, 1, 1, 1)

        ## Update the image:
        # take a pgd step using the prior

        # added. adam update
        if args.adam:
            g = upsampler(prior)
            adam_first = beta1 * adam_first + (1 - beta1) * g
            adam_second = beta2 * adam_second + (1 - beta2) * g * g
            first_unbias = adam_first / (1 - beta1**adam_step)
            second_unbias = adam_second / (1 - beta2**adam_step)
            adam_step += 1
            if args.targeted:
                new_im = image - image_lr_ch * ch.sign(
                    first_unbias / (ch.sqrt(second_unbias) + 1e-7))
            else:
                new_im = image + image_lr_ch * ch.sign(
                    first_unbias / (ch.sqrt(second_unbias) + 1e-7))
        else:
            new_im = image_step(image, upsampler(prior), image_lr_ch)

        image = proj_step(new_im)
        image = ch.clamp(image, 0, 1)
        if args.mode == 'l2':
            if not ch.all(norm(image - orig_images) <= args.epsilon + 1e-3):
                raise ValueError("OOB")
        else:
            if not (image - orig_images).max() <= args.epsilon + 1e-3:
                raise ValueError("OOB")

        ## Continue query count (modified)
        total_queries += 2 * args.gradient_iters * not_dones_mask
        if args.targeted:
            not_dones_mask = not_dones_mask * ((model_to_fool(
                batch_norm(image)).argmax(1) != true_label).float())
        else:
            not_dones_mask = not_dones_mask * ((model_to_fool(
                batch_norm(image)).argmax(1) == true_label).float())

        ## Logging stuff
        new_losses = L(image)
        success_mask = (1 - not_dones_mask) * correct_classified_mask
        num_success = success_mask.sum()
        current_success_rate = (num_success /
                                correct_classified_mask.sum()).cpu().item()
        success_queries = ((success_mask * total_queries).sum() /
                           num_success).cpu().item()
        not_done_loss = ((new_losses * not_dones_mask).sum() /
                         not_dones_mask.sum()).cpu().item()
        max_curr_queries = total_queries.max().cpu().item()
        if args.log_progress and max_curr_queries % 100 == 0:
            print("Queries: %d | Success rate: %f | Average queries: %f" %
                  (max_curr_queries, current_success_rate, success_queries))
            #print("curr loss:", np.mean(new_losses.cpu().numpy()))
        if current_success_rate == 1.0:
            break

        # learning rate decay
        if args.decay:
            last_losses.append(new_losses.cpu().numpy())
            last_losses = last_losses[-plateau_length:]
            if len(last_losses) == plateau_length:
                if args.targeted:
                    image_lr = np.where(
                        last_losses[-1] < last_losses[0],
                        np.maximum(image_lr / args.plateau_drop, min_lr),
                        image_lr)
                else:
                    image_lr = np.where(
                        last_losses[-1] > last_losses[0],
                        np.maximum(image_lr / args.plateau_drop, min_lr),
                        image_lr)

    # Return results
    return {
        'average_queries': success_queries,  # Average queries for this batch
        'num_correctly_classified': correct_classified_mask.sum().cpu().item(
        ),  # Number of originally correctly classified images
        'success_rate': current_success_rate,  # Success rate
        'images_orig': orig_images.cpu().numpy(),  # Original images
        'images_adv': image.cpu().numpy(),  # Adversarial images
        'all_queries':
        total_queries.cpu().numpy(),  # Number of queries used for each image
        'correctly_classified': correct_classified_mask.cpu().numpy(
        ),  # 0/1 mask for whether image was originally classified
        'success': success_mask.cpu().numpy(
        ),  # 0/1 mask for whether the attack succeeds on each image
    }
예제 #16
0
def make_adversarial_examples(image,
                              true_label,
                              model_to_fool,
                              nes=True,
                              mode="linf",
                              epsilon=0.04,
                              max_queries=10000,
                              gradient_iters=50,
                              fd_eta=0.05,
                              image_lr=0.0001,
                              online_lr=100,
                              exploration=1,
                              prior_size=50,
                              log_progress=True):
    '''
    The main process for generating adversarial examples with priors.
    '''
    # Initial setup
    batch_size = image.size(0)
    total_queries = ch.zeros(batch_size)
    upsampler = Upsample(size=(image.size(2), image.size(2)))
    prior = ch.zeros(batch_size, 3, prior_size, prior_size).cuda()

    dim = prior.nelement() / batch_size
    prior_step = gd_prior_step if mode == 'l2' else eg_step
    image_step = l2_image_step if mode == 'l2' else linf_step
    proj_maker = l2_proj if mode == 'l2' else linf_proj
    proj_step = proj_maker(image, epsilon)

    def normalized_eval(x):
        x_copy = x.clone()
        x_copy = ch.stack([F.normalize(x_copy[i], [0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) \
                        for i in range(batch_size)])
        return model_to_fool(x_copy)

    # Loss function
    criterion = ch.nn.CrossEntropyLoss(reduction='none')

    losses = criterion(normalized_eval(image), true_label)

    # Original classifications
    orig_images = image.clone()
    orig_classes = normalized_eval(image).argmax(1).cuda()
    correct_classified_mask = (orig_classes == true_label).cpu().float()
    total_ims = correct_classified_mask.cpu().sum()
    not_dones_mask = correct_classified_mask.cpu().clone()

    t = 0

    while not ch.any(total_queries > max_queries):
        t += gradient_iters * 2
        if t >= max_queries:
            break
        if not nes:
            ## Updating the prior:
            # Create noise for exporation, estimate the gradient, and take a PGD step
            exp_noise = exploration * ch.randn_like(prior) / (dim**0.5)
            # Query deltas for finite difference estimator
            q1 = upsampler(prior + exp_noise)
            q2 = upsampler(prior - exp_noise)
            # Loss points for finite difference estimator
            l1 = criterion(normalized_eval(image + fd_eta * q1 / norm(q1)),
                           true_label)  # L(prior + c*noise)
            l2 = criterion(normalized_eval(image + fd_eta * q2 / norm(q2)),
                           true_label)  # L(prior - c*noise)
            # Finite differences estimate of directional derivative
            est_deriv = (l1 - l2) / (fd_eta * exploration)
            # 2-query gradient estimate
            est_grad = est_deriv.view(-1, 1, 1, 1) * exp_noise
            # Update the prior with the estimated gradient

            prior = prior_step(prior, est_grad, online_lr)

        else:
            prior = ch.zeros_like(image)
            for _ in range(gradient_iters):

                exp_noise = ch.randn_like(image) / (dim**0.5)
                est_deriv = (
                    criterion(normalized_eval(image + fd_eta * exp_noise),
                              true_label) -
                    criterion(normalized_eval(image - fd_eta * exp_noise),
                              true_label)) / fd_eta
                prior += est_deriv.view(-1, 1, 1, 1) * exp_noise

            # Preserve images that are already done,
            # Unless we are specifically measuring gradient estimation
            prior = prior * not_dones_mask.view(-1, 1, 1, 1)

        ## Update the image:
        # take a pgd step using the prior
        new_im = image_step(
            image,
            upsampler(prior *
                      correct_classified_mask.cuda().view(-1, 1, 1, 1)),
            image_lr)
        image = proj_step(new_im)

        image = ch.clamp(image, 0, 1)

        ## Continue query count
        total_queries += 2 * gradient_iters * not_dones_mask
        not_dones_mask = not_dones_mask * (
            (normalized_eval(image).argmax(1) == true_label).cpu().float())

        ## Logging stuff
        new_losses = criterion(normalized_eval(image), true_label).cpu()
        success_mask = (1 - not_dones_mask) * correct_classified_mask
        num_success = success_mask.cpu().sum()
        current_success_rate = (num_success /
                                correct_classified_mask.sum()).cpu().item()
        success_queries = ((success_mask * total_queries).sum() /
                           num_success).cpu().item()
        not_done_loss = ((new_losses * not_dones_mask).cpu().sum() /
                         not_dones_mask.sum()).item()
        max_curr_queries = total_queries.max().cpu().item()
        if log_progress:
            print("Queries: %d | Success rate: %f | Average queries: %f" %
                  (max_curr_queries, current_success_rate, success_queries))

        if current_success_rate == 1.0:
            break
    if batch_size == 1:
        return {
            "image_adv": image.cpu().numpy(),
            "prediction": normalized_eval(image).argmax(1),
            "elapsed_budget": total_queries.cpu().numpy()[0],
            "success": success_mask.cpu().numpy()[0] == True
        }
    return {
        'average_queries': success_queries,
        'num_correctly_classified': correct_classified_mask.sum().cpu().item(),
        'success_rate': current_success_rate,
        'images_orig': orig_images.cpu().numpy(),
        'images_adv': image.cpu().numpy(),
        'all_queries': total_queries.cpu().numpy(),
        'correctly_classified': correct_classified_mask.cpu().numpy(),
        'success': success_mask.cpu().numpy()
    }
예제 #17
0
    def make_adversarial_examples(self, batch_index, images, true_labels, args, target_model):
        '''
        The attack process for generating adversarial examples with priors.
        '''
        prior_size = target_model.input_size[-1] if not args.tiling else args.tile_size
        assert args.tiling == (args.dataset == "ImageNet")
        if args.tiling:
            upsampler = Upsample(size=(target_model.input_size[-2], target_model.input_size[-1]))
        else:
            upsampler = lambda x: x
        with torch.no_grad():
            logit = target_model(images)
        pred = logit.argmax(dim=1)
        query = torch.zeros(args.batch_size).cuda()
        correct = pred.eq(true_labels).float()  # shape = (batch_size,)
        not_done = correct.clone()  # shape = (batch_size,)
        selected = torch.arange(batch_index * args.batch_size,
                                min((batch_index + 1) * args.batch_size, self.total_images))  # 选择这个batch的所有图片的index
        if args.targeted:
            if args.target_type == 'random':
                target_labels = torch.randint(low=0, high=CLASS_NUM[args.dataset], size=true_labels.size()).long().cuda()
                invalid_target_index = target_labels.eq(true_labels)
                while invalid_target_index.sum().item() > 0:
                    target_labels[invalid_target_index] = torch.randint(low=0, high=logit.shape[1],
                                                                 size=target_labels[invalid_target_index].shape).long().cuda()
                    invalid_target_index = target_labels.eq(true_labels)
            elif args.target_type == 'least_likely':
                target_labels = logit.argmin(dim=1)
            elif args.target_type == "increment":
                target_labels = torch.fmod(true_labels + 1, CLASS_NUM[args.dataset])
            else:
                raise NotImplementedError('Unknown target_type: {}'.format(args.target_type))
        else:
            target_labels = None
        prior = torch.zeros(args.batch_size, IN_CHANNELS[args.dataset], prior_size, prior_size).cuda()
        dim = prior.nelement() / args.batch_size               # nelement() --> total number of elements
        prior_step = self.gd_prior_step if args.norm == 'l2' else self.eg_prior_step
        image_step = self.l2_image_step if args.norm == 'l2' else self.linf_image_step
        proj_maker = self.l2_proj if args.norm == 'l2' else self.linf_proj  # 调用proj_maker返回的是一个函数
        proj_step = proj_maker(images, args.epsilon)
        criterion = self.cw_loss if args.loss == "cw" else self.xent_loss
        # Loss function
        adv_images = images.clone()
        for step_index in range(args.max_queries // 2):
            # Create noise for exporation, estimate the gradient, and take a PGD step
            exp_noise = args.exploration * torch.randn_like(prior) / (dim ** 0.5)  # parameterizes the exploration to be done around the prior
            # Query deltas for finite difference estimator
            exp_noise = exp_noise.cuda()
            q1 = upsampler(prior + exp_noise)  # 这就是Finite Difference算法, prior相当于论文里的v,这个prior也会更新,把梯度累积上去
            q2 = upsampler(prior - exp_noise)   # prior 相当于累积的更新量,用这个更新量,再去修改image,就会变得非常准
            # Loss points for finite difference estimator
            q1_images = adv_images + args.fd_eta * q1 / self.norm(q1)
            q2_images = adv_images + args.fd_eta * q2 / self.norm(q2)
            with torch.no_grad():
                q1_logits = target_model(q1_images)
                q2_logits = target_model(q2_images)
            l1 = criterion(q1_logits, true_labels, target_labels)
            l2 = criterion(q2_logits, true_labels, target_labels)
            # Finite differences estimate of directional derivative
            est_deriv = (l1 - l2) / (args.fd_eta * args.exploration)  # 方向导数 , l1和l2是loss
            # 2-query gradient estimate
            est_grad = est_deriv.view(-1, 1, 1, 1) * exp_noise  # B, C, H, W,
            # Update the prior with the estimated gradient
            prior = prior_step(prior, est_grad, args.online_lr)  # 注意,修正的是prior,这就是bandit算法的精髓
            grad = upsampler(prior)  # prior相当于梯度
            ## Update the image:
            # take a pgd step using the prior
            adv_images = image_step(adv_images, grad * correct.view(-1, 1, 1, 1), args.image_lr)  # prior放大后相当于累积的更新量,可以用来更新
            adv_images = proj_step(adv_images)
            adv_images = torch.clamp(adv_images, 0, 1)
            with torch.no_grad():
                adv_logit = target_model(adv_images)
            adv_pred = adv_logit.argmax(dim=1)
            adv_prob = F.softmax(adv_logit, dim=1)
            adv_loss = criterion(adv_logit, true_labels, target_labels)
            ## Continue query count
            query = query + 2 * not_done
            if args.targeted:
                not_done = not_done * (1 - adv_pred.eq(target_labels).float()).float()  # not_done初始化为 correct, shape = (batch_size,)
            else:
                not_done = not_done * adv_pred.eq(true_labels).float()  # 只要是跟原始label相等的,就还需要query,还没有成功
            success = (1 - not_done) * correct
            success_query = success * query
            not_done_loss = adv_loss * not_done
            not_done_prob = adv_prob[torch.arange(args.batch_size), true_labels] * not_done

            log.info('Attacking image {} - {} / {}, step {}, max query {}'.format(
                batch_index * args.batch_size, (batch_index + 1) * args.batch_size,
                self.total_images, step_index + 1, int(query.max().item())
            ))
            log.info('        correct: {:.4f}'.format(correct.mean().item()))
            log.info('       not_done: {:.4f}'.format(not_done[correct.byte()].mean().item()))
            log.info('      fd_scalar: {:.9f}'.format((l1 - l2).mean().item()))
            if success.sum().item() > 0:
                log.info('     mean_query: {:.4f}'.format(success_query[success.byte()].mean().item()))
                log.info('   median_query: {:.4f}'.format(success_query[success.byte()].median().item()))
            if not_done.sum().item() > 0:
                log.info('  not_done_loss: {:.4f}'.format(not_done_loss[not_done.byte()].mean().item()))
                log.info('  not_done_prob: {:.4f}'.format(not_done_prob[not_done.byte()].mean().item()))

            if not not_done.byte().any():  # all success
                break


        for key in ['query', 'correct',  'not_done',
                    'success', 'success_query', 'not_done_loss', 'not_done_prob']:
            value_all = getattr(self, key+"_all")
            value = eval(key)
            value_all[selected] = value.detach().float().cpu()  # 由于value_all是全部图片都放在一个数组里,当前batch选择出来