def get_x0(x, is_sample=False): """ Helper function to randomly initialize the the inner maximizer algos randomize such that the functionality is preserved. Functionality is preserved by maintaining the features present in x :param x: training sample :param is_sample: flag to sample randomly from feasible area or return just x :return: randomly sampled feasible version of x """ if is_sample: # print("Original Number of Features:", x.sum()) rand_x = round_x(torch.rand(x.size()) - .49) rand_x = clip_tensor(rand_x) if x.is_cuda: rand_x = rand_x.cuda() # print("New Number of Features:", or_float_tensors(x, rand_x).sum()) return or_float_tensors(x, rand_x) else: return x
def rfgsm_k(x, y, model, loss_fct, k=25, epsilon=0.02, is_report_loss_diff=False, use_sample=False): """ FGSM^k with randomized rounding :param x: (tensor) feature vector :param y: :param model: nn model :param loss_fct: loss function :param k: num of steps :param epsilon: update value in each direction :param is_report_loss_diff: :param use_sample: :return: the adversarial version of x according to rfgsm_k (tensor) """ # some book-keeping if next(model.parameters()).is_cuda: x = x.cuda() y = y.cuda() y = Variable(y) # compute natural loss loss_natural = loss_fct(model(Variable(x)), y).data # initialize starting point x_next = get_x0(x, use_sample) # multi-step with gradients for t in range(k): # forward pass x_var = Variable(x_next, requires_grad=True) y_model = model(x_var) loss = loss_fct(y_model, y) # compute gradient grad_vars = torch.autograd.grad(loss.mean(), x_var) # find the next sample x_next = x_next + epsilon * torch.sign(grad_vars[0].data) # projection x_next = clip_tensor(x_next) # rounding step alpha = torch.rand(x_next.size()) if x_next.is_cuda: alpha = alpha.cuda() x_next = round_x(x_next, alpha=alpha) # feasible projection x_next = or_float_tensors(x_next, x) # compute adversarial loss loss_adv = loss_fct(model(Variable(x_next)), y).data if is_report_loss_diff: print( "Natural loss (%.4f) vs Adversarial loss (%.4f), Difference: (%.4f)" % (loss_natural.mean(), loss_adv.mean(), loss_adv.mean() - loss_natural.mean())) replace_flag = (loss_adv < loss_natural).unsqueeze(1).expand_as(x_next) x_next[replace_flag] = x[replace_flag] if x_next.is_cuda: x_next = x_next.cpu() return x_next
def topkextra(x, y, model, loss_fct, k=25, epsilon=0.02, alpha=0.5, is_report_loss_diff=False, use_sample=False): x_next = topk(x, y, model, loss_fct, k, epsilon, alpha, False, use_sample) # some book-keeping if next(model.parameters()).is_cuda: x = x.cuda() y = y.cuda() x_next = x_next.cuda() y = Variable(y) # compute natural loss y_model = model(Variable(x)) loss_natural = loss_fct(y_model, y).data for i in range(1): x_best = x_next.clone() y_model = model(Variable(x_next)) best_loss = loss_fct(y_model, y) factor = 2 * len(x) no_improve = 0 for n in range(k): # forward pass # x_old = x_next.clone() xn_var = Variable(x_next, requires_grad=True) y_model = model(xn_var) loss = loss_fct(y_model, y) # compute gradient grads = torch.autograd.grad(loss.mean(), xn_var)[0].data # topk signs = torch.gt(grads, 0).float() grads = (signs - x_next) * grads grads -= x * grads rand_vars = torch.rand(len(grads), len(grads[0])) if next(model.parameters()).is_cuda: rand_vars = rand_vars.cuda() grads = rand_vars * grads kvals, kidx = grads.topk(k=min(10000, max(1, int(factor))), dim=1) x_next.scatter_(dim=1, index=kidx, src=signs.gather(dim=1, index=kidx)) # projection x_next = clip_tensor(x_next) x_next = or_float_tensors(x_next, x) # compute adversarial loss loss_adv = loss_fct(model(Variable(x_next)), y) factor = random.random() * 2 * len(x) + 1.0 #if loss.data.mean() > loss_adv.data.mean(): # x_next = x_old # factor = max(1,factor * 0.5) #else: # factor = factor * 2.0 #print(loss_adv.data.mean()) found = False for r in range(len(x)): if loss_adv.data[r] > best_loss.data[r]: x_best[r] = x_next[r].clone() best_loss.data[r] = loss_adv.data[r] found = True if found is True: # if loss_adv.data.mean() > best_loss.data.mean(): #x_best = x_next.clone() #best_loss = loss_adv #x_next = x_best.clone() no_improve = 0 else: no_improve += 1 if no_improve > len(x): break x_next = topk(x, y.data, model, loss_fct, k, epsilon, alpha, False, use_sample, x_best).cuda() # projection #x_next = clip_tensor(x_next) #x_next = or_float_tensors(x_next, x) #x_next = x_best # compute adversarial loss y_model = model(Variable(x_next)) loss_adv = loss_fct(y_model, y).data if is_report_loss_diff: print( "Natural loss (%.4f) vs Adversarial loss (%.4f), Difference: (%.4f)" % (loss_natural.mean(), loss_adv.mean(), loss_adv.mean() - loss_natural.mean())) replace_flag = (loss_adv < loss_natural).unsqueeze(1).expand_as(x_next) x_next[replace_flag] = x[replace_flag] if x_next.is_cuda: x_next = x_next.cpu() return x_next
def topkrestart(x, y, model, loss_fct, k=25, epsilon=0.02, alpha=0.5, is_report_loss_diff=False, use_sample=False): #x_next = topk(x,y,model,loss_fct,k,epsilon,alpha,is_report_loss_diff=False,use_sample=False) # some book-keeping if next(model.parameters()).is_cuda: x = x.cuda() y = y.cuda() y = Variable(y) # compute natural loss y_model = model(Variable(x)) loss_natural = loss_fct(y_model, y).data x_next = x.clone() x_best = topk(x, y.data, model, loss_fct, k, epsilon, alpha, False, use_sample) y_model = model(Variable(x_best.cuda())) best_loss = loss_fct(y_model, y) for i in range(10): x_rand = torch.rand(len(x), len(x[0])) x_rand = torch.lt(x_rand, thresholds).float() x_rand = or_float_tensors(x_rand.cpu(), x.cpu()).cuda() x_next = topk(x, y.data, model, loss_fct, k, epsilon, alpha, False, use_sample, x_rand) y_model = model(Variable(x_next.cuda())) loss_adv = loss_fct(y_model, y) for r in range(len(x)): if loss_adv.data[r] > best_loss.data[r]: x_best[r] = x_next[r].clone() best_loss.data[r] = loss_adv.data[r] #print(best_loss.data.mean()) x_next = x_best.clone() x_next = clip_tensor(x_next) x_next = or_float_tensors(x_next.cpu(), x.cpu()).cuda() # compute adversarial loss y_model = model(Variable(x_next)) loss_adv = loss_fct(y_model, y).data if is_report_loss_diff: print( "Natural loss (%.4f) vs Adversarial loss (%.4f), Difference: (%.4f)" % (loss_natural.mean(), loss_adv.mean(), loss_adv.mean() - loss_natural.mean())) replace_flag = (loss_adv < loss_natural).unsqueeze(1).expand_as(x_next) x_next[replace_flag] = x[replace_flag] if x_next.is_cuda: x_next = x_next.cpu() return x_next
def topk(x, y, model, loss_fct, k=25, epsilon=0.02, alpha=0.5, is_report_loss_diff=False, use_sample=False, start_x=None): # some book-keeping if next(model.parameters()).is_cuda: x = x.cuda() y = y.cuda() y = Variable(y) # compute natural loss y_model = model(Variable(x)) loss_natural = loss_fct(y_model, y).data # initialize starting point x_next = get_x0(x, use_sample).clone() if start_x is not None: x_next = start_x.clone() x_best = x_next.clone() best_loss = loss_fct(y_model, y) factor = 1.0 for n in range(k): # forward pass x_old = x_next.clone() xn_var = Variable(x_next, requires_grad=True) y_model = model(xn_var) loss = loss_fct(y_model, y) # compute gradient grads = torch.autograd.grad(loss.mean(), xn_var)[0].data # topk signs = torch.gt(grads, 0).float() grads = (signs - x_next) * grads grads -= x * grads rand_vars = torch.rand(len(grads), len(grads[0])) kvals, kidx = grads.topk(k=min(10000, max(1, int(factor))), dim=1) x_next.scatter_(dim=1, index=kidx, src=signs.gather(dim=1, index=kidx)) # projection x_next = clip_tensor(x_next) x_next = or_float_tensors(x_next, x) # compute adversarial loss loss_adv = loss_fct(model(Variable(x_next)), y) found = 0 for r in range(len(x)): if loss_adv.data[r] > best_loss.data[r]: x_best[r] = x_next[r].clone() best_loss.data[r] = loss_adv.data[r] found += 1 #x_next = x_best.clone() if found < len(x) * 0.5 and loss.data.mean() > loss_adv.data.mean(): #if loss.data.mean() > loss_adv.data.mean(): factor = max(factor * 0.5, 0.25) x_next = x_old #if found is False: if factor < 0.5: break else: factor = factor * 2.0 #x_next = x_best.clone() x_next = x_best # compute adversarial loss y_model = model(Variable(x_next)) loss_adv = loss_fct(y_model, y).data if is_report_loss_diff: print( "Natural loss (%.4f) vs Adversarial loss (%.4f), Difference: (%.4f)" % (loss_natural.mean(), loss_adv.mean(), loss_adv.mean() - loss_natural.mean())) replace_flag = (loss_adv < loss_natural).unsqueeze(1).expand_as(x_next) x_next[replace_flag] = x[replace_flag] if x_next.is_cuda: x_next = x_next.cpu() return x_next