diff --git a/ganimation/attacks.py b/ganimation/attacks.py index 3089a2f..ca3be29 100644 --- a/ganimation/attacks.py +++ b/ganimation/attacks.py @@ -80,8 +80,7 @@ class LinfPGDAttack(object): def perturb_iter_class(self, X_nat, y, c_trg): """ - Given examples (X_nat, y), returns adversarial - examples within epsilon of X_nat in l_infinity norm. + Iterative Class Conditional Attack """ X = X_nat.clone().detach_() @@ -113,6 +112,38 @@ class LinfPGDAttack(object): return X, eta + def perturb_joint_class(self, X_nat, y, c_trg): + """ + Joint Class Conditional Attack + """ + X = X_nat.clone().detach_() + + J = c_trg.size(0) + full_loss = 0.0 + + for i in range(self.k): + for j in range(J): + # print(i) + X.requires_grad = True + output_att, output_img = self.model(X, c_trg[j,:].unsqueeze(0)) + + out = imFromAttReg(output_att, output_img, X) + + self.model.zero_grad() + + loss = -self.loss_fn(output_att, y) + full_loss += loss + + full_loss.backward() + grad = X.grad + + X_adv = X + self.a * grad.sign() + + eta = torch.clamp(X_adv - X_nat, min=-self.epsilon, max=self.epsilon) + X = torch.clamp(X_nat + eta, min=-1, max=1).detach_() + + return X, eta + def clip_tensor(X, Y, Z): # Clip X with Y min and Z max X_np = X.data.cpu().numpy() diff --git a/ganimation/solver.py b/ganimation/solver.py index 310426f..0a5c0c3 100644 --- a/ganimation/solver.py +++ b/ganimation/solver.py @@ -404,29 +404,47 @@ class Solver(Utils): x_advs = [] for idx, image_path in enumerate(images_to_animate_path): - image_to_animate = regular_image_transform( - Image.open(image_path)).unsqueeze(0).cuda() + image_to_animate = regular_image_transform(Image.open(image_path)).unsqueeze(0).cuda() all_images = torch.cat([regular_image_transform(Image.open(path)).unsqueeze(0) for path in images_to_animate_path], dim=0).cuda() - if idx == 0: - for target_idx in range(targets.size(0)): - x_adv, perturb = pgd_attack.perturb(image_to_animate, black, targets[target_idx, :].unsqueeze(0).cuda()) - x_advs.append((x_adv, perturb)) + # Transfer to different images + # if idx == 0: + # for target_idx in range(targets.size(0)): + # x_adv, perturb = pgd_attack.perturb(image_to_animate, black, targets[target_idx, :].unsqueeze(0).cuda()) + # x_advs.append((x_adv, perturb)) for target_idx in range(targets.size(0)): - # if target_idx == 0: - # img = regular_image_transform(Image.open(images_to_animate_path[idx])).unsqueeze(0).cuda() - # # x_adv, perturb = pgd_attack.perturb(img, black, targets[0, :].unsqueeze(0).cuda()) - # x_adv, perturb = pgd_attack.perturb_iter_class(image_to_animate, black, targets[:, :].cuda()) - # # _, perturb = pgd_attack.perturb_iter_data(image_to_animate, all_images, black, targets[68, :].unsqueeze(0).cuda()) + # Transfer to different classes + if target_idx == 0: + # img = regular_image_transform(Image.open(images_to_animate_path[idx])).unsqueeze(0).cuda() + + # Wrong Class + x_adv, perturb = pgd_attack.perturb(image_to_animate, black, targets[0, :].unsqueeze(0).cuda() + + # Joint Class Conditional + # x_adv, perturb = pgd_attack.perturb_joint_class(image_to_animate, black, targets[:, :].cuda()) + + # Iterative Class Conditional + # x_adv, perturb = pgd_attack.perturb_iter_class(image_to_animate, black, targets[:, :].cuda()) + + # Iterative Data + # _, perturb = pgd_attack.perturb_iter_data(image_to_animate, all_images, black, targets[68, :].unsqueeze(0).cuda()) targets_au = targets[target_idx, :].unsqueeze(0).cuda() + + # Normal Attack # x_adv, perturb = pgd_attack.perturb(image_to_animate, black, targets_au) - x_adv, perturb = x_advs[target_idx] - # x_adv = image_to_animate + perturb - x_adv = image_to_animate + + # x_adv, perturb = x_advs[target_idx] + + x_adv = image_to_animate + perturb + + # No Attack + # x_adv = image_to_animate + # print(image_to_animate.shape, x_adv.shape) + with torch.no_grad(): resulting_images_att, resulting_images_reg = self.G( x_adv, targets_au)