# torch imports import torch # other modules import argparse import numpy as np import foolbox from tqdm import trange # PATHING import os import sys root = os.path.abspath(os.curdir) sys.path.append(root) # internal imports from utils.lin.sparse_rs import RSAttack from utils.lin.models import * from utils.helpers import * def main(): #---------------------------------------------------------------------------# # Parse the only input, path parser = argparse.ArgumentParser(description='Runs the pointwise attack on network for both beta=100 and beta=1') parser.add_argument("exp_path", help="pass the RELATIVE path of the PARENT directory of your network (net.pth)") # optinal arguements parser.add_argument("bs", nargs="?", type=int, default=64, help="batch size fed into foolbox") parser.add_argument("num_batches", nargs="?", type=int, default=16, help="batch size fed into foolbox") parser.add_argument("num_iters", nargs="?", type=int, default=10, help="times to repeat the attack") args = parser.parse_args() exp_path = root + '/' + args.exp_path + '/' bs = args.bs num_batches = args.num_batches num_iters = args.num_iters # since we only tested with k=10, we can simply check the name of dir (rob or og) if 'og' in exp_path.split('/'): k = 0 else: k = 10 #---------------------------------------------------------------------------# # check cuda if torch.cuda.is_available(): device = torch.device('cuda:0') else: device = torch.device('cpu') # get data loaders transform = transforms.Compose( [transforms.ToTensor(),transforms.Normalize((0.1307,), (0.3081,)),flatten()]) testset = datasets.MNIST(root=root+'/datasets/',train = False,download = False, transform=transform) test_loader = torch.utils.data.DataLoader(testset, batch_size=bs, shuffle=False, num_workers = 2) dataiter = iter(test_loader) images, labels = dataiter.next() images = images.numpy() # prep the network net_path = exp_path + 'net.pth' if k == 0: net = L_Net().to(device) else: net = r_L_Net(k).to(device) net.load_state_dict(torch.load(net_path, map_location=device)) net.eval() # RUN the attack for j in range(2): if j%2 == 1: bounds = (-160,160) # aprox beta=100 else: bounds = (images.min(),images.max()) # SETUP # fmodel = foolbox.models.PyTorchModel(net, bounds=bounds, num_classes=10, channel_axis=1, device=device) attack = foolbox.attacks.PointwiseAttack(model=fmodel,distance=foolbox.distances.L0) Data = {} Data['final_l0'] = [] # ITERATE # print("-----"*8) print("running attack with bounds: ",bounds) for batch in trange(num_batches): images, labels = dataiter.next() images = images.numpy() # final l0 distances of entire batch final_l0 = np.ones(bs)*10000 # best attacked images final_images = images.copy() for _ in range(num_iters): # run the attack saving the best adversarial images adv_images = attack(images.copy(), labels.numpy()) out = net(torch.tensor(adv_images).to(device)) _, pred_adv = torch.max(out.data, 1) # calculate L_0 distances for these new images perturbed = np.zeros((bs,28*28),dtype=bool) for z in range(bs): perturbed[z] += abs(images[z,:]-adv_images[z,:]>0.0001) # this gives list of total perturbed pixels for each image total_l0 = perturbed.sum(axis=1) # we only save on three conditions cond_1 = total_l0>0 # there was an actual attack cond_2 = total_l0 < final_l0 # the attack was better than the best one cond_3 = (pred_adv != labels.to(device)).to('cpu').numpy() # the attack was succesful # save both the images and the best L_0 distances for this iteration improved = cond_1*cond_2*cond_3 final_images[improved] = adv_images[improved] final_l0[improved] = np.minimum(total_l0[improved],final_l0[improved]) # save the best l_0 distances for this batch Data['final_l0'].append(final_l0) Data['final_l0'] = np.asarray(Data['final_l0']) print('Final median l0 distance: ',np.median(Data['final_l0'])) if __name__ == '__main__': main()