123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- # 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.conv.sparse_rs import RSAttack
- from utils.conv.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.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),])
- testset = datasets.CIFAR10(root=root+'/datasets/CIFAR/',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 = VGG().to(device)
- else:
- net = rob_VGG(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 = (-260,260) # aprox beta=100
- else:
- bounds = (-2.429065704345703,2.7537312507629395)
- # 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().copy())
- 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,32,32),dtype=bool)
- for z in range(bs):
- for ch in range(3):
- # adds True if pixel at this channel was perturbed
- perturbed[z] += abs(images[z,ch,:]-adv_images[z,ch,:]>0.0001)
- # this gives list of total perturbed pixels for each image
- total_l0 = perturbed.sum(axis=1).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()
|