Yaning1001's picture
Add files using upload-large-folder tool
d38bce3 verified
"""
https://github.com/lordwarlock/Pytorch-BPDA/blob/master/bpda.py
"""
import torch
import torch.nn as nn
import torchvision.models as models
import numpy as np
def normalize(image, mean, std):
return (image - mean)/std
def preprocess(image):
image = image / 255
image = np.transpose(image, (2, 0, 1))
mean = np.array([0.485, 0.456, 0.406]).reshape((3, 1, 1))
std = np.array([0.229, 0.224, 0.225]).reshape((3, 1, 1))
image = normalize(image, mean, std)
return image
def image2tensor(image):
img_t = torch.Tensor(image)
img_t = img_t.unsqueeze(0)
img_t.requires_grad_()
return img_t
def label2tensor(label):
target = np.array([label])
target = torch.from_numpy(target).long()
return target
def get_img_grad_given_label(image, label, model):
logits = model(image)
ce = nn.CrossEntropyLoss()
loss = ce(logits, target)
loss.backward()
ret = image.grad.clone()
model.zero_grad()
image.grad.data.zero_()
return ret
def get_cw_grad(adv, origin, label, model):
logits = model(adv)
ce = nn.CrossEntropyLoss()
l2 = nn.MSELoss()
loss = ce(logits, label) + l2(0, origin - adv) / l2(0, origin)
loss.backward()
ret = adv.grad.clone()
model.zero_grad()
adv.grad.data.zero_()
origin.grad.data.zero_()
return ret
def l2_norm(adv, img):
adv = adv.detach().numpy()
img = img.detach().numpy()
ret = np.sum(np.square(adv - img))/np.sum(np.square(img))
return ret
def clip_bound(adv):
mean = np.array([0.485, 0.456, 0.406]).reshape((3, 1, 1))
std = np.array([0.229, 0.224, 0.225]).reshape((3, 1, 1))
adv = adv * std + mean
adv = np.clip(adv, 0., 1.)
adv = (adv - mean) / std
return adv.astype(np.float32)
def identity_transform(x):
return x.detach().clone()
def BPDA_attack(image,target, model, step_size = 1., iterations = 10, linf=False, transform_func=identity_transform):
target = label2tensor(target)
adv = image.detach().numpy()
adv = torch.from_numpy(adv)
adv.requires_grad_()
for _ in range(iterations):
adv_def = transform_func(adv)
adv_def.requires_grad_()
l2 = nn.MSELoss()
loss = l2(0, adv_def)
loss.backward()
g = get_cw_grad(adv_def, image, target, model)
if linf:
g = torch.sign(g)
print(g.numpy().sum())
adv = adv.detach().numpy() - step_size * g.numpy()
adv = clip_bound(adv)
adv = torch.from_numpy(adv)
adv.requires_grad_()
if linf:
print('label', torch.argmax(model(adv)), 'linf', torch.max(torch.abs(adv - image)).detach().numpy())
else:
print('label', torch.argmax(model(adv)), 'l2', l2_norm(adv, image))
return adv.detach().numpy()
if __name__ == '__main__':
import matplotlib
matplotlib.use('TkAgg')
import skimage
resnet18 = models.resnet18(pretrained=True).eval() # for CPU, remove cuda()
image = preprocess(skimage.io.imread('test.png'))
img_t = image2tensor(image)
BPDA_attack(img_t, 924, resnet18)
print('L-inf')
BPDA_attack(img_t, 924, resnet18, step_size = 0.003, linf=True)