bat.attacks.bandits_attack
1import os 2import gc 3import numpy as np 4from tqdm import tqdm 5 6import concurrent.futures 7 8SCALE = 255 9PREPROCESS = lambda x: x 10 11### 12# Different optimization steps 13# All take the form of func(x, g, lr) 14# eg: exponentiated gradients 15# l2/linf: projected gradient descent 16### 17 18def eg_step(x, g, lr): 19 real_x = (x + 1) / 2 # from [-1, 1] to [0, 1] 20 pos = real_x * np.exp(lr * g) 21 neg = (1 - real_x) * np.exp(-lr * g) 22 new_x = pos / (pos + neg) 23 return new_x * 2 - 1 24 25def linf_step(x, g, lr): 26 return x + lr * np.sign(g) 27 28# def l2_prior_step(x, g, lr): 29# new_x = x + lr * g / np.linalg.norm(g) 30# norm_new_x = np.linalg.norm(new_x) 31# norm_mask = (norm_new_x < 1.0).float() 32# return new_x * norm_mask + (1 - norm_mask) * new_x / norm_new_x 33 34# def gd_prior_step(x, g, lr): 35# return x + lr * g 36 37# def l2_image_step(x, g, lr): 38# return x + lr * g / np.linalg.norm(g) 39 40def cross_entropy(y_pred, y_true): 41 """ 42 y_pred is the softmax output of the model 43 y_true is labels (num_examples x 1) 44 Note that y is not one-hot encoded vector. 45 It can be computed as y.argmax(axis=1) from one-hot encoded vectors of labels if required. 46 """ 47 48 y_true = np.array(y_true) 49 m = y_true.shape[0] 50 51 # We dont need to compute softmax, since y_pred is already softmaxed 52 # from scipy.special import softmax 53 # p = softmax(y_pred) 54 p = y_pred 55 56 # We use multidimensional array indexing to extract 57 # softmax probability of the correct label for each sample. 58 # Refer to https://docs.scipy.org/doc/numpy/user/basics.indexing.html#indexing-multi-dimensional-arrays for understanding multidimensional array indexing. 59 log_likelihood = -np.log(p[range(m), y_true]) 60 61 # No reduction 62 # loss = np.sum(log_likelihood) / m 63 64 return log_likelihood 65 66class BanditsAttack(): 67 def __init__(self, classifier): 68 """ 69 Create a class: `BanditAttack` instance. 70 - classifier: model to attack 71 """ 72 self.classifier = classifier 73 74 def init(self, x): 75 """ 76 Initialize the attack. 77 """ 78 y_pred = self.classifier.predict(PREPROCESS(x)) 79 80 x_adv = x.copy() 81 82 priors = [] 83 for i in range(len(x)): 84 h, w, c = x[i].shape 85 priors.append(np.zeros((h, w, c))) 86 87 return x_adv, y_pred, priors 88 89 def step(self, x, x_adv, y, priors, epsilon, fd_eta, image_lr, online_lr, exploration): 90 91 x_query_1 = [] 92 x_query_2 = [] 93 94 exp_noises = [] 95 96 for i, img in enumerate(x_adv): 97 ## Updating the prior: 98 # Create noise for exporation, estimate the gradient, and take a PGD step 99 h, w, c = img.shape 100 dim = h * w * c 101 exp_noise = exploration * np.random.normal(0.0, 1.0, size = priors[i].shape) / (dim ** 0.5) * SCALE 102 103 # Query deltas for finite difference estimator 104 q1 = priors[i] + exp_noise 105 q2 = priors[i] - exp_noise 106 107 norm_q1 = np.linalg.norm(q1) 108 norm_q2 = np.linalg.norm(q2) 109 110 # The original paper did not clip the noise 111 # x_query_1.append(img + fd_eta * (q1 / (1e-8 if norm_q1 == 0.0 else norm_q1))) 112 # x_query_2.append(img + fd_eta * (q2 / (1e-8 if norm_q2 == 0.0 else norm_q2))) 113 114 x_query_1.append(np.uint8(np.clip(img + fd_eta * (q1 / (1e-8 if norm_q1 == 0.0 else norm_q1)), 0, 1.0 * SCALE))) 115 x_query_2.append(np.uint8(np.clip(img + fd_eta * (q2 / (1e-8 if norm_q2 == 0.0 else norm_q2)), 0, 1.0 * SCALE))) 116 117 exp_noises.append(exp_noise) 118 119 # Loss points for finite difference estimator 120 l1 = cross_entropy(self.classifier.predict(PREPROCESS(x_query_1)), y) # L(prior + c*noise) 121 l2 = cross_entropy(self.classifier.predict(PREPROCESS(x_query_2)), y) # L(prior - c*noise) 122 123 for i, img in enumerate(x_adv): 124 # Finite differences estimate of directional derivative 125 est_deriv = (l1[i] - l2[i]) / (fd_eta * exploration) 126 # 2-query gradient estimate 127 est_grad = est_deriv * exp_noises[i] 128 # Update the prior with the estimated gradient 129 130 priors[i] = eg_step(priors[i], est_grad, online_lr) 131 132 ## Update the image: 133 # take a pgd step using the prior 134 img = linf_step(img, priors[i], image_lr) 135 img = x[i] + np.clip(img - x[i], -epsilon, epsilon) 136 img = np.clip(img, 0, 1 * SCALE) 137 138 x_adv[i] = img 139 140 return x_adv, priors 141 142 def batch(self, x, x_adv, y, priors, epsilon, fd_eta, image_lr, online_lr, exploration, concurrency): 143 144 assert len(x) == len(x_adv) == len(y) == len(priors) == 1 145 146 noises_new = [] 147 priors_new = [] 148 149 with concurrent.futures.ThreadPoolExecutor() as executor: 150 future_to_url = {executor.submit(self.step, x, x_adv, y, priors, epsilon, fd_eta, image_lr, online_lr, exploration): j for j in range(0, concurrency)} 151 for future in concurrent.futures.as_completed(future_to_url): 152 j = future_to_url[future] 153 try: 154 xn, pn = future.result() 155 noises_new.append(xn[0] - x_adv[0]) 156 priors_new.append(pn[0] - priors[0]) 157 except Exception as exc: 158 print('Task %r generated an exception: %s' % (j, exc)) 159 else: 160 pass 161 162 for i in range(0, len(noises_new)): 163 x_adv[0] = x_adv[0] + noises_new[i] / concurrency 164 priors[0] = priors[0] + priors_new[i] / concurrency 165 166 x_adv[0] = x_adv[0] + np.clip(x_adv[0] - x[0], -epsilon, epsilon) 167 x_adv[0] = np.clip(x_adv[0], 0, 1 * SCALE) 168 169 return x_adv, priors 170 171 def attack(self, x, y, epsilon=0.05, fd_eta=0.1, image_lr=0.01, online_lr=100, exploration=1.0, max_it=10000, concurrency=1): 172 """ 173 Initiate the attack. 174 175 - x: input data 176 - y: input labels 177 - epsilon: perturbation on each pixel 178 - max_it: number of iterations 179 """ 180 181 n_targets = 0 182 if type(x) == list: 183 n_targets = len(x) 184 elif type(x) == np.ndarray: 185 n_targets = x.shape[0] 186 else: 187 raise ValueError('Input type not supported...') 188 189 assert n_targets > 0 190 191 x_adv, y_pred, priors = self.init(x) 192 193 # Continue query count 194 y_pred_classes = np.argmax(y_pred, axis=1) 195 correct_classified_mask = (y_pred_classes == y) 196 not_dones_mask = correct_classified_mask.copy() 197 198 correct_classified = [i for i, v in enumerate(correct_classified_mask) if v] 199 200 print('Clean accuracy: {:.2%}'.format(np.mean(correct_classified_mask))) 201 202 if np.mean(correct_classified_mask) == 0: 203 print('No clean examples classified correctly. Aborting...') 204 n_queries = np.ones(len(x)) # ones because we have already used 1 query 205 206 mean_nq, mean_nq_ae = np.mean(n_queries), np.mean(n_queries) 207 208 return x_adv 209 210 if n_targets > 1: 211 # Horizontally Distributed Attack 212 pbar = tqdm(range(0, max_it), desc="Distributed Bandits Attack (Horizontal)") 213 else: 214 # Vertically Distributed Attack 215 pbar = tqdm(range(0, max_it, concurrency), desc="Distributed Bandits Attack (Vertical)") 216 217 total_queries = np.zeros(len(x)) 218 219 for i_iter in pbar: 220 221 not_dones = [i for i, v in enumerate(not_dones_mask) if v] 222 223 x_curr = [x[idx] for idx in not_dones] 224 x_adv_curr = [x_adv[idx] for idx in not_dones] 225 y_curr = [y[idx] for idx in not_dones] 226 prior_curr = [priors[idx] for idx in not_dones] 227 228 if n_targets > 1: 229 # Horizontally Distributed Attack 230 x_adv_curr, prior_curr = self.step(x_curr, x_adv_curr, y_curr, prior_curr, epsilon * SCALE, fd_eta * SCALE, image_lr * SCALE, online_lr, exploration) 231 else: 232 # Vertically Distributed Attack 233 x_adv_curr, prior_curr = self.batch(x_curr, x_adv_curr, y_curr, prior_curr, epsilon * SCALE, fd_eta * SCALE, image_lr * SCALE, online_lr, exploration, concurrency) 234 235 y_pred_curr = self.classifier.predict(PREPROCESS(x_adv_curr)) 236 y_curr = np.argmax(y_pred_curr, axis=1) 237 238 for i in range(len(not_dones)): 239 x_adv[not_dones[i]] = x_adv_curr[i] 240 priors[not_dones[i]] = prior_curr[i] 241 y_pred[not_dones[i]] = y_pred_curr[i] 242 y_pred_classes[not_dones[i]] = y_curr[i] 243 244 # Logging stuff 245 total_queries += 3 * not_dones_mask * concurrency 246 247 not_dones_mask = not_dones_mask * (y_pred_classes == y) 248 249 # max_curr_queries = total_queries.max() 250 251 success_mask = correct_classified_mask * (1 - not_dones_mask) 252 num_success = success_mask.sum() 253 current_success_rate = (num_success / correct_classified_mask.sum()) 254 255 if num_success == 0: 256 success_queries = -1 257 else: 258 success_queries = ((success_mask * total_queries).sum() / num_success) 259 260 pbar.set_postfix({'Total Queries': total_queries.sum(), 'Mean Higest Prediction': y_pred[correct_classified].max(axis=1).mean(), 'Attack Success Rate': current_success_rate, 'Avg Queries': success_queries}) 261 262 acc = not_dones_mask.sum() / correct_classified_mask.sum() 263 mean_nq, mean_nq_ae = np.mean(total_queries), np.mean(total_queries *success_mask) 264 265 # Early break 266 if current_success_rate == 1.0: 267 break 268 269 gc.collect() 270 271 return x_adv
SCALE =
255
def
PREPROCESS(x):
10PREPROCESS = lambda x: x
def
eg_step(x, g, lr):
def
linf_step(x, g, lr):
def
cross_entropy(y_pred, y_true):
41def cross_entropy(y_pred, y_true): 42 """ 43 y_pred is the softmax output of the model 44 y_true is labels (num_examples x 1) 45 Note that y is not one-hot encoded vector. 46 It can be computed as y.argmax(axis=1) from one-hot encoded vectors of labels if required. 47 """ 48 49 y_true = np.array(y_true) 50 m = y_true.shape[0] 51 52 # We dont need to compute softmax, since y_pred is already softmaxed 53 # from scipy.special import softmax 54 # p = softmax(y_pred) 55 p = y_pred 56 57 # We use multidimensional array indexing to extract 58 # softmax probability of the correct label for each sample. 59 # Refer to https://docs.scipy.org/doc/numpy/user/basics.indexing.html#indexing-multi-dimensional-arrays for understanding multidimensional array indexing. 60 log_likelihood = -np.log(p[range(m), y_true]) 61 62 # No reduction 63 # loss = np.sum(log_likelihood) / m 64 65 return log_likelihood
y_pred is the softmax output of the model y_true is labels (num_examples x 1) Note that y is not one-hot encoded vector. It can be computed as y.argmax(axis=1) from one-hot encoded vectors of labels if required.
class
BanditsAttack:
67class BanditsAttack(): 68 def __init__(self, classifier): 69 """ 70 Create a class: `BanditAttack` instance. 71 - classifier: model to attack 72 """ 73 self.classifier = classifier 74 75 def init(self, x): 76 """ 77 Initialize the attack. 78 """ 79 y_pred = self.classifier.predict(PREPROCESS(x)) 80 81 x_adv = x.copy() 82 83 priors = [] 84 for i in range(len(x)): 85 h, w, c = x[i].shape 86 priors.append(np.zeros((h, w, c))) 87 88 return x_adv, y_pred, priors 89 90 def step(self, x, x_adv, y, priors, epsilon, fd_eta, image_lr, online_lr, exploration): 91 92 x_query_1 = [] 93 x_query_2 = [] 94 95 exp_noises = [] 96 97 for i, img in enumerate(x_adv): 98 ## Updating the prior: 99 # Create noise for exporation, estimate the gradient, and take a PGD step 100 h, w, c = img.shape 101 dim = h * w * c 102 exp_noise = exploration * np.random.normal(0.0, 1.0, size = priors[i].shape) / (dim ** 0.5) * SCALE 103 104 # Query deltas for finite difference estimator 105 q1 = priors[i] + exp_noise 106 q2 = priors[i] - exp_noise 107 108 norm_q1 = np.linalg.norm(q1) 109 norm_q2 = np.linalg.norm(q2) 110 111 # The original paper did not clip the noise 112 # x_query_1.append(img + fd_eta * (q1 / (1e-8 if norm_q1 == 0.0 else norm_q1))) 113 # x_query_2.append(img + fd_eta * (q2 / (1e-8 if norm_q2 == 0.0 else norm_q2))) 114 115 x_query_1.append(np.uint8(np.clip(img + fd_eta * (q1 / (1e-8 if norm_q1 == 0.0 else norm_q1)), 0, 1.0 * SCALE))) 116 x_query_2.append(np.uint8(np.clip(img + fd_eta * (q2 / (1e-8 if norm_q2 == 0.0 else norm_q2)), 0, 1.0 * SCALE))) 117 118 exp_noises.append(exp_noise) 119 120 # Loss points for finite difference estimator 121 l1 = cross_entropy(self.classifier.predict(PREPROCESS(x_query_1)), y) # L(prior + c*noise) 122 l2 = cross_entropy(self.classifier.predict(PREPROCESS(x_query_2)), y) # L(prior - c*noise) 123 124 for i, img in enumerate(x_adv): 125 # Finite differences estimate of directional derivative 126 est_deriv = (l1[i] - l2[i]) / (fd_eta * exploration) 127 # 2-query gradient estimate 128 est_grad = est_deriv * exp_noises[i] 129 # Update the prior with the estimated gradient 130 131 priors[i] = eg_step(priors[i], est_grad, online_lr) 132 133 ## Update the image: 134 # take a pgd step using the prior 135 img = linf_step(img, priors[i], image_lr) 136 img = x[i] + np.clip(img - x[i], -epsilon, epsilon) 137 img = np.clip(img, 0, 1 * SCALE) 138 139 x_adv[i] = img 140 141 return x_adv, priors 142 143 def batch(self, x, x_adv, y, priors, epsilon, fd_eta, image_lr, online_lr, exploration, concurrency): 144 145 assert len(x) == len(x_adv) == len(y) == len(priors) == 1 146 147 noises_new = [] 148 priors_new = [] 149 150 with concurrent.futures.ThreadPoolExecutor() as executor: 151 future_to_url = {executor.submit(self.step, x, x_adv, y, priors, epsilon, fd_eta, image_lr, online_lr, exploration): j for j in range(0, concurrency)} 152 for future in concurrent.futures.as_completed(future_to_url): 153 j = future_to_url[future] 154 try: 155 xn, pn = future.result() 156 noises_new.append(xn[0] - x_adv[0]) 157 priors_new.append(pn[0] - priors[0]) 158 except Exception as exc: 159 print('Task %r generated an exception: %s' % (j, exc)) 160 else: 161 pass 162 163 for i in range(0, len(noises_new)): 164 x_adv[0] = x_adv[0] + noises_new[i] / concurrency 165 priors[0] = priors[0] + priors_new[i] / concurrency 166 167 x_adv[0] = x_adv[0] + np.clip(x_adv[0] - x[0], -epsilon, epsilon) 168 x_adv[0] = np.clip(x_adv[0], 0, 1 * SCALE) 169 170 return x_adv, priors 171 172 def attack(self, x, y, epsilon=0.05, fd_eta=0.1, image_lr=0.01, online_lr=100, exploration=1.0, max_it=10000, concurrency=1): 173 """ 174 Initiate the attack. 175 176 - x: input data 177 - y: input labels 178 - epsilon: perturbation on each pixel 179 - max_it: number of iterations 180 """ 181 182 n_targets = 0 183 if type(x) == list: 184 n_targets = len(x) 185 elif type(x) == np.ndarray: 186 n_targets = x.shape[0] 187 else: 188 raise ValueError('Input type not supported...') 189 190 assert n_targets > 0 191 192 x_adv, y_pred, priors = self.init(x) 193 194 # Continue query count 195 y_pred_classes = np.argmax(y_pred, axis=1) 196 correct_classified_mask = (y_pred_classes == y) 197 not_dones_mask = correct_classified_mask.copy() 198 199 correct_classified = [i for i, v in enumerate(correct_classified_mask) if v] 200 201 print('Clean accuracy: {:.2%}'.format(np.mean(correct_classified_mask))) 202 203 if np.mean(correct_classified_mask) == 0: 204 print('No clean examples classified correctly. Aborting...') 205 n_queries = np.ones(len(x)) # ones because we have already used 1 query 206 207 mean_nq, mean_nq_ae = np.mean(n_queries), np.mean(n_queries) 208 209 return x_adv 210 211 if n_targets > 1: 212 # Horizontally Distributed Attack 213 pbar = tqdm(range(0, max_it), desc="Distributed Bandits Attack (Horizontal)") 214 else: 215 # Vertically Distributed Attack 216 pbar = tqdm(range(0, max_it, concurrency), desc="Distributed Bandits Attack (Vertical)") 217 218 total_queries = np.zeros(len(x)) 219 220 for i_iter in pbar: 221 222 not_dones = [i for i, v in enumerate(not_dones_mask) if v] 223 224 x_curr = [x[idx] for idx in not_dones] 225 x_adv_curr = [x_adv[idx] for idx in not_dones] 226 y_curr = [y[idx] for idx in not_dones] 227 prior_curr = [priors[idx] for idx in not_dones] 228 229 if n_targets > 1: 230 # Horizontally Distributed Attack 231 x_adv_curr, prior_curr = self.step(x_curr, x_adv_curr, y_curr, prior_curr, epsilon * SCALE, fd_eta * SCALE, image_lr * SCALE, online_lr, exploration) 232 else: 233 # Vertically Distributed Attack 234 x_adv_curr, prior_curr = self.batch(x_curr, x_adv_curr, y_curr, prior_curr, epsilon * SCALE, fd_eta * SCALE, image_lr * SCALE, online_lr, exploration, concurrency) 235 236 y_pred_curr = self.classifier.predict(PREPROCESS(x_adv_curr)) 237 y_curr = np.argmax(y_pred_curr, axis=1) 238 239 for i in range(len(not_dones)): 240 x_adv[not_dones[i]] = x_adv_curr[i] 241 priors[not_dones[i]] = prior_curr[i] 242 y_pred[not_dones[i]] = y_pred_curr[i] 243 y_pred_classes[not_dones[i]] = y_curr[i] 244 245 # Logging stuff 246 total_queries += 3 * not_dones_mask * concurrency 247 248 not_dones_mask = not_dones_mask * (y_pred_classes == y) 249 250 # max_curr_queries = total_queries.max() 251 252 success_mask = correct_classified_mask * (1 - not_dones_mask) 253 num_success = success_mask.sum() 254 current_success_rate = (num_success / correct_classified_mask.sum()) 255 256 if num_success == 0: 257 success_queries = -1 258 else: 259 success_queries = ((success_mask * total_queries).sum() / num_success) 260 261 pbar.set_postfix({'Total Queries': total_queries.sum(), 'Mean Higest Prediction': y_pred[correct_classified].max(axis=1).mean(), 'Attack Success Rate': current_success_rate, 'Avg Queries': success_queries}) 262 263 acc = not_dones_mask.sum() / correct_classified_mask.sum() 264 mean_nq, mean_nq_ae = np.mean(total_queries), np.mean(total_queries *success_mask) 265 266 # Early break 267 if current_success_rate == 1.0: 268 break 269 270 gc.collect() 271 272 return x_adv
BanditsAttack(classifier)
68 def __init__(self, classifier): 69 """ 70 Create a class: `BanditAttack` instance. 71 - classifier: model to attack 72 """ 73 self.classifier = classifier
Create a class: BanditAttack
instance.
- classifier: model to attack
def
init(self, x):
75 def init(self, x): 76 """ 77 Initialize the attack. 78 """ 79 y_pred = self.classifier.predict(PREPROCESS(x)) 80 81 x_adv = x.copy() 82 83 priors = [] 84 for i in range(len(x)): 85 h, w, c = x[i].shape 86 priors.append(np.zeros((h, w, c))) 87 88 return x_adv, y_pred, priors
Initialize the attack.
def
step( self, x, x_adv, y, priors, epsilon, fd_eta, image_lr, online_lr, exploration):
90 def step(self, x, x_adv, y, priors, epsilon, fd_eta, image_lr, online_lr, exploration): 91 92 x_query_1 = [] 93 x_query_2 = [] 94 95 exp_noises = [] 96 97 for i, img in enumerate(x_adv): 98 ## Updating the prior: 99 # Create noise for exporation, estimate the gradient, and take a PGD step 100 h, w, c = img.shape 101 dim = h * w * c 102 exp_noise = exploration * np.random.normal(0.0, 1.0, size = priors[i].shape) / (dim ** 0.5) * SCALE 103 104 # Query deltas for finite difference estimator 105 q1 = priors[i] + exp_noise 106 q2 = priors[i] - exp_noise 107 108 norm_q1 = np.linalg.norm(q1) 109 norm_q2 = np.linalg.norm(q2) 110 111 # The original paper did not clip the noise 112 # x_query_1.append(img + fd_eta * (q1 / (1e-8 if norm_q1 == 0.0 else norm_q1))) 113 # x_query_2.append(img + fd_eta * (q2 / (1e-8 if norm_q2 == 0.0 else norm_q2))) 114 115 x_query_1.append(np.uint8(np.clip(img + fd_eta * (q1 / (1e-8 if norm_q1 == 0.0 else norm_q1)), 0, 1.0 * SCALE))) 116 x_query_2.append(np.uint8(np.clip(img + fd_eta * (q2 / (1e-8 if norm_q2 == 0.0 else norm_q2)), 0, 1.0 * SCALE))) 117 118 exp_noises.append(exp_noise) 119 120 # Loss points for finite difference estimator 121 l1 = cross_entropy(self.classifier.predict(PREPROCESS(x_query_1)), y) # L(prior + c*noise) 122 l2 = cross_entropy(self.classifier.predict(PREPROCESS(x_query_2)), y) # L(prior - c*noise) 123 124 for i, img in enumerate(x_adv): 125 # Finite differences estimate of directional derivative 126 est_deriv = (l1[i] - l2[i]) / (fd_eta * exploration) 127 # 2-query gradient estimate 128 est_grad = est_deriv * exp_noises[i] 129 # Update the prior with the estimated gradient 130 131 priors[i] = eg_step(priors[i], est_grad, online_lr) 132 133 ## Update the image: 134 # take a pgd step using the prior 135 img = linf_step(img, priors[i], image_lr) 136 img = x[i] + np.clip(img - x[i], -epsilon, epsilon) 137 img = np.clip(img, 0, 1 * SCALE) 138 139 x_adv[i] = img 140 141 return x_adv, priors
def
batch( self, x, x_adv, y, priors, epsilon, fd_eta, image_lr, online_lr, exploration, concurrency):
143 def batch(self, x, x_adv, y, priors, epsilon, fd_eta, image_lr, online_lr, exploration, concurrency): 144 145 assert len(x) == len(x_adv) == len(y) == len(priors) == 1 146 147 noises_new = [] 148 priors_new = [] 149 150 with concurrent.futures.ThreadPoolExecutor() as executor: 151 future_to_url = {executor.submit(self.step, x, x_adv, y, priors, epsilon, fd_eta, image_lr, online_lr, exploration): j for j in range(0, concurrency)} 152 for future in concurrent.futures.as_completed(future_to_url): 153 j = future_to_url[future] 154 try: 155 xn, pn = future.result() 156 noises_new.append(xn[0] - x_adv[0]) 157 priors_new.append(pn[0] - priors[0]) 158 except Exception as exc: 159 print('Task %r generated an exception: %s' % (j, exc)) 160 else: 161 pass 162 163 for i in range(0, len(noises_new)): 164 x_adv[0] = x_adv[0] + noises_new[i] / concurrency 165 priors[0] = priors[0] + priors_new[i] / concurrency 166 167 x_adv[0] = x_adv[0] + np.clip(x_adv[0] - x[0], -epsilon, epsilon) 168 x_adv[0] = np.clip(x_adv[0], 0, 1 * SCALE) 169 170 return x_adv, priors
def
attack( self, x, y, epsilon=0.05, fd_eta=0.1, image_lr=0.01, online_lr=100, exploration=1.0, max_it=10000, concurrency=1):
172 def attack(self, x, y, epsilon=0.05, fd_eta=0.1, image_lr=0.01, online_lr=100, exploration=1.0, max_it=10000, concurrency=1): 173 """ 174 Initiate the attack. 175 176 - x: input data 177 - y: input labels 178 - epsilon: perturbation on each pixel 179 - max_it: number of iterations 180 """ 181 182 n_targets = 0 183 if type(x) == list: 184 n_targets = len(x) 185 elif type(x) == np.ndarray: 186 n_targets = x.shape[0] 187 else: 188 raise ValueError('Input type not supported...') 189 190 assert n_targets > 0 191 192 x_adv, y_pred, priors = self.init(x) 193 194 # Continue query count 195 y_pred_classes = np.argmax(y_pred, axis=1) 196 correct_classified_mask = (y_pred_classes == y) 197 not_dones_mask = correct_classified_mask.copy() 198 199 correct_classified = [i for i, v in enumerate(correct_classified_mask) if v] 200 201 print('Clean accuracy: {:.2%}'.format(np.mean(correct_classified_mask))) 202 203 if np.mean(correct_classified_mask) == 0: 204 print('No clean examples classified correctly. Aborting...') 205 n_queries = np.ones(len(x)) # ones because we have already used 1 query 206 207 mean_nq, mean_nq_ae = np.mean(n_queries), np.mean(n_queries) 208 209 return x_adv 210 211 if n_targets > 1: 212 # Horizontally Distributed Attack 213 pbar = tqdm(range(0, max_it), desc="Distributed Bandits Attack (Horizontal)") 214 else: 215 # Vertically Distributed Attack 216 pbar = tqdm(range(0, max_it, concurrency), desc="Distributed Bandits Attack (Vertical)") 217 218 total_queries = np.zeros(len(x)) 219 220 for i_iter in pbar: 221 222 not_dones = [i for i, v in enumerate(not_dones_mask) if v] 223 224 x_curr = [x[idx] for idx in not_dones] 225 x_adv_curr = [x_adv[idx] for idx in not_dones] 226 y_curr = [y[idx] for idx in not_dones] 227 prior_curr = [priors[idx] for idx in not_dones] 228 229 if n_targets > 1: 230 # Horizontally Distributed Attack 231 x_adv_curr, prior_curr = self.step(x_curr, x_adv_curr, y_curr, prior_curr, epsilon * SCALE, fd_eta * SCALE, image_lr * SCALE, online_lr, exploration) 232 else: 233 # Vertically Distributed Attack 234 x_adv_curr, prior_curr = self.batch(x_curr, x_adv_curr, y_curr, prior_curr, epsilon * SCALE, fd_eta * SCALE, image_lr * SCALE, online_lr, exploration, concurrency) 235 236 y_pred_curr = self.classifier.predict(PREPROCESS(x_adv_curr)) 237 y_curr = np.argmax(y_pred_curr, axis=1) 238 239 for i in range(len(not_dones)): 240 x_adv[not_dones[i]] = x_adv_curr[i] 241 priors[not_dones[i]] = prior_curr[i] 242 y_pred[not_dones[i]] = y_pred_curr[i] 243 y_pred_classes[not_dones[i]] = y_curr[i] 244 245 # Logging stuff 246 total_queries += 3 * not_dones_mask * concurrency 247 248 not_dones_mask = not_dones_mask * (y_pred_classes == y) 249 250 # max_curr_queries = total_queries.max() 251 252 success_mask = correct_classified_mask * (1 - not_dones_mask) 253 num_success = success_mask.sum() 254 current_success_rate = (num_success / correct_classified_mask.sum()) 255 256 if num_success == 0: 257 success_queries = -1 258 else: 259 success_queries = ((success_mask * total_queries).sum() / num_success) 260 261 pbar.set_postfix({'Total Queries': total_queries.sum(), 'Mean Higest Prediction': y_pred[correct_classified].max(axis=1).mean(), 'Attack Success Rate': current_success_rate, 'Avg Queries': success_queries}) 262 263 acc = not_dones_mask.sum() / correct_classified_mask.sum() 264 mean_nq, mean_nq_ae = np.mean(total_queries), np.mean(total_queries *success_mask) 265 266 # Early break 267 if current_success_rate == 1.0: 268 break 269 270 gc.collect() 271 272 return x_adv
Initiate the attack.
- x: input data
- y: input labels
- epsilon: perturbation on each pixel
- max_it: number of iterations