├── .gitignore ├── .gitmodules ├── find_uap.py ├── perturbations ├── perturbation_resnet18.pth └── perturbation_vgg16.pth ├── readme.md ├── test_uap.py └── utils.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | local_settings.py 55 | 56 | # Flask stuff: 57 | instance/ 58 | .webassets-cache 59 | 60 | # Scrapy stuff: 61 | .scrapy 62 | 63 | # Sphinx documentation 64 | docs/_build/ 65 | 66 | # PyBuilder 67 | target/ 68 | 69 | # IPython Notebook 70 | .ipynb_checkpoints 71 | 72 | # pyenv 73 | .python-version 74 | 75 | # celery beat schedule file 76 | celerybeat-schedule 77 | 78 | # dotenv 79 | .env 80 | 81 | # virtualenv 82 | venv/ 83 | ENV/ 84 | 85 | # Spyder project settings 86 | .spyderproject 87 | 88 | # Rope project settings 89 | .ropeproject 90 | 91 | # PyCharm Project Files 92 | .idea 93 | 94 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "DeepFool"] 2 | path = DeepFool 3 | url = https://github.com/LTS4/DeepFool.git 4 | -------------------------------------------------------------------------------- /find_uap.py: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | import utils 3 | import torch.backends.cudnn as cudnn 4 | cudnn.enabled = False 5 | ############################################################## 6 | from docopt import docopt 7 | import time 8 | import torch 9 | import torchvision 10 | import numpy as np 11 | import torch.optim as optim 12 | 13 | docstr = """Find Universal Adverserial Perturbation for Image Classification models trained in pytorch. 14 | 15 | Usage: 16 | find_uap.py [options] 17 | find_uap.py (-h | --help) 18 | find_uap.py --version 19 | 20 | Options: 21 | -h --help Show this screen. 22 | --version Show version. 23 | --data_dep= Use data for finding UAP or not.[default: False] 24 | --save_loc= Location for saving the UAP as FloatTensor[default: same_dir] 25 | --batch_size= batch_size for processing while forming UAP in gpu[default: 25] 26 | --gpu= Which GPU to use[default: 3] 27 | --max_iter_uni= maximum epochs to train for[default: 10] 28 | --xi= controls the l_p magnitude of the perturbation[default: 0.1866] 29 | --delta= controls the desired fooling rate[default: 0.2] 30 | --p= norm to be used for the UAP[default: inf] 31 | --num_classes= For deepfool: num_classes (limits the number of classes to test against)[default: 10] 32 | --overshoot= For deepfool: used as a termination criterion to prevent vanishing updates[default: 0.02] 33 | --max_iter_df= For deepfool: maximum number of iterations for deepfool[default: 10] 34 | --t_p= For batch deepfool: truth perentage, for how many flipped labels in a batch atleast.[default: 0.2] 35 | """ 36 | 37 | if __name__ == '__main__': 38 | start_time = time.time() 39 | args = docopt(docstr, version='v1.0') 40 | torch.cuda.set_device(int(args['--gpu'])) 41 | 42 | net = utils.get_model(args['']) 43 | 44 | location_img = args[''] 45 | img_list = args[''] 46 | max_iter_uni=int(args['--max_iter_uni']) 47 | xi=float(args['--xi']) 48 | delta=float(args['--delta']) 49 | if(args['--p'] == 'inf'): 50 | p = np.inf 51 | else: 52 | p=int(args['--p']) 53 | if(args['--save_loc'] == 'same_dir'): 54 | save_loc = '.' 55 | else: 56 | save_loc = args['--save_loc'] 57 | num_classes=int(args['--num_classes']) 58 | overshoot=float(args['--overshoot']) 59 | max_iter_df=int(args['--max_iter_df']) 60 | t_p=float(args['--t_p']) 61 | 62 | file = open(img_list) 63 | img_names = [] 64 | for f in file: 65 | img_names.append(f.split(' ')[0]) 66 | img_names = [location_img +x for x in img_names] 67 | st = time.time() 68 | if(eval(args['--data_dep'])): 69 | batch_size = 1 70 | uap = utils.universal_perturbation_data_dependant(img_names, net, xi=xi, delta=delta, max_iter_uni =max_iter_uni, 71 | p=p, num_classes=num_classes, overshoot=overshoot, 72 | max_iter_df=max_iter_df,init_batch_size = batch_size,t_p = t_p) 73 | else: 74 | batch_size = int(args['--batch_size']) 75 | uap = utils.universal_perturbation_data_independant(img_names, net,delta=delta, max_iter_uni = max_iter_uni, xi=xi, 76 | p=p, num_classes=num_classes, overshoot=overshoot, 77 | max_iter_df=max_iter_df,init_batch_size=batch_size) 78 | 79 | print('found uap.Total time: ' ,time.time()-st) 80 | uap = uap.data.cpu() 81 | torch.save(uap,save_loc+'perturbation_'+args['']+'.pth') 82 | -------------------------------------------------------------------------------- /perturbations/perturbation_resnet18.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BardOfCodes/universal_pytorch/6ae4dbb9795026a895b187063a9d6bd1e2842dd7/perturbations/perturbation_resnet18.pth -------------------------------------------------------------------------------- /perturbations/perturbation_vgg16.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BardOfCodes/universal_pytorch/6ae4dbb9795026a895b187063a9d6bd1e2842dd7/perturbations/perturbation_vgg16.pth -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Universal Adversarial Perturbation 2 | 3 | This code contains implementation of the following papers in pytorch. 4 | 5 | 1) [DeepFool](https://arxiv.org/abs/1511.04599) : A batch deepfool version based on [this](https://github.com/LTS4/DeepFool) github repository. 6 | 2) [Universal Adverserial Perturbation](https://arxiv.org/abs/1707.05572): Based on [this](https://github.com/LTS4/universal) github repository 7 | 3) [Fast Feature Fool](https://arxiv.org/abs/1610.08401): Based on [this](https://github.com/utsavgarg/fast-feature-fool) github repository 8 | 9 | ## Introduction 10 | 11 | Universal Adverserial Perturbations are single perturbations of very small norm which are able to successfully fool networks. It is quite astonishing as it shows that a single directional shift in the image space can cause such huge errors. 12 | 13 | 14 | ## Usage 15 | 16 | This repository provides two types of Universal Adverserial Perturbations(UAPs), Data dependent(based on Universal Adverserial Perturbations) , and Data Independent(based on fast feature fool). 17 | 18 | #### For finding UAP for a network : 19 | ``` 20 | python find_uap model im_path im_list [options] 21 | ``` 22 | Where, 23 | * `model`: is the network you want to find UAP for(currently 'vgg16' and 'resnet18', easily extendable) 24 | * `im_path`: is the path to folder containing images to train perturbation on. 25 | * `im_list` : is the path to file containing list of all images to train perturbation on. 26 | 27 | For more information, use `python find_uap.py --h` 28 | 29 | #### For Evaluating a perturbation's performance: 30 | ``` 31 | test_uap.py [options] 32 | ``` 33 | Where, 34 | * `model`: is the network you want to evaluate UAP for(currently 'vgg16' and 'resnet18', easily extendable) 35 | * `im_path`: is the path to folder containing images to evaluate perturbation on. 36 | * `im_list` : is the path to file containing list of all images to evaluate perturbation on. 37 | 38 | For more information, use `python test_uap.py --h` 39 | 40 | ## Important information 41 | 42 | As models used in works Universal Adverserial Perturbation and Fast-feature-fool were on tensorflow, these model took input of range 0-255. However, in Pytorch, the models have a different input range. The input is processed in the following fashion: 43 | 44 | * First the input is scaled 0-1 rather than 0-255 45 | * Each channel is normalized using the channel mean and channel standard deviations. 46 | 47 | Using this information, we can find out the input range:
48 | ``` 49 | (Lowest = min(-Channel_mean/Channel_std),Highest = max((1-Channel_mean)/ Channel_std)) 50 | ``` 51 | From this we calculate the input range to be 4.765. The norm limits for the perturbations have been shifted accordingly. 52 | 53 | ## Future enhancements: 54 | 55 | * The batch deepfool has to be made more efficient. Mechanism such that in each iteration, forward pass is performed only for images in batch which have not yet been fooled has to be added. 56 | * More results for the various nets (ResNet152, VGG19, etc.) 57 | * Provide UAPs thorugh [foolbox](https://github.com/bethgelab/foolbox). 58 | 59 | 60 | 61 | ## Acknowlegdement 62 | 63 | I would like to thank : 64 | 65 | * [Mopuri Reddy](https://github.com/mopurikreddy) ,[Utsav Garg](https://github.com/utsavgarg)and [EPFL LTS4](https://github.com/LTS4) for finding out this interesting phenomena. 66 | 67 | Also, a big thanks to [Video Analytics Lab](http://val.serc.iisc.ernet.in/valweb/). 68 | 69 | -------------------------------------------------------------------------------- /test_uap.py: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | import utils 3 | import torch.backends.cudnn as cudnn 4 | cudnn.enabled = False 5 | ############################################################## 6 | from docopt import docopt 7 | import time 8 | import torch 9 | import torch.optim as optim 10 | 11 | docstr = """Test Universal Adverserial Perturbation for Image Classification models trained in pytorch. 12 | 13 | Usage: 14 | test_uap.py [options] 15 | test_uap.py (-h | --help) 16 | test_uap.py --version 17 | 18 | Options: 19 | -h --help Show this screen. 20 | --version Show version. 21 | --batch_size= batch_size for processing while forming UAP in gpu[default: 100] 22 | --gpu= Which GPU to use[default: 3] 23 | """ 24 | 25 | if __name__ == '__main__': 26 | start_time = time.time() 27 | args = docopt(docstr, version='v1.0') 28 | torch.cuda.set_device(int(args['--gpu'])) 29 | batch_size = int(args['--batch_size']) 30 | 31 | net = utils.get_model(args['']) 32 | location_img = args[''] 33 | img_list = args[''] 34 | 35 | file = open(img_list) 36 | img_names = [] 37 | for f in file: 38 | img_names.append(f.split(' ')[0]) 39 | img_names = [location_img +x for x in img_names] 40 | st = time.time() 41 | v = torch.load(args['']) 42 | v = torch.autograd.Variable(v.cuda()) 43 | _,_ = utils.get_fooling_rate(img_names,batch_size,v,net) 44 | 45 | print('Total time: ' ,time.time()-st) 46 | -------------------------------------------------------------------------------- /utils.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | import torch.nn.functional as F 3 | import torchvision 4 | import torchvision.transforms as transforms 5 | import numpy as np 6 | import matplotlib.pyplot as plt 7 | import torch 8 | import torch.optim as optim 9 | import torch.utils.data as data_utils 10 | from torch.autograd import Variable 11 | from torch.autograd.gradcheck import zero_gradients 12 | import math 13 | from PIL import Image 14 | import torchvision.models as models 15 | import sys 16 | sys.path.insert(0,'DeepFool/Python/') 17 | from deepfool import deepfool 18 | import random 19 | import time 20 | 21 | def proj_lp(v, xi, p): 22 | 23 | # Project on the lp ball centered at 0 and of radius xi 24 | 25 | 26 | if p ==np.inf: 27 | v = torch.clamp(v,-xi,xi) 28 | else: 29 | v = v * min(1, xi/(torch.norm(v,p)+0.00001)) 30 | return v 31 | 32 | def data_input_init(xi): 33 | mean = [ 0.485, 0.456, 0.406 ] 34 | std = [ 0.229, 0.224, 0.225 ] 35 | tf = transforms.Compose([ 36 | transforms.Scale(256), 37 | transforms.CenterCrop(224), 38 | transforms.ToTensor(), 39 | transforms.Normalize(mean = mean, 40 | std = std)]) 41 | 42 | v = (torch.rand(1,3,224,224).cuda()-0.5)*2*xi 43 | return (mean,std,tf,v) 44 | 45 | def batch_deepfool(cur_img, net, num_classes=10, overshoot=0.02, max_iter=50,t_p=0.25): 46 | 47 | """ 48 | :param image: Image of size HxWx3 49 | :param net: network (input: images, output: values of activation **BEFORE** softmax). 50 | :param num_classes: num_classes (limits the number of classes to test against, by default = 10) 51 | :param overshoot: used as a termination criterion to prevent vanishing updates (default = 0.02). 52 | :param max_iter: maximum number of iterations for deepfool (default = 50) 53 | :param t_p: truth perentage, for how many flipped labels in a batch.(default = 0.25) 54 | :return: minimal perturbation that fools the classifier, number of iterations that it required, new estimated_label and perturbed image 55 | """ 56 | f_image = net.forward(cur_img) 57 | batch_size = cur_img.size(0) 58 | I = torch.sort(f_image,1)[1].data 59 | nv_idx = torch.range(I.size(1)-1, 0, -1).long().cuda() 60 | I = I.index_select(1, nv_idx) 61 | 62 | I = I[:,0:num_classes] 63 | label = I[:,0] 64 | 65 | input_shape = cur_img.size() 66 | pert_image = torch.autograd.Variable(cur_img.data,requires_grad = True) 67 | 68 | w = torch.zeros(input_shape).cuda() 69 | r_tot = torch.zeros(input_shape).cuda() 70 | pert = torch.FloatTensor((np.inf,)*batch_size).cuda() 71 | 72 | loop_i = 0 73 | 74 | x = pert_image 75 | fs = net.forward(x) 76 | 77 | 78 | fs_list = [fs[i,I[i,k]] for k in range(num_classes) for i in range(batch_size)] 79 | k_i = label 80 | truth_percent = torch.sum(torch.eq(k_i,label))/float(batch_size) 81 | 82 | while truth_percent>t_p and loop_i < max_iter: 83 | 84 | truth_guards = torch.eq(k_i,label) 85 | index_truth = [i for i in range(batch_size) if truth_guards[i] == 1] 86 | 87 | fs_backer = [fs[i,I[i,0]] for i in index_truth] 88 | fs_backer = torch.sum(torch.stack(tuple(fs_backer),0)) 89 | fs_backer.backward(retain_variables=True) 90 | 91 | grad_orig = torch.Tensor(x.grad.data.cpu()).cuda() 92 | 93 | for k in range(1, num_classes): 94 | zero_gradients(x) 95 | fs_backer = [fs[i,I[i,k]] for i in index_truth] 96 | fs_backer = torch.sum(torch.stack(tuple(fs_backer),0)) 97 | fs_backer.backward(retain_variables=True) 98 | cur_grad = torch.Tensor(x.grad.data.cpu()).cuda() 99 | 100 | # set new w_k and new f_k 101 | # set new w_k and new f_k 102 | r_i = torch.zeros(input_shape).cuda() 103 | pert_k = torch.zeros(batch_size).cuda() 104 | f_k = [0]*batch_size 105 | f_k_batch = [0]*batch_size 106 | w_k = cur_grad - grad_orig 107 | w_k_batch = [0]*batch_size 108 | for i in index_truth: 109 | f_k[i] = fs[i,I[i,k]] -fs[i,I[i,0]] 110 | f_k_batch[i] = torch.abs(f_k[i].data) 111 | w_k_batch[i] = torch.norm(w_k[i]) + 0.000001 112 | pert_k[i] = (f_k_batch[i]/w_k_batch[i])[0] 113 | if pert_k[i] <= pert[i]: 114 | pert[i] = pert_k[i] 115 | w[i] = w_k[i] 116 | r_i[i] = pert[i]*w[i]/w_k_batch[i] 117 | 118 | r_tot = r_tot + r_i 119 | pert_image =cur_img.data + (1+overshoot)*r_tot 120 | x = Variable(pert_image, requires_grad=True) 121 | fs = net.forward(x) 122 | k_i = torch.sort(fs,1)[1].data 123 | nv_idx = torch.range(k_i.size(1)-1, 0, -1).long().cuda() 124 | k_i = k_i.index_select(1, nv_idx) 125 | k_i = k_i[:,0] 126 | truth_percent = torch.sum(torch.eq(k_i,label))/float(batch_size) 127 | loop_i += 1 128 | 129 | print(loop_i, truth_percent) 130 | r_tot = (1+overshoot)*r_tot 131 | 132 | return torch.mean(r_tot,0), loop_i, label, k_i, pert_image 133 | 134 | def universal_perturbation_data_dependant(data_list, model, xi=10, delta=0.2, max_iter_uni = 10, p=np.inf, num_classes=10, overshoot=0.02, max_iter_df=10,init_batch_size = 1,t_p = 0.2): 135 | """ 136 | :data_list: list of image names 137 | :model: the target network 138 | :param xi: controls the l_p magnitude of the perturbation 139 | :param delta: controls the desired fooling rate (default = 80% fooling rate) 140 | :param max_iter_uni: optional other termination criterion (maximum number of iteration, default = 10,000) 141 | :param p: norm to be used (default = np.inf) 142 | :param num_classes: For deepfool: num_classes (limits the number of classes to test against, by default = 10) 143 | :param overshoot: For deepfool: used as a termination criterion to prevent vanishing updates (default = 0.02). 144 | :param max_iter_df:For deepfool: maximum number of iterations for deepfool (default = 10) 145 | :param t_p:For deepfool: truth perentage, for how many flipped labels in a batch.(default = 0.2) 146 | :batch_size: batch size to use for testing 147 | 148 | :return: the universal perturbation. 149 | """ 150 | time_start = time.time() 151 | mean, std,tf,_ = data_input_init(xi) 152 | v = torch.autograd.Variable(torch.zeros(init_batch_size,3,224,224).cuda(),requires_grad=True) 153 | 154 | fooling_rate = 0.0 155 | num_images = len(data_list) 156 | itr = 0 157 | batch_size = init_batch_size 158 | num_batches = np.int(np.ceil(np.float(num_images) / np.float(batch_size))) 159 | 160 | while fooling_rate < 1-delta and itr < max_iter_uni: 161 | random.shuffle(data_list) 162 | batch_size = init_batch_size 163 | print ('Starting pass number ', itr) 164 | # Go through the data set and compute the perturbation increments sequentially 165 | for k in range(0, num_batches): 166 | cur_img = torch.zeros(batch_size,3,224,224) 167 | data_inp = data_list[k*batch_size:min((k+1)*batch_size,len(data_list))] 168 | for i,name in enumerate(data_inp): 169 | im_orig = Image.open(name) 170 | cur_img[i] = tf(im_orig) 171 | cur_img = torch.autograd.Variable(cur_img).cuda() 172 | batch_size = cur_img.size(0) 173 | true_labels = np.argmax(model(cur_img).cpu().data.numpy(),1).astype(int) 174 | pert_labels = np.argmax(model(cur_img+torch.stack((v[0],)*batch_size,0)).cpu().data.numpy(),1).astype(int) 175 | cor_stat = np.sum(true_labels==pert_labels) 176 | 177 | if (cor_stat/float(batch_size)) > 0: 178 | dr, iter, _, _, _ = deepfool((cur_img+torch.stack((v[0],)*batch_size,0)).data[0], model,num_classes= num_classes, 179 | overshoot= overshoot,max_iter= max_iter_df) 180 | # dr, iter, _, _, _ =batch_deepfool(cur_img, model,num_classes= num_classes,overshoot= overshoot, 181 | # max_iter= max_iter_df) 182 | # print(np.norm(dr)) 183 | 184 | if iter < max_iter_df-1: 185 | v.data = v.data + torch.from_numpy(dr).cuda() 186 | # v.data = v.data + dr 187 | # Project on l_p ball 188 | v.data = proj_lp(v.data, xi, p) 189 | 190 | if(k%10 ==0): 191 | print('>> k = ', k, ', pass #', itr) 192 | print('time for this',time.time()-time_start) 193 | print('Norm of v',torch.norm(v)) 194 | batch_size = 100 195 | fooling_rate,model = get_fooling_rate(data_list,batch_size,v,model) 196 | itr = itr + 1 197 | 198 | return v 199 | 200 | def universal_perturbation_data_independant(data_list, model,delta=0.2, max_iter_uni = np.inf, xi=10/255.0, p=np.inf, num_classes=10, overshoot=0.02, max_iter_df=10,init_batch_size=50): 201 | 202 | """ 203 | :data_list: list of image names 204 | :model: the target network 205 | :param xi: controls the l_p magnitude of the perturbation 206 | :param delta: controls the desired fooling rate (default = 80% fooling rate) 207 | :param max_iter_uni: optional other termination criterion (maximum number of iteration, default = 10,000) 208 | :param p: norm to be used (default = np.inf) 209 | 210 | :return: the universal perturbation. 211 | """ 212 | mean, std,tf,init_v = data_input_init(xi) 213 | v = torch.autograd.Variable(init_v.cuda(),requires_grad=True) 214 | 215 | fooling_rate = 0.0 216 | num_images = len(data_list) 217 | itr = 0 218 | global main_value 219 | main_value = [0] 220 | main_value[0] =torch.autograd.Variable(torch.zeros(1)).cuda() 221 | 222 | batch_size = init_batch_size 223 | 224 | optimer = optim.Adam([v], lr = 0.1) 225 | 226 | num_batches = np.int(np.ceil(np.float(num_images) / np.float(batch_size))) 227 | model = set_hooks(model) 228 | 229 | while fooling_rate < 1-delta and itr < max_iter_uni: 230 | 231 | random.shuffle(data_list) 232 | print ('Starting pass number ', itr) 233 | 234 | # Go through the data set and compute the perturbation increments sequentially 235 | for k in range(0, num_batches): 236 | cur_img = torch.zeros(batch_size,3,224,224) 237 | M = min((k+1)*batch_size,num_images) 238 | for j in range(k*batch_size,M): 239 | im_orig = Image.open(data_list[j]) 240 | cur_img[j%batch_size] = tf(im_orig) 241 | cur_img = torch.autograd.Variable(cur_img).cuda() 242 | 243 | optimer.zero_grad() 244 | out = model(cur_img+torch.stack((v[0],)*batch_size,0)) 245 | loss = main_value[0] 246 | 247 | loss.backward() 248 | optimer.step() 249 | main_value[0] = torch.autograd.Variable(torch.zeros(1)).cuda() 250 | v.data = proj_lp(v.data, xi, p) 251 | if k%6 == 0 and k!=0: 252 | v.data = torch.div(v.data,2.0) 253 | print('Current k',k,'scaled v. norm is ',torch.norm(v.data)) 254 | 255 | batch_size = 100 256 | fooling_rate,model = get_fooling_rate(data_list,batch_size,v,model) 257 | itr+=1 258 | return v 259 | 260 | def get_fooling_rate(data_list,batch_size,v,model): 261 | """ 262 | :data_list: list of image names 263 | :batch_size: batch size to use for testing 264 | :model: the target network 265 | """ 266 | # Perturb the dataset with computed perturbation 267 | tf = data_input_init(0)[2] 268 | num_images = len(data_list) 269 | est_labels_orig = np.zeros((num_images)) 270 | est_labels_pert = np.zeros((num_images)) 271 | 272 | batch_size = 100 273 | num_batches = np.int(np.ceil(np.float(num_images) / np.float(batch_size))) 274 | # Compute the estimated labels in batches 275 | for ii in range(0, num_batches): 276 | m = (ii * batch_size) 277 | M = min((ii+1)*batch_size, num_images) 278 | dataset = torch.zeros(M-m,3,224,224) 279 | dataset_perturbed =torch.zeros(M-m,3,224,224) 280 | for iter,name in enumerate(data_list[m:M]): 281 | im_orig = Image.open(name) 282 | if (im_orig.mode == 'RGB'): 283 | dataset[iter] = tf(im_orig) 284 | dataset_perturbed[iter] = tf(im_orig).cuda()+ v[0].data 285 | else: 286 | im_orig = torch.squeeze(torch.stack((tf(im_orig),)*3,0),1) 287 | dataset[iter] = im_orig 288 | dataset_perturbed[iter] = im_orig.cuda()+ v[0].data 289 | dataset_var = torch.autograd.Variable(dataset,volatile = True).cuda() 290 | dataset_perturbed_var = torch.autograd.Variable(dataset_perturbed,volatile = True).cuda() 291 | 292 | est_labels_orig[m:M] = np.argmax(model(dataset_var).data.cpu().numpy(), axis=1).flatten() 293 | est_labels_pert[m:M] = np.argmax(model(dataset_perturbed_var).data.cpu().numpy(), axis=1).flatten() 294 | if ii%10 ==0: 295 | print(ii,'batches done.') 296 | 297 | # Compute the fooling rate 298 | fooling_rate = float(np.sum(est_labels_pert != est_labels_orig) / float(num_images)) 299 | print('FOOLING RATE = ', fooling_rate) 300 | for param in model.parameters(): 301 | param.volatile = False 302 | param.requires_grad = False 303 | 304 | return fooling_rate,model 305 | 306 | def set_hooks(model): 307 | 308 | def get_norm(self, forward_input, forward_output): 309 | global main_value 310 | main_value[0] += -torch.log((torch.mean(torch.abs(forward_output)))) 311 | 312 | layers_to_opt = get_layers_to_opt(model.__class__.__name__) 313 | print(layers_to_opt,'Layers') 314 | for name,layer in model.named_modules(): 315 | if(name in layers_to_opt): 316 | print(name) 317 | layer.register_forward_hook(get_norm) 318 | return model 319 | 320 | def get_layers_to_opt(model): 321 | if model =='VGG': 322 | layers_to_opt = [1,3,6,8,11,13,15,18,20,22,25,27,29] 323 | layers_to_opt = ['features.'+str(x) for x in layers_to_opt] 324 | elif 'ResNet' in model: 325 | layers_to_opt = ['conv1','layer1','layer2','layer3','layer4'] 326 | return layers_to_opt 327 | 328 | def get_model(model): 329 | if model == 'vgg16': 330 | net = models.vgg16(pretrained=True) 331 | elif model =='resnet18': 332 | net = models.resnet18(pretrained=True) 333 | 334 | for params in net.parameters(): 335 | requires_grad = False 336 | net.eval() 337 | net.cuda() 338 | return net 339 | --------------------------------------------------------------------------------