Ejemplo n.º 1
0
def test_attack(threshold, arch, dataset, test_loader):
    target_model = StandardModel(dataset, arch, no_grad=False)
    if torch.cuda.is_available():
        target_model = target_model.cuda()
    target_model.eval()
    attack = LinfPGDAttack(target_model, loss_fn=nn.CrossEntropyLoss(reduction="sum"), eps=threshold, nb_iter=30,
                           eps_iter=0.01, rand_init=True, clip_min=0.0, clip_max=1.0, targeted=False)
    all_count = 0
    success_count = 0
    all_adv_images = []
    all_true_labels = []
    for idx, (img, true_label) in enumerate(test_loader):
        img = img.cuda()
        true_label = true_label.cuda().long()

        adv_image = attack.perturb(img, true_label) # (3, 224, 224), float
        if adv_image is None:
            continue
        adv_label = target_model.forward(adv_image).max(1)[1].detach().cpu().numpy().astype(np.int32)
        # adv_image = np.transpose(adv_image, (0, 2, 3, 1)) # N,C,H,W -> (N, H, W, 3), float
        all_count += len(img)
        true_label_np = true_label.detach().cpu().numpy().astype(np.int32)
        success_count+= len(np.where(true_label_np != adv_label)[0])
        all_adv_images.append(adv_image.cpu().detach().numpy())
        all_true_labels.append(true_label_np)
    attack_success_rate = success_count / float(all_count)
    log.info("Before train. Attack success rate is {:.3f}".format(attack_success_rate))
    return target_model, np.concatenate(all_adv_images,0), np.concatenate(all_true_labels, 0)  # N,224,224,3
def load_models(dataset):
    archs = []
    model_path_list = []
    if dataset == "CIFAR-10" or dataset == "CIFAR-100":
        for arch in ["resnet-110","WRN-28-10","WRN-34-10","resnext-8x64d","resnext-16x64d"]:
            test_model_path = "{}/train_pytorch_model/real_image_model/{}-pretrained/{}/checkpoint.pth.tar".format(
                PY_ROOT, dataset, arch)
            if os.path.exists(test_model_path):
                archs.append(arch)
                model_path_list.append(test_model_path)
            else:
                log.info(test_model_path + " does not exist!")
    elif dataset == "TinyImageNet":
        # for arch in ["vgg11_bn","resnet18","vgg16_bn","resnext64_4","densenet121"]:
        for arch in MODELS_TEST_STANDARD[dataset]:
            test_model_path = "{}/train_pytorch_model/real_image_model/{}@{}@*.pth.tar".format(
                PY_ROOT, dataset, arch)
            test_model_path = list(glob.glob(test_model_path))[0]
            if os.path.exists(test_model_path):
                archs.append(arch)
                model_path_list.append(test_model_path)
            else:
                log.info(test_model_path + "does not exist!")
    else:
        for arch in ["inceptionv3","inceptionv4", "inceptionresnetv2","resnet101", "resnet152"]:
            test_model_list_path = "{}/train_pytorch_model/real_image_model/{}-pretrained/checkpoints/{}*.pth".format(
                PY_ROOT, dataset, arch)
            test_model_path = list(glob.glob(test_model_list_path))
            if len(test_model_path) == 0:  # this arch does not exists in args.dataset
                continue
            archs.append(arch)
            model_path_list.append(test_model_path[0])
    models = []
    print("begin construct model")
    if dataset == "TinyImageNet":
        for idx, arch in enumerate(archs):
            model = MetaLearnerModelBuilder.construct_tiny_imagenet_model(arch, dataset)
            model_path = model_path_list[idx]
            model.load_state_dict(torch.load(model_path, map_location=lambda storage, location: storage)["state_dict"])
            model.cuda()
            model.eval()
            models.append(model)
    else:
        for arch in archs:
            model = StandardModel(dataset, arch, no_grad=True)
            model.cuda()
            model.eval()
            models.append(model)
    print("end construct model")
    return models
Ejemplo n.º 3
0
def main(args, arch):
    model = StandardModel(args["dataset"], arch, False)
    model.cuda()
    model.eval()
    # attack related settings
    if args["attack_method"] == "zoo" or args[
            "attack_method"] == "autozoom_bilin":
        if args["img_resize"] is None:
            args["img_resize"] = model.input_size[-1]
            log.info(
                "Argument img_resize is not set and not using autoencoder, set to image original size:{}"
                .format(args["img_resize"]))

    codec = None
    if args["attack_method"] == "zoo_ae" or args[
            "attack_method"] == "autozoom_ae":
        codec = Codec(model.input_size[-1],
                      IN_CHANNELS[args["dataset"]],
                      args["compress_mode"],
                      args["resize"],
                      use_tanh=args["use_tanh"])
        codec.load_codec(args["codec_path"])
        codec.cuda()
        decoder = codec.decoder
        args["img_resize"] = decoder.input_shape[1]
        log.info(
            "Loading autoencoder: {}, set the attack image size to:{}".format(
                args["codec_path"], args["img_resize"]))

    # setup attack
    if args["attack_method"] == "zoo":
        blackbox_attack = ZOO(model, args["dataset"], args)
    elif args["attack_method"] == "zoo_ae":
        blackbox_attack = ZOO_AE(model, args["dataset"], args, decoder)
    elif args["attack_method"] == "autozoom_bilin":
        blackbox_attack = AutoZOOM_BiLIN(model, args["dataset"], args)
    elif args["attack_method"] == "autozoom_ae":
        blackbox_attack = AutoZOOM_AE(model, args["dataset"], args, decoder)
    target_str = "untargeted" if args[
        "attack_type"] != "targeted" else "targeted_{}".format(
            args["target_type"])
    save_result_path = args[
        "exp_dir"] + "/data_{}@arch_{}@attack_{}@{}_result.json".format(
            args["dataset"], arch, args["attack_method"], target_str)
    attack_framework = AutoZoomAttackFramework(args)
    attack_framework.attack_dataset_images(args, blackbox_attack, arch, model,
                                           codec, save_result_path)
    model.cpu()
Ejemplo n.º 4
0
def main(args, arch):
    model = StandardModel(args.dataset, arch, args.solver != "fake_zero")
    model.cuda()
    model.eval()
    if args.init_size is None:
        args.init_size = model.input_size[-1]
        log.info(
            "Argument init_size is not set and not using autoencoder, set to image original size:{}"
            .format(args.init_size))

    target_str = "untargeted" if not args.targeted else "targeted_{}".format(
        args.target_type)
    save_result_path = args.exp_dir + "/data_{}@arch_{}@solver_{}@{}_result.json".format(
        args.dataset, arch, args.solver, target_str)
    if os.path.exists(save_result_path):
        model.cpu()
        return
    attack_framework = ZooAttackFramework(args)
    attack_framework.attack_dataset_images(args, arch, model, save_result_path)
    model.cpu()
def main():
    parser = argparse.ArgumentParser(
        description='Square Attack Hyperparameters.')
    parser.add_argument('--norm',
                        type=str,
                        required=True,
                        choices=['l2', 'linf'])
    parser.add_argument('--dataset', type=str, required=True)
    parser.add_argument(
        '--gpu',
        type=str,
        required=True,
        help='GPU number. Multiple GPUs are possible for PT models.')
    parser.add_argument(
        '--p',
        type=float,
        default=0.05,
        help=
        'Probability of changing a coordinate. Note: check the paper for the best values. '
        'Linf standard: 0.05, L2 standard: 0.1. But robust models require higher p.'
    )
    parser.add_argument('--epsilon', type=float, help='Radius of the Lp ball.')
    parser.add_argument('--max_queries', type=int, default=1000)
    parser.add_argument(
        '--json-config',
        type=str,
        default=
        '/home1/machen/meta_perturbations_black_box_attack/configures/square_attack_conf.json',
        help='a configures file to be passed in instead of arguments')
    parser.add_argument('--batch_size', type=int, default=100)
    parser.add_argument('--targeted', action="store_true")
    parser.add_argument('--target_type',
                        type=str,
                        default='random',
                        choices=['random', 'least_likely', "increment"])
    parser.add_argument('--loss', type=str)

    args = parser.parse_args()
    os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
    os.environ["CUDA_VISIBLE_DEVICES"] = args.gpu

    if args.json_config:
        # If a json file is given, use the JSON file as the base, and then update it with args
        defaults = json.load(open(args.json_config))[args.dataset][args.norm]
        arg_vars = vars(args)
        arg_vars = {
            k: arg_vars[k]
            for k in arg_vars if arg_vars[k] is not None
        }
        defaults.update(arg_vars)
        args = SimpleNamespace(**defaults)

    if args.targeted and args.dataset == "ImageNet":
        args.max_queries = 10000

    save_dir_path = "{}/data_square_attack/{}/{}".format(
        PY_ROOT, args.dataset,
        "targeted_attack" if args.targeted else "untargeted_attack")
    os.makedirs(save_dir_path, exist_ok=True)
    loss_type = "cw" if not args.targeted else "xent"
    args.loss = loss_type
    log_path = osp.join(
        save_dir_path,
        get_log_path(args.dataset, loss_type, args.norm, args.targeted,
                     args.target_type))

    set_log_file(log_path)

    log.info('Command line is: {}'.format(' '.join(sys.argv)))
    log.info("Log file is written in {}".format(log_path))
    log.info('Called with args:')
    print_args(args)
    trn_data_loader = DataLoaderMaker.get_img_label_data_loader(
        args.dataset, args.batch_size, is_train=True)
    models = []
    for arch in MODELS_TRAIN_STANDARD[args.dataset]:
        if StandardModel.check_arch(arch, args.dataset):
            model = StandardModel(args.dataset, arch, True)
            model = model.eval()
            models.append({"arch_name": arch, "model": model})
    model_data_dict = defaultdict(list)
    for images, labels in trn_data_loader:
        model_info = random.choice(models)
        arch = model_info["arch_name"]
        model = model_info["model"]
        if images.size(-1) != model.input_size[-1]:
            images = F.interpolate(images,
                                   size=model.input_size[-1],
                                   mode='bilinear',
                                   align_corners=True)
        model_data_dict[(arch, model)].append((images, labels))

    log.info("Assign data to multiple models over!")
    attacker = SquareAttack(args.dataset,
                            args.targeted,
                            args.target_type,
                            args.epsilon,
                            args.norm,
                            max_queries=args.max_queries)
    attacker.attack_all_images(args, model_data_dict, save_dir_path)
    log.info("All done!")
Ejemplo n.º 6
0
                test_model_list_path = list(glob.glob(test_model_list_path))
                if len(test_model_list_path
                       ) == 0:  # this arch does not exists in args.dataset
                    continue
                archs.append(arch)
    else:
        assert args.arch is not None
        archs = [args.arch]
    args.arch = ", ".join(archs)
    log.info('Command line is: {}'.format(' '.join(sys.argv)))
    log.info("Log file is written in {}".format(log_file_path))
    log.info('Called with args:')
    print_args(args)
    surrogate_model = StandardModel(args.dataset, args.surrogate_arch, False)
    surrogate_model.cuda()
    surrogate_model.eval()

    attacker = SwitchNeg(args.dataset, args.batch_size, args.targeted,
                         args.target_type, args.epsilon, args.norm, 0.0, 1.0,
                         args.max_queries)
    for arch in archs:
        if args.attack_defense:
            save_result_path = args.exp_dir + "/{}_{}_result.json".format(
                arch, args.defense_model)
        else:
            save_result_path = args.exp_dir + "/{}_result.json".format(arch)
        if os.path.exists(save_result_path):
            continue
        log.info("Begin attack {} on {}, result will be saved to {}".format(
            arch, args.dataset, save_result_path))
Ejemplo n.º 7
0
        state.targeted = args.targeted
        state.dataset = args.dataset
        state.batch_size = args.batch_size
    device = torch.device(args.gpu)
    train_loader = DataLoaderMaker.get_img_label_data_loader(
        args.dataset, state.batch_size, True)
    val_loader = DataLoaderMaker.get_img_label_data_loader(
        args.dataset, state.batch_size, False)
    nets = []
    log.info("Initialize pretrained models.")
    for model_name in MODELS_TRAIN_STANDARD[args.dataset]:
        pretrained_model = StandardModel(args.dataset,
                                         model_name,
                                         no_grad=False)
        # pretrained_model.cuda()
        pretrained_model.eval()
        nets.append(pretrained_model)
    log.info("Initialize over!")
    model = nn.Sequential(ImagenetEncoder(), ImagenetDecoder(args.dataset))
    model = model.cuda()
    optimizer_G = torch.optim.SGD(model.parameters(),
                                  state.learning_rate_G,
                                  momentum=state.momentum,
                                  weight_decay=0,
                                  nesterov=True)
    scheduler_G = torch.optim.lr_scheduler.StepLR(optimizer_G,
                                                  step_size=state.epochs //
                                                  state.schedule,
                                                  gamma=state.gamma)
    hingeloss = MarginLoss(margin=state.margin, target=state.targeted)
Ejemplo n.º 8
0
lr_scheduler = optim.lr_scheduler.LambdaLR(optimizer, [anneal_lr])

for epoch in range(EPOCH_TOTAL):  # loop over the dataset multiple times
    logger.info("Start Epoch {}".format(epoch))
    running_loss_1, running_loss_2 = 0.0, 0.0
    lr_scheduler.step(epoch)

    for i, data_batch in enumerate(train_loader):
        # get the inputs; data is a list of [inputs, labels]
        # if i == 19:
        #     break
        img_batch, label_batch = data_batch
        img_batch, label_batch = img_batch.cuda(), label_batch.cuda()

        train_img_batch, train_label_batch = [], []
        model.eval()
        if args.adv_ratio > 0.:
            adv_x = pgd.projected_gradient_descent(model, img_batch,
                                                   **pgd_kwargs)
            adv_x_s, adv_label_batch_s = shuffle_minibatch(adv_x, label_batch)
            train_img_batch.append(adv_x_s)
            train_label_batch.append(adv_label_batch_s)

        if args.adv_ratio < 1.:
            img_batch_s, label_batch_s = shuffle_minibatch(
                img_batch, label_batch)
            train_img_batch.append(img_batch_s)
            train_label_batch.append(label_batch_s)

        train_img_batch = torch.cat(train_img_batch, dim=0)
        model.train()
    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()
                                transform=train_preprocessor)
elif dataset == "TinyImageNet":
    train_dataset = TinyImageNet(IMAGE_DATA_ROOT[dataset],
                                 train_preprocessor,
                                 train=True)

batch_size = args.batch_size
train_loader = torch.utils.data.DataLoader(train_dataset,
                                           batch_size=batch_size,
                                           shuffle=True,
                                           num_workers=0)

print('==> Building model..')
arch_list = MODELS_TRAIN_STANDARD[args.dataset]
model_dict = {}
for arch in arch_list:
    if StandardModel.check_arch(arch, args.dataset):
        print("begin use arch {}".format(arch))
        model = StandardModel(args.dataset, arch, no_grad=True)
        model_dict[arch] = model.eval()
        print("use arch {} done".format(arch))
print("==> Save gradient..")
for arch, model in model_dict.items():
    dump_path = "{}/benign_images_logits_pair/{}/{}_images.npy".format(
        PY_ROOT, args.dataset, arch)
    os.makedirs(os.path.dirname(dump_path), exist_ok=True)
    model = model.cuda()
    save_image_logits_pairs(model, train_loader, dump_path, args.batch_size,
                            args.max_items)
    model.cpu()
Ejemplo n.º 11
0
    def __init__(self, dataset, batch_size, meta_arch, meta_train_type, distill_loss, data_loss, norm, targeted, use_softmax, mode="meta"):
        if mode == "meta":
            target_str = "targeted_attack_random" if targeted else "untargeted_attack"
            # 2Q_DISTILLATION@CIFAR-100@TRAIN_I_TEST_II@model_resnet34@loss_pair_mse@dataloss_cw_l2_untargeted_attack@epoch_4@meta_batch_size_30@num_support_50@num_updates_12@lr_0.001@inner_lr_0.01.pth.tar
            self.meta_model_path = "{root}/train_pytorch_model/meta_simulator/{meta_train_type}@{dataset}@{split}@model_{meta_arch}@loss_{loss}@dataloss_{data_loss}_{norm}_{target_str}*inner_lr_0.01.pth.tar".format(
                root=PY_ROOT, meta_train_type=meta_train_type.upper(), dataset=dataset, split=SPLIT_DATA_PROTOCOL.TRAIN_I_TEST_II,
                meta_arch=meta_arch, loss=distill_loss, data_loss=data_loss, norm=norm, target_str=target_str)
            log.info("start using {}".format(self.meta_model_path))
            self.meta_model_path = glob.glob(self.meta_model_path)
            pattern = re.compile(".*model_(.*?)@.*inner_lr_(.*?)\.pth.*")
            assert len(self.meta_model_path) > 0
            self.meta_model_path = self.meta_model_path[0]
            log.info("load meta model {}".format(self.meta_model_path))
            ma = pattern.match(os.path.basename(self.meta_model_path))
            arch = ma.group(1)
            self.inner_lr = float(ma.group(2))
            meta_backbone = self.construct_model(arch, dataset)
            self.meta_network = MetaNetwork(meta_backbone)
            self.pretrained_weights = torch.load(self.meta_model_path, map_location=lambda storage, location: storage)
            self.meta_network.load_state_dict(self.pretrained_weights["state_dict"])
            log.info("Load model in epoch {}.".format(self.pretrained_weights["epoch"]))
            self.pretrained_weights = self.pretrained_weights["state_dict"]
        elif mode == "vanilla":
            target_str = "targeted" if targeted else "untargeted"
            arch = meta_arch
            # 2Q_DISTILLATION@CIFAR-100@TRAIN_I_TEST_II@model_resnet34@loss_pair_mse@dataloss_cw_l2_untargeted_attack@epoch_4@meta_batch_size_30@num_support_50@num_updates_12@lr_0.001@inner_lr_0.01.pth.tar
            self.meta_model_path = "{root}/train_pytorch_model/vanilla_simulator/{dataset}@{norm}_norm_{target_str}@{meta_arch}*.tar".format(
                root=PY_ROOT, dataset=dataset,
                meta_arch=meta_arch,norm=norm, target_str=target_str)
            log.info("start using {}".format(self.meta_model_path))
            self.meta_model_path = glob.glob(self.meta_model_path)
            assert len(self.meta_model_path) > 0
            self.meta_model_path = self.meta_model_path[0]
            log.info("load meta model {}".format(self.meta_model_path))
            self.inner_lr = 0.01
            self.meta_network = self.construct_model(meta_arch, dataset)
            self.pretrained_weights = torch.load(self.meta_model_path, map_location=lambda storage, location: storage)
            log.info("Load model in epoch {}.".format(self.pretrained_weights["epoch"]))
            self.pretrained_weights = self.pretrained_weights["state_dict"]
        elif mode == "deep_benign_images":
            arch = "resnet34"
            self.inner_lr = 0.01
            self.meta_network = self.construct_model(arch, dataset)
            self.meta_model_path = "{root}/train_pytorch_model/real_image_model/{dataset}@{arch}@epoch_200@lr_0.1@batch_200.pth.tar".format(
                root=PY_ROOT, dataset=dataset, arch=arch)
            assert os.path.exists(self.meta_model_path), "{} does not exists!".format(self.meta_model_path)
            self.pretrained_weights = torch.load(self.meta_model_path, map_location=lambda storage, location: storage)[
                "state_dict"]
        elif mode == "random_init":
            arch = "resnet34"
            self.inner_lr = 0.01
            self.meta_network = self.construct_model(arch, dataset)
            self.pretrained_weights = self.meta_network.state_dict()
        elif mode == 'ensemble_avg':
            self.inner_lr = 0.01
            self.archs = ["densenet-bc-100-12","resnet-110","vgg19_bn"]
            self.meta_network = []  # meta_network和pretrained_weights都改成list
            self.pretrained_weights = []
            for arch in self.archs:
                model = StandardModel(dataset, arch, no_grad=False, load_pretrained=True)
                model.eval()
                model.cuda()
                self.meta_network.append(model)
                self.pretrained_weights.append(model.state_dict())
        elif mode == "benign_images":
            self.inner_lr = 0.01
            self.meta_model_path = "{root}/train_pytorch_model/meta_simulator_on_benign_images/{dataset}@{split}*@inner_lr_0.01.pth.tar".format(
                root=PY_ROOT, meta_train_type=meta_train_type.upper(), dataset=dataset,
                split=SPLIT_DATA_PROTOCOL.TRAIN_I_TEST_II)
            self.meta_model_path = glob.glob(self.meta_model_path)
            pattern = re.compile(".*model_(.*?)@.*")
            assert len(self.meta_model_path) > 0
            self.meta_model_path = self.meta_model_path[0]
            ma = pattern.match(os.path.basename(self.meta_model_path))
            log.info("Loading meta model from {}".format(self.meta_model_path))
            arch = ma.group(1)
            self.pretrained_weights = torch.load(self.meta_model_path, map_location=lambda storage, location: storage)["state_dict"]
            meta_backbone = self.construct_model(arch, dataset)
            self.meta_network = MetaNetwork(meta_backbone)
            self.meta_network.load_state_dict(self.pretrained_weights)
            self.meta_network.eval()
            self.meta_network.cuda()
        elif mode == "reptile_on_benign_images":
            self.inner_lr = 0.01
            self.meta_model_path = "{root}/train_pytorch_model/meta_simulator_reptile_on_benign_images/{dataset}@{split}*@inner_lr_0.01.pth.tar".format(
                root=PY_ROOT, meta_train_type=meta_train_type.upper(), dataset=dataset,
                split=SPLIT_DATA_PROTOCOL.TRAIN_I_TEST_II)
            self.meta_model_path = glob.glob(self.meta_model_path)
            pattern = re.compile(".*model_(.*?)@.*")
            assert len(self.meta_model_path) > 0
            self.meta_model_path = self.meta_model_path[0]
            log.info("Loading meta model from {}".format(self.meta_model_path))
            ma = pattern.match(os.path.basename(self.meta_model_path))
            arch = ma.group(1)
            self.pretrained_weights = torch.load(self.meta_model_path, map_location=lambda storage, location: storage)["state_dict"]
            meta_backbone = self.construct_model(arch, dataset)
            self.meta_network = MetaNetwork(meta_backbone)
            self.meta_network.load_state_dict(self.pretrained_weights)
            self.meta_network.eval()
            self.meta_network.cuda()


        self.arch = arch
        self.dataset = dataset
        self.need_pair_distance = (distill_loss.lower()=="pair_mse")
        # self.need_pair_distance = False
        self.softmax = nn.Softmax(dim=1)
        self.mse_loss = nn.MSELoss(reduction="mean")
        self.pair_wise_distance = nn.PairwiseDistance(p=2)
        self.use_softmax = use_softmax
        if mode != "ensemble_avg":
            self.meta_network.load_state_dict(self.pretrained_weights)
            self.meta_network.eval()
            self.meta_network.cuda()
        self.batch_size = batch_size
        if mode == 'ensemble_avg':
            self.batch_weights = defaultdict(dict)
            for idx in range(len(self.pretrained_weights)):
                for i in range(batch_size):
                    self.batch_weights[idx][i] = self.pretrained_weights[idx]
        else:
            self.batch_weights = dict()
            for i in range(batch_size):
                self.batch_weights[i] = self.pretrained_weights
Ejemplo n.º 12
0
def main():
    parser = argparse.ArgumentParser(
        description='Square Attack Hyperparameters.')
    parser.add_argument('--norm',
                        type=str,
                        required=True,
                        choices=['l2', 'linf'])
    parser.add_argument('--dataset', type=str, required=True)
    parser.add_argument('--exp-dir',
                        default='logs',
                        type=str,
                        help='directory to save results and logs')
    parser.add_argument(
        '--gpu',
        type=str,
        required=True,
        help='GPU number. Multiple GPUs are possible for PT models.')
    parser.add_argument(
        '--p',
        type=float,
        default=0.05,
        help=
        'Probability of changing a coordinate. Note: check the paper for the best values. '
        'Linf standard: 0.05, L2 standard: 0.1. But robust models require higher p.'
    )
    parser.add_argument('--epsilon', type=float, help='Radius of the Lp ball.')
    parser.add_argument('--max_queries', type=int, default=10000)
    parser.add_argument('--surrogate_queries', type=int, default=10)
    parser.add_argument(
        '--json-config',
        type=str,
        default=
        '/home1/machen/meta_perturbations_black_box_attack/configures/square_attack_conf.json',
        help='a configures file to be passed in instead of arguments')
    parser.add_argument('--batch_size', type=int, default=100)
    parser.add_argument('--targeted', action="store_true")
    parser.add_argument('--target_type',
                        type=str,
                        default='increment',
                        choices=['random', 'least_likely', "increment"])
    parser.add_argument('--attack_defense', action="store_true")
    parser.add_argument('--defense_model', type=str, default=None)
    parser.add_argument('--arch',
                        default=None,
                        type=str,
                        help='network architecture')
    parser.add_argument('--test_archs', action="store_true")
    parser.add_argument('--accept_ratio',
                        type=float,
                        default=0.75,
                        help="14 surrogate models * 0.75 = 10 models")

    args = parser.parse_args()
    os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
    os.environ["CUDA_VISIBLE_DEVICES"] = args.gpu

    if args.json_config:
        # If a json file is given, use the JSON file as the base, and then update it with args
        defaults = json.load(open(args.json_config))[args.dataset][args.norm]
        arg_vars = vars(args)
        arg_vars = {
            k: arg_vars[k]
            for k in arg_vars if arg_vars[k] is not None
        }
        defaults.update(arg_vars)
        args = SimpleNamespace(**defaults)

    if args.targeted and args.dataset == "ImageNet":
        args.max_queries = 50000
    args.exp_dir = os.path.join(
        args.exp_dir,
        get_exp_dir_name(args.dataset, args.norm, args.targeted,
                         args.target_type, args))
    os.makedirs(args.exp_dir, exist_ok=True)
    if args.test_archs:
        if args.attack_defense:
            log_file_path = osp.join(
                args.exp_dir, 'run_defense_{}.log'.format(args.defense_model))
        else:
            log_file_path = osp.join(args.exp_dir, 'run.log')
    elif args.arch is not None:
        if args.attack_defense:
            log_file_path = osp.join(
                args.exp_dir,
                'run_defense_{}_{}.log'.format(args.arch, args.defense_model))
        else:
            log_file_path = osp.join(args.exp_dir,
                                     'run_{}.log'.format(args.arch))
    set_log_file(log_file_path)
    if args.test_archs:
        archs = []
        if args.dataset == "CIFAR-10" or args.dataset == "CIFAR-100":
            for arch in MODELS_TEST_STANDARD[args.dataset]:
                test_model_path = "{}/train_pytorch_model/real_image_model/{}-pretrained/{}/checkpoint.pth.tar".format(
                    PY_ROOT, args.dataset, arch)
                if os.path.exists(test_model_path):
                    archs.append(arch)
                else:
                    log.info(test_model_path + " does not exists!")
        elif args.dataset == "TinyImageNet":
            for arch in MODELS_TEST_STANDARD[args.dataset]:
                test_model_list_path = "{root}/train_pytorch_model/real_image_model/{dataset}@{arch}*.pth.tar".format(
                    root=PY_ROOT, dataset=args.dataset, arch=arch)
                test_model_path = list(glob.glob(test_model_list_path))
                if test_model_path and os.path.exists(test_model_path[0]):
                    archs.append(arch)
        else:
            for arch in MODELS_TEST_STANDARD[args.dataset]:
                test_model_list_path = "{}/train_pytorch_model/real_image_model/{}-pretrained/checkpoints/{}*.pth".format(
                    PY_ROOT, args.dataset, arch)
                test_model_list_path = list(glob.glob(test_model_list_path))
                if len(test_model_list_path
                       ) == 0:  # this arch does not exists in args.dataset
                    continue
                archs.append(arch)
    else:
        assert args.arch is not None
        archs = [args.arch]

    train_model_names = MODELS_TRAIN_STANDARD[
        args.
        dataset] if not args.attack_defense else MODELS_TRAIN_WITHOUT_RESNET[
            args.dataset]
    surrogate_models = []
    for surr_arch in train_model_names:
        if surr_arch in archs:
            continue
        surrogate_model = StandardModel(args.dataset, surr_arch, no_grad=True)
        surrogate_model.eval()
        surrogate_models.append(surrogate_model)

    args.arch = ", ".join(archs)
    log.info('Command line is: {}'.format(' '.join(sys.argv)))
    log.info("Log file is written in {}".format(log_file_path))
    log.info('Called with args:')
    print_args(args)
    attacker = SquareAttack(args.dataset,
                            args.batch_size,
                            args.targeted,
                            args.target_type,
                            args.epsilon,
                            args.norm,
                            max_queries=args.max_queries)
    for arch in archs:
        if args.attack_defense:
            save_result_path = args.exp_dir + "/{}_{}_result.json".format(
                arch, args.defense_model)
        else:
            save_result_path = args.exp_dir + "/{}_result.json".format(arch)
        if os.path.exists(save_result_path):
            continue
        log.info("Begin attack {} on {}, result will be saved to {}".format(
            arch, args.dataset, save_result_path))
        if args.attack_defense:
            model = DefensiveModel(args.dataset,
                                   arch,
                                   no_grad=True,
                                   defense_model=args.defense_model)
        else:
            model = StandardModel(args.dataset, arch, no_grad=True)
        model.cuda()
        model.eval()
        attacker.attack_all_images(args, arch, model, surrogate_models,
                                   save_result_path)
                test_model_list_path = list(glob.glob(test_model_list_path))
                if len(test_model_list_path
                       ) == 0:  # this arch does not exists in args.dataset
                    continue
                archs.append(arch)
    else:
        assert args.arch is not None
        archs = [args.arch]
    args.arch = ", ".join(archs)
    log.info('Command line is: {}'.format(' '.join(sys.argv)))
    log.info("Log file is written in {}".format(log_file_path))
    log.info('Called with args:')
    print_args(args)
    surrogate_model = StandardModel(args.dataset, args.surrogate_arch, False)
    surrogate_model.cuda()
    surrogate_model.eval()
    other_surrogate_models = []
    train_model_names = MODELS_TRAIN_STANDARD[
        args.
        dataset] if not args.attack_defense else MODELS_TRAIN_WITHOUT_RESNET[
            args.dataset]
    for surr_arch in train_model_names:
        if surr_arch == args.surrogate_arch or surr_arch in archs:
            continue
        other_surrogate_model = StandardModel(args.dataset, surr_arch, False)
        other_surrogate_model.eval()
        other_surrogate_models.append(other_surrogate_model)

    attacker = SWITCH(args.dataset, args.batch_size, args.targeted,
                      args.target_type, args.epsilon, args.norm, 0.0, 1.0,
                      args.max_queries)