device = "cuda" if torch.cuda.is_available() else "cpu" model = resnet50(pretrained=True).eval().to(device) preprocess = T.Compose([T.Resize(256), T.CenterCrop(224), T.ToTensor(), T.Normalize(mean=[0.485,0.456,0.406], std=[0.229,0.224,0.225])])
# Define atk_hairy_hairy: as PGD but adding a high-frequency "hair" mask def generate_hair_mask(shape, density=0.02): # shape: (1,3,H,W) in [0,1] tensor _,_,H,W = shape mask = torch.zeros(1,1,H,W) rng = torch.Generator().manual_seed(0) num_strands = max(1,int(H*W*density/50)) for _ in range(num_strands): x = torch.randint(0,W,(1,), generator=rng).item() y = torch.randint(0,H,(1,), generator=rng).item() length = torch.randint(int(H*0.05), int(H*0.3),(1,), generator=rng).item() thickness = torch.randint(1,4,(1,), generator=rng).item() for t in range(length): xx = min(W-1, max(0, x + int((t/length-0.5)*10))) yy = min(H-1, max(0, y + t)) mask[0,0,yy:yy+thickness, xx:xx+thickness] = 1.0 return mask.to(device)
# Wrap model for Foolbox fmodel = fb.PyTorchModel(model, bounds=(0,1), preprocessing=dict(mean=[0.485,0.456,0.406], std=[0.229,0.224,0.225])) atk hairy hairy
# Use PGD but restrict updates to mask locations and add high-frequency noise pattern attack = LinfPGD(steps=40, abs_stepsize=0.01)
# Helper: load images def load_images(folder, maxn=50): paths = [os.path.join(folder,f) for f in os.listdir(folder) if f.lower().endswith(('.jpg','.png'))] imgs=[] for p in paths[:maxn]: img = Image.open(p).convert('RGB') imgs.append((p, preprocess(img).unsqueeze(0))) return imgs device = "cuda" if torch
results=[] for path, x in images: x = x.to(device) # get label logits = model((x - torch.tensor([0.485,0.456,0.406],device=device).view(1,3,1,1)) / torch.tensor([0.229,0.224,0.225],device=device).view(1,3,1,1)) orig_label = logits.argmax(dim=1).cpu().item()
logits_final = model((adv - torch.tensor([0.485,0.456,0.406],device=device).view(1,3,1,1)) / torch.tensor([0.229,0.224,0.225],device=device).view(1,3,1,1)) adv_label = logits_final.argmax(dim=1).cpu().item() success = adv_label != orig_label delta = (adv - x).abs().view(3,-1).max().cpu().item() l2 = torch.norm((adv-x).view(-1)).item() # save save_image(adv.squeeze().cpu(), path.replace("./images/","./advs/")) results.append(dict(path=path, orig=orig_label, adv=adv_label, success=success, linf=delta, l2=l2)) density=0.02): # shape: (1
mask = generate_hair_mask(x.shape, density=0.03) # define custom attack loop: PGD steps, but project and apply only where mask==1 adv = x.clone().detach() adv.requires_grad_(True) eps = 8/255.0 alpha = 2/255.0 for i in range(40): logits_adv = model((adv - torch.tensor([0.485,0.456,0.406],device=device).view(1,3,1,1)) / torch.tensor([0.229,0.224,0.225],device=device).view(1,3,1,1)) loss = torch.nn.functional.cross_entropy(logits_adv, torch.tensor([orig_label],device=device)) loss.backward() grad = adv.grad.data step = alpha * grad.sign() # create hair-patterned perturbation: alternate sign per-pixel high freq hf_pattern = torch.rand_like(adv) * 2 - 1 perturb = step * mask + 0.002 * hf_pattern * mask adv = adv.detach() + perturb # clip per-pixel to eps within L_inf of x adv = torch.max(torch.min(adv, x + eps), x - eps) adv = torch.clamp(adv, 0.0, 1.0).requires_grad_(True)
The Modern Work team specializes in developing and integrating custom solutions across the entire Microsoft 365 ecosystem. We design native applications for Microsoft and Azure platforms, and we implement business processes that maximize the return on investment in Microsoft 365.