NTU ML2023Spring Part3.10 Adversarial Attack
gdown 的链接又挂了,还好 dropbox 没挂.
只实现了 medium baseline 相应的 ifsgm.简单来说就是迭代地做 fsgm.把上面 fsgm 的代码抄过来再改改就行了.
def ifgsm(model, x, y, loss_fn, epsilon=epsilon, alpha=alpha, num_iter=20):
x_adv = x.detach().clone()
x_upper = x + epsilon
x_lower = x - epsilon
# write a loop with num_iter times
for i in range(num_iter):
x_adv.requires_grad = True
loss = loss_fn(model(x_adv), y) # calculate loss
loss.backward() # calculate gradient
# fgsm: use gradient ascent on x_adv to maximize loss
grad = x_adv.grad.detach()
x_adv.grad.zero_()
x_adv.requires_grad = False
x_adv = x_adv + alpha * grad.sign()
# clip
x_adv = torch.min(x_adv, x_upper)
x_adv = torch.max(x_adv, x_lower)
return x_adv
效果显著啊!原来 fsgm 效果是这样的:
adv_examples, fgsm_acc, fgsm_loss = gen_adv_examples(model, adv_loader, fgsm, loss_fn)
print(f'fgsm_acc = {fgsm_acc:.5f}, fgsm_loss = {fgsm_loss:.5f}')
fgsm_acc = 0.59000, fgsm_loss = 2.49187
改成 ifsgm 之后:
adv_examples, fgsm_acc, fgsm_loss = gen_adv_examples(model, adv_loader, ifgsm, loss_fn)
print(f'fgsm_acc = {fgsm_acc:.5f}, fgsm_loss = {fgsm_loss:.5f}')
fgsm_acc = 0.95000, fgsm_loss = 0.22678
后面的 ensemble attack 咕了.