1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
| def is_adversarial(model, input, target_classes): outputs = model(input) classes = (outputs>=0.5)+0 assert classes.shape == target_classes.shape is_adv = torch.all(classes==target_classes) return is_adv
def random_alter(tensor, n): total_elements = tensor.numel() indices = torch.randperm(total_elements)[:n]
tensor.view(-1)[indices] = ~tensor.view(-1)[indices] return tensor
def init_pop(image, target_image, target_classes, classfier, pop_size, init_rate): distances = torch.zeros((pop_size, )) distance=torch.tensor(torch.inf) V = [] n = math.floor(init_rate*image.shape[2]*image.shape[3]) print(n) v = (image!=target_image)
for i in range(pop_size): print(f"generate iter{i}") while True: v_o = v.detach().clone() v_o = random_alter(v_o, n) x_pert = image x_pert = np.where(v_o, target_image, x_pert) x_pert = torch.from_numpy(x_pert) distance_pert = update_distance(image, x_pert, classfier, target_classes) if distance_pert.item() < distance.item(): distances[i] = torch.where(distance_pert<distance, distance_pert, distance) V.append(v_o) break return V, distances
def update_distance(original, x_pert, model, target_classes): distance_pert = torch.norm(original-x_pert) is_adv=is_adversarial(model, x_pert, target_classes) distance_pert = torch.where(is_adv, distance_pert, torch.inf) return distance_pert
def rand_select_jq(V, kb): valid_indices = np.where(~np.isin(V, kb))[0] v_j_index = np.random.choice(valid_indices) v_q_index = np.random.choice(valid_indices[valid_indices != v_j_index]) v_j = V[v_j_index] v_q = V[v_q_index] return v_j, v_q
def binary_differential_recombination(v_j, v_q, v_kb): new_candidate = np.zeros_like(v_kb) random_indices = np.random.rand(v_kb.shape) new_candidate[random_indices>0.5] = v_j[random_indices>0.5] new_candidate[random_indices<=0.5] = v_q[random_indices<=0.5] recombined = np.where(new_candidate == 0, v_kb, new_candidate) return recombined
def mutation(v_o, mu): num_ones = np.sum(v_o == 1) num_mutations = int(mu * num_ones) mutation_indices = np.random.choice(np.where(v_o == 1)[0], num_mutations, replace=False) v_o[mutation_indices] = 0 return v_o
def SparseEvo(pop_size, generation, length, model, image, target_image, target_label, eps, batch_size, gradient): generation_save = np.zeros((10000,)) Vector, distances = init_pop(image, target_image, target_label, model, pop_size, init_rate=0.5) k_worst = np.argmax(distances) k_best = np.argmin(distances) problem = Problem(model, image, target_label, eps, batch_size) for i in range(generation.shape[0]): v_j, v_q = rand_select_jq(Vector, k_best) v_r = binary_differential_recombination(v_j, v_q, Vector[k_best]) v_mut = mutation(v_r, mu=0.5) x_pert = image x_pert[v_mut] = target_image[v_mut] distance_pert = np.linalg.norm(image-x_pert, ord=2) outputs_pert = model(x_pert) labels_pert = (outputs_pert>0.5)+0 if distance_pert < distances[k_worst]: distances[k_worst] = distance_pert Vector[k_worst] = v_mut k_worst = np.argmax(distances) k_best = np.argmin(distances) x_pert = image x_pert[Vector[k_best]] = target_image[Vector[k_best]]
|