Upload folder using huggingface_hub
Browse files- robust_loss/__init__.py +7 -0
- robust_loss/adaad.py +65 -0
- robust_loss/ard.py +72 -0
- robust_loss/hat.py +77 -0
- robust_loss/mart.py +54 -0
- robust_loss/rslad.py +76 -0
- robust_loss/sat.py +158 -0
- robust_loss/trades.py +92 -0
robust_loss/__init__.py
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .hat import *
|
| 2 |
+
from .mart import *
|
| 3 |
+
from .trades import *
|
| 4 |
+
from .rslad import *
|
| 5 |
+
from .sat import *
|
| 6 |
+
from .ard import *
|
| 7 |
+
from .adaad import *
|
robust_loss/adaad.py
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
import torch.nn as nn
|
| 3 |
+
import torch.nn.functional as F
|
| 4 |
+
from torch.autograd import Variable
|
| 5 |
+
import torch.optim as optim
|
| 6 |
+
import numpy as np
|
| 7 |
+
def adaad_inner_loss(model,
|
| 8 |
+
teacher_model,
|
| 9 |
+
x_natural,
|
| 10 |
+
step_size=2/255,
|
| 11 |
+
steps=10,
|
| 12 |
+
epsilon=8/255,
|
| 13 |
+
BN_eval=True,
|
| 14 |
+
random_init=True,
|
| 15 |
+
clip_min=0.0,
|
| 16 |
+
clip_max=1.0):
|
| 17 |
+
# define KL-loss
|
| 18 |
+
criterion_kl = nn.KLDivLoss(reduction='none')
|
| 19 |
+
if BN_eval:
|
| 20 |
+
model.eval()
|
| 21 |
+
|
| 22 |
+
# set eval mode for teacher model
|
| 23 |
+
teacher_model.eval()
|
| 24 |
+
# generate adversarial example
|
| 25 |
+
if random_init:
|
| 26 |
+
x_adv = x_natural.detach() + 0.001 * torch.randn(x_natural.shape).cuda().detach()
|
| 27 |
+
else:
|
| 28 |
+
x_adv = x_natural.detach()
|
| 29 |
+
for _ in range(steps):
|
| 30 |
+
x_adv.requires_grad_()
|
| 31 |
+
with torch.enable_grad():
|
| 32 |
+
loss_kl = criterion_kl(F.log_softmax(model(x_adv), dim=1),
|
| 33 |
+
F.softmax(teacher_model(x_adv), dim=1))
|
| 34 |
+
loss_kl = torch.sum(loss_kl)
|
| 35 |
+
grad = torch.autograd.grad(loss_kl, [x_adv])[0]
|
| 36 |
+
x_adv = x_adv.detach() + step_size * torch.sign(grad.detach())
|
| 37 |
+
x_adv = torch.min(torch.max(x_adv, x_natural -
|
| 38 |
+
epsilon), x_natural + epsilon)
|
| 39 |
+
x_adv = torch.clamp(x_adv, clip_min, clip_max)
|
| 40 |
+
|
| 41 |
+
if BN_eval:
|
| 42 |
+
model.train()
|
| 43 |
+
model.train()
|
| 44 |
+
|
| 45 |
+
x_adv = Variable(torch.clamp(x_adv, clip_min, clip_max),
|
| 46 |
+
requires_grad=False)
|
| 47 |
+
return x_adv
|
| 48 |
+
def adaad_loss(teacher_model,model,x_natural,y,optimizer,step_size=0.0078,
|
| 49 |
+
epsilon=0.031,
|
| 50 |
+
perturb_steps=10,
|
| 51 |
+
beta = 6.0,
|
| 52 |
+
AdaAD_alpha=1.0):
|
| 53 |
+
adv_inputs = adaad_inner_loss(model,teacher_model,x_natural,step_size,perturb_steps,epsilon)
|
| 54 |
+
ori_outputs = model(x_natural)
|
| 55 |
+
adv_outputs = model(adv_inputs)
|
| 56 |
+
with torch.no_grad():
|
| 57 |
+
teacher_model.eval()
|
| 58 |
+
t_ori_outputs = teacher_model(x_natural)
|
| 59 |
+
t_adv_outputs = teacher_model(adv_inputs)
|
| 60 |
+
kl_loss1 = nn.KLDivLoss()(F.log_softmax(adv_outputs, dim=1),
|
| 61 |
+
F.softmax(t_adv_outputs.detach(), dim=1))
|
| 62 |
+
kl_loss2 = nn.KLDivLoss()(F.log_softmax(ori_outputs, dim=1),
|
| 63 |
+
F.softmax(t_ori_outputs.detach(), dim=1))
|
| 64 |
+
loss = AdaAD_alpha*kl_loss1 + (1-AdaAD_alpha)*kl_loss2
|
| 65 |
+
return loss
|
robust_loss/ard.py
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
import torch.nn as nn
|
| 3 |
+
import torch.nn.functional as F
|
| 4 |
+
from torch.autograd import Variable
|
| 5 |
+
import torch.optim as optim
|
| 6 |
+
import numpy as np
|
| 7 |
+
def attack_pgd(model,train_batch_data,train_batch_labels,attack_iters=10,step_size=2/255.0,epsilon=8.0/255.0):
|
| 8 |
+
ce_loss = torch.nn.CrossEntropyLoss().cuda()
|
| 9 |
+
train_ifgsm_data = train_batch_data.detach() + torch.zeros_like(train_batch_data).uniform_(-epsilon,epsilon)
|
| 10 |
+
train_ifgsm_data = torch.clamp(train_ifgsm_data,0,1)
|
| 11 |
+
for i in range(attack_iters):
|
| 12 |
+
train_ifgsm_data.requires_grad_()
|
| 13 |
+
logits = model(train_ifgsm_data)
|
| 14 |
+
loss = ce_loss(logits,train_batch_labels.cuda())
|
| 15 |
+
loss.backward()
|
| 16 |
+
train_grad = train_ifgsm_data.grad.detach()
|
| 17 |
+
train_ifgsm_data = train_ifgsm_data + step_size*torch.sign(train_grad)
|
| 18 |
+
train_ifgsm_data = torch.clamp(train_ifgsm_data.detach(),0,1)
|
| 19 |
+
train_ifgsm_pert = train_ifgsm_data - train_batch_data
|
| 20 |
+
train_ifgsm_pert = torch.clamp(train_ifgsm_pert,-epsilon,epsilon)
|
| 21 |
+
train_ifgsm_data = train_batch_data + train_ifgsm_pert
|
| 22 |
+
train_ifgsm_data = train_ifgsm_data.detach()
|
| 23 |
+
return train_ifgsm_data
|
| 24 |
+
|
| 25 |
+
def ard_inner_loss(model,
|
| 26 |
+
teacher_logits,
|
| 27 |
+
x_natural,
|
| 28 |
+
y,
|
| 29 |
+
optimizer,
|
| 30 |
+
step_size=0.0078,
|
| 31 |
+
epsilon=0.031,
|
| 32 |
+
perturb_steps=10,
|
| 33 |
+
beta=6.0):
|
| 34 |
+
# define KL-loss
|
| 35 |
+
criterion_kl = nn.KLDivLoss(size_average=False,reduce=False)
|
| 36 |
+
model.eval()
|
| 37 |
+
batch_size = len(x_natural)
|
| 38 |
+
# generate adversarial example
|
| 39 |
+
x_adv = x_natural.detach() + 0.001 * torch.randn(x_natural.shape).cuda().detach()
|
| 40 |
+
|
| 41 |
+
for _ in range(perturb_steps):
|
| 42 |
+
x_adv.requires_grad_()
|
| 43 |
+
with torch.enable_grad():
|
| 44 |
+
loss_kl = criterion_kl(F.log_softmax(model(x_adv), dim=1),
|
| 45 |
+
F.softmax(teacher_logits, dim=1))
|
| 46 |
+
loss_kl = torch.sum(loss_kl)
|
| 47 |
+
grad = torch.autograd.grad(loss_kl, [x_adv])[0]
|
| 48 |
+
x_adv = x_adv.detach() + step_size * torch.sign(grad.detach())
|
| 49 |
+
x_adv = torch.min(torch.max(x_adv, x_natural - epsilon), x_natural + epsilon)
|
| 50 |
+
x_adv = torch.clamp(x_adv, 0.0, 1.0)
|
| 51 |
+
|
| 52 |
+
model.train()
|
| 53 |
+
|
| 54 |
+
x_adv = Variable(torch.clamp(x_adv, 0.0, 1.0), requires_grad=False)
|
| 55 |
+
# zero gradient
|
| 56 |
+
# optimizer.zero_grad()
|
| 57 |
+
logits = model(x_adv)
|
| 58 |
+
return logits
|
| 59 |
+
def ard_loss(teacher_model,model,x_natural,y,optimizer,step_size=0.0078,
|
| 60 |
+
epsilon=0.031,
|
| 61 |
+
perturb_steps=10,
|
| 62 |
+
beta=6.0,
|
| 63 |
+
alpha = 1.0,
|
| 64 |
+
temp = 30.0):
|
| 65 |
+
KL_loss = nn.KLDivLoss()
|
| 66 |
+
XENT_loss = nn.CrossEntropyLoss()
|
| 67 |
+
teacher_logits = teacher_model(x_natural)
|
| 68 |
+
adv_logits = ard_inner_loss(model,teacher_logits,x_natural,y,optimizer,step_size,epsilon,perturb_steps)
|
| 69 |
+
model.train()
|
| 70 |
+
nat_logits = model(x_natural)
|
| 71 |
+
loss = alpha*temp*temp*KL_loss(F.log_softmax(adv_logits/temp, dim=1),F.softmax(teacher_logits/temp, dim=1))+(1.0-alpha)*XENT_loss(nat_logits, y)
|
| 72 |
+
return loss
|
robust_loss/hat.py
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
from torch.autograd import Variable
|
| 3 |
+
import torch
|
| 4 |
+
import torch.nn as nn
|
| 5 |
+
import torch.nn.functional as F
|
| 6 |
+
from robust_loss.sat import ctx_noparamgrad_and_eval
|
| 7 |
+
def hat_loss(model, x, y, optimizer, step_size=0.007, epsilon=0.031, perturb_steps=10, beta=1.0,
|
| 8 |
+
attack='linf',natural_criterion= None ,h=3.5, gamma=1.0, hr_model=None):
|
| 9 |
+
"""
|
| 10 |
+
TRADES + Helper-based adversarial training.
|
| 11 |
+
"""
|
| 12 |
+
|
| 13 |
+
criterion_kl = nn.KLDivLoss(reduction='sum')
|
| 14 |
+
model.eval()
|
| 15 |
+
|
| 16 |
+
x_adv = x.detach() + 0.001 * torch.randn(x.shape).cuda().detach()
|
| 17 |
+
p_natural = F.softmax(model(x), dim=1)
|
| 18 |
+
|
| 19 |
+
if attack == 'l_inf':
|
| 20 |
+
for _ in range(perturb_steps):
|
| 21 |
+
x_adv.requires_grad_()
|
| 22 |
+
with torch.enable_grad():
|
| 23 |
+
loss_kl = criterion_kl(F.log_softmax(model(x_adv), dim=1), p_natural)
|
| 24 |
+
grad = torch.autograd.grad(loss_kl, [x_adv])[0]
|
| 25 |
+
x_adv = x_adv.detach() + step_size * torch.sign(grad.detach())
|
| 26 |
+
x_adv = torch.min(torch.max(x_adv, x - epsilon), x + epsilon)
|
| 27 |
+
x_adv = torch.clamp(x_adv, 0.0, 1.0)
|
| 28 |
+
elif attack == 'l2':
|
| 29 |
+
delta = 0.001 * torch.randn(x.shape).cuda().detach()
|
| 30 |
+
delta = Variable(delta.data, requires_grad=True)
|
| 31 |
+
|
| 32 |
+
batch_size = len(x)
|
| 33 |
+
optimizer_delta = torch.optim.SGD([delta], lr=step_size)
|
| 34 |
+
|
| 35 |
+
for _ in range(perturb_steps):
|
| 36 |
+
adv = x + delta
|
| 37 |
+
optimizer_delta.zero_grad()
|
| 38 |
+
with torch.enable_grad():
|
| 39 |
+
loss = (-1) * criterion_kl(F.log_softmax(model(adv), dim=1), p_natural)
|
| 40 |
+
loss.backward(retain_graph=True)
|
| 41 |
+
|
| 42 |
+
grad_norms = delta.grad.view(batch_size, -1).norm(p=2, dim=1)
|
| 43 |
+
delta.grad.div_(grad_norms.view(-1, 1, 1, 1))
|
| 44 |
+
if (grad_norms == 0).any():
|
| 45 |
+
delta.grad[grad_norms == 0] = torch.randn_like(delta.grad[grad_norms == 0])
|
| 46 |
+
optimizer_delta.step()
|
| 47 |
+
|
| 48 |
+
delta.data.add_(x)
|
| 49 |
+
delta.data.clamp_(0, 1).sub_(x)
|
| 50 |
+
delta.data.renorm_(p=2, dim=0, maxnorm=epsilon)
|
| 51 |
+
x_adv = Variable(x + delta, requires_grad=False)
|
| 52 |
+
else:
|
| 53 |
+
raise ValueError(f'Attack={attack} not supported for TRADES training!')
|
| 54 |
+
model.train()
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
x_adv = Variable(torch.clamp(x_adv, 0.0, 1.0), requires_grad=False)
|
| 58 |
+
x_hr = x + h * (x_adv - x)
|
| 59 |
+
if hr_model == None:
|
| 60 |
+
with ctx_noparamgrad_and_eval(model):
|
| 61 |
+
y_hr = model(x_adv).argmax(dim=1)
|
| 62 |
+
else:
|
| 63 |
+
with ctx_noparamgrad_and_eval(hr_model):
|
| 64 |
+
y_hr = hr_model(x_adv).argmax(dim=1)
|
| 65 |
+
|
| 66 |
+
optimizer.zero_grad()
|
| 67 |
+
|
| 68 |
+
out_clean, out_adv, out_help = model(x), model(x_adv), model(x_hr)
|
| 69 |
+
loss_clean = F.cross_entropy(out_clean, y, reduction='mean')
|
| 70 |
+
loss_adv = (1/len(x)) * criterion_kl(F.log_softmax(out_adv, dim=1), F.softmax(out_clean, dim=1))
|
| 71 |
+
|
| 72 |
+
loss_help = F.cross_entropy(out_help, y_hr, reduction='mean')
|
| 73 |
+
loss = loss_clean + beta * loss_adv + gamma * loss_help
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
return loss
|
robust_loss/mart.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
import torch.nn as nn
|
| 3 |
+
import torch.nn.functional as F
|
| 4 |
+
from torch.autograd import Variable
|
| 5 |
+
from utils.criterion import CrossEntropyWithLabelSmooth
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
def mart_loss(model, x_natural, y, optimizer, step_size=0.007, epsilon=0.031, perturb_steps=10, beta=6.0,
|
| 9 |
+
attack='l_inf',natural_criterion= nn.CrossEntropyLoss()):
|
| 10 |
+
"""
|
| 11 |
+
MART training (Wang et al, 2020).
|
| 12 |
+
"""
|
| 13 |
+
|
| 14 |
+
kl = nn.KLDivLoss(reduction='none')
|
| 15 |
+
model.eval()
|
| 16 |
+
batch_size = len(x_natural)
|
| 17 |
+
|
| 18 |
+
# generate adversarial example
|
| 19 |
+
x_adv = x_natural.detach() + 0.001 * torch.randn(x_natural.shape).cuda().detach()
|
| 20 |
+
if attack == 'l_inf':
|
| 21 |
+
for _ in range(perturb_steps):
|
| 22 |
+
x_adv.requires_grad_()
|
| 23 |
+
with torch.enable_grad():
|
| 24 |
+
loss_ce = natural_criterion(model(x_adv), y)
|
| 25 |
+
grad = torch.autograd.grad(loss_ce, [x_adv])[0]
|
| 26 |
+
x_adv = x_adv.detach() + step_size * torch.sign(grad.detach())
|
| 27 |
+
x_adv = torch.min(torch.max(x_adv, x_natural - epsilon), x_natural + epsilon)
|
| 28 |
+
x_adv = torch.clamp(x_adv, 0.0, 1.0)
|
| 29 |
+
else:
|
| 30 |
+
raise ValueError(f'Attack={attack} not supported for MART training!')
|
| 31 |
+
model.train()
|
| 32 |
+
|
| 33 |
+
x_adv = Variable(torch.clamp(x_adv, 0.0, 1.0), requires_grad=False)
|
| 34 |
+
# zero gradient
|
| 35 |
+
optimizer.zero_grad()
|
| 36 |
+
|
| 37 |
+
logits = model(x_natural)
|
| 38 |
+
logits_adv = model(x_adv)
|
| 39 |
+
|
| 40 |
+
adv_probs = F.softmax(logits_adv, dim=1)
|
| 41 |
+
tmp1 = torch.argsort(adv_probs, dim=1)[:, -2:]
|
| 42 |
+
new_y = torch.where(tmp1[:, -1] == y, tmp1[:, -2], tmp1[:, -1])
|
| 43 |
+
loss_adv = natural_criterion(logits_adv, y) + F.nll_loss(torch.log(1.0001 - adv_probs + 1e-12), new_y)
|
| 44 |
+
|
| 45 |
+
nat_probs = F.softmax(logits, dim=1)
|
| 46 |
+
true_probs = torch.gather(nat_probs, 1, (y.unsqueeze(1)).long()).squeeze()
|
| 47 |
+
|
| 48 |
+
loss_robust = (1.0 / batch_size) * torch.sum(
|
| 49 |
+
torch.sum(kl(torch.log(adv_probs + 1e-12), nat_probs), dim=1) * (1.0000001 - true_probs))
|
| 50 |
+
loss = loss_adv + float(beta) * loss_robust
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
return loss
|
robust_loss/rslad.py
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
import torch.nn as nn
|
| 3 |
+
import torch.nn.functional as F
|
| 4 |
+
from torch.autograd import Variable
|
| 5 |
+
import torch.optim as optim
|
| 6 |
+
import numpy as np
|
| 7 |
+
|
| 8 |
+
# def attack_pgd(model,train_batch_data,train_batch_labels,attack_iters=10,step_size=2/255.0,epsilon=8.0/255.0):
|
| 9 |
+
# ce_loss = torch.nn.CrossEntropyLoss().cuda()
|
| 10 |
+
# train_ifgsm_data = train_batch_data.detach() + torch.zeros_like(train_batch_data).uniform_(-epsilon,epsilon)
|
| 11 |
+
# train_ifgsm_data = torch.clamp(train_ifgsm_data,0,1)
|
| 12 |
+
# for i in range(attack_iters):
|
| 13 |
+
# train_ifgsm_data.requires_grad_()
|
| 14 |
+
# logits = model(train_ifgsm_data)
|
| 15 |
+
# loss = ce_loss(logits,train_batch_labels.cuda())
|
| 16 |
+
# loss.backward()
|
| 17 |
+
# train_grad = train_ifgsm_data.grad.detach()
|
| 18 |
+
# train_ifgsm_data = train_ifgsm_data + step_size*torch.sign(train_grad)
|
| 19 |
+
# train_ifgsm_data = torch.clamp(train_ifgsm_data.detach(),0,1)
|
| 20 |
+
# train_ifgsm_pert = train_ifgsm_data - train_batch_data
|
| 21 |
+
# train_ifgsm_pert = torch.clamp(train_ifgsm_pert,-epsilon,epsilon)
|
| 22 |
+
# train_ifgsm_data = train_batch_data + train_ifgsm_pert
|
| 23 |
+
# train_ifgsm_data = train_ifgsm_data.detach()
|
| 24 |
+
# return train_ifgsm_data
|
| 25 |
+
def kl_loss(a,b):
|
| 26 |
+
loss = -a*b + torch.log(b+1e-5)*b
|
| 27 |
+
return loss
|
| 28 |
+
def rslad_inner_loss(model,
|
| 29 |
+
teacher_logits,
|
| 30 |
+
x_natural,
|
| 31 |
+
y,
|
| 32 |
+
optimizer,
|
| 33 |
+
step_size=0.0078,
|
| 34 |
+
epsilon=0.031,
|
| 35 |
+
perturb_steps=10,
|
| 36 |
+
beta=6.0):
|
| 37 |
+
# define KL-loss
|
| 38 |
+
criterion_kl = nn.KLDivLoss(size_average=False,reduce=False)
|
| 39 |
+
model.eval()
|
| 40 |
+
batch_size = len(x_natural)
|
| 41 |
+
# generate adversarial example
|
| 42 |
+
x_adv = x_natural.detach() + 0.001 * torch.randn(x_natural.shape).cuda().detach()
|
| 43 |
+
|
| 44 |
+
for _ in range(perturb_steps):
|
| 45 |
+
x_adv.requires_grad_()
|
| 46 |
+
with torch.enable_grad():
|
| 47 |
+
loss_kl = criterion_kl(F.log_softmax(model(x_adv), dim=1),
|
| 48 |
+
F.softmax(teacher_logits, dim=1))
|
| 49 |
+
loss_kl = torch.sum(loss_kl)
|
| 50 |
+
grad = torch.autograd.grad(loss_kl, [x_adv])[0]
|
| 51 |
+
x_adv = x_adv.detach() + step_size * torch.sign(grad.detach())
|
| 52 |
+
x_adv = torch.min(torch.max(x_adv, x_natural - epsilon), x_natural + epsilon)
|
| 53 |
+
x_adv = torch.clamp(x_adv, 0.0, 1.0)
|
| 54 |
+
|
| 55 |
+
model.train()
|
| 56 |
+
|
| 57 |
+
x_adv = Variable(torch.clamp(x_adv, 0.0, 1.0), requires_grad=False)
|
| 58 |
+
# zero gradient
|
| 59 |
+
# optimizer.zero_grad()
|
| 60 |
+
# logits = model(x_adv)
|
| 61 |
+
return x_adv
|
| 62 |
+
def rslad_loss(teacher_model,model,x_natural,y,optimizer,step_size=0.0078,
|
| 63 |
+
epsilon=0.031,
|
| 64 |
+
perturb_steps=10,
|
| 65 |
+
beta=6.0):
|
| 66 |
+
teacher_logits = teacher_model(x_natural)
|
| 67 |
+
x_adv = rslad_inner_loss(model,teacher_logits,x_natural,y,optimizer,step_size,epsilon,perturb_steps)
|
| 68 |
+
adv_logits = model(x_adv)
|
| 69 |
+
model.train()
|
| 70 |
+
nat_logits = model(x_natural)
|
| 71 |
+
kl_Loss1 = kl_loss(F.log_softmax(adv_logits,dim=1),F.softmax(teacher_logits.detach(),dim=1))
|
| 72 |
+
kl_Loss2 = kl_loss(F.log_softmax(nat_logits,dim=1),F.softmax(teacher_logits.detach(),dim=1))
|
| 73 |
+
kl_Loss1 = torch.mean(kl_Loss1)
|
| 74 |
+
kl_Loss2 = torch.mean(kl_Loss2)
|
| 75 |
+
loss = 5/6.0*kl_Loss1 + 1/6.0*kl_Loss2
|
| 76 |
+
return loss
|
robust_loss/sat.py
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
import torch.nn as nn
|
| 3 |
+
import torch.nn.functional as F
|
| 4 |
+
from attacks import create_attack
|
| 5 |
+
import numpy as np
|
| 6 |
+
from torch.autograd import Variable
|
| 7 |
+
from contextlib import contextmanager
|
| 8 |
+
if torch.cuda.is_available():
|
| 9 |
+
device = torch.device('cuda')
|
| 10 |
+
else:
|
| 11 |
+
device = torch.device('cpu')
|
| 12 |
+
|
| 13 |
+
class ctx_noparamgrad(object):
|
| 14 |
+
def __init__(self, module):
|
| 15 |
+
self.prev_grad_state = get_param_grad_state(module)
|
| 16 |
+
self.module = module
|
| 17 |
+
set_param_grad_off(module)
|
| 18 |
+
|
| 19 |
+
def __enter__(self):
|
| 20 |
+
pass
|
| 21 |
+
|
| 22 |
+
def __exit__(self, *args):
|
| 23 |
+
set_param_grad_state(self.module, self.prev_grad_state)
|
| 24 |
+
return False
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
class ctx_eval(object):
|
| 28 |
+
def __init__(self, module):
|
| 29 |
+
self.prev_training_state = get_module_training_state(module)
|
| 30 |
+
self.module = module
|
| 31 |
+
set_module_training_off(module)
|
| 32 |
+
|
| 33 |
+
def __enter__(self):
|
| 34 |
+
pass
|
| 35 |
+
|
| 36 |
+
def __exit__(self, *args):
|
| 37 |
+
set_module_training_state(self.module, self.prev_training_state)
|
| 38 |
+
return False
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
@contextmanager
|
| 42 |
+
def ctx_noparamgrad_and_eval(module):
|
| 43 |
+
with ctx_noparamgrad(module) as a, ctx_eval(module) as b:
|
| 44 |
+
yield (a, b)
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def get_module_training_state(module):
|
| 48 |
+
return {mod: mod.training for mod in module.modules()}
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
def set_module_training_state(module, training_state):
|
| 52 |
+
for mod in module.modules():
|
| 53 |
+
mod.training = training_state[mod]
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def set_module_training_off(module):
|
| 57 |
+
for mod in module.modules():
|
| 58 |
+
mod.training = False
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
def get_param_grad_state(module):
|
| 62 |
+
return {param: param.requires_grad for param in module.parameters()}
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
def set_param_grad_state(module, grad_state):
|
| 66 |
+
for param in module.parameters():
|
| 67 |
+
param.requires_grad = grad_state[param]
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def set_param_grad_off(module):
|
| 71 |
+
for param in module.parameters():
|
| 72 |
+
param.requires_grad = False
|
| 73 |
+
class MadrysLoss(nn.Module):
|
| 74 |
+
def __init__(self, step_size=0.007, epsilon=0.031, perturb_steps=10, beta=6.0,
|
| 75 |
+
distance='l_inf', cutmix=False, adjust_freeze=True, cutout=False,
|
| 76 |
+
cutout_length=16):
|
| 77 |
+
super(MadrysLoss, self).__init__()
|
| 78 |
+
self.step_size = step_size
|
| 79 |
+
self.epsilon = epsilon
|
| 80 |
+
self.perturb_steps = perturb_steps
|
| 81 |
+
self.beta = beta
|
| 82 |
+
self.distance = distance
|
| 83 |
+
self.cross_entropy = torch.nn.CrossEntropyLoss()
|
| 84 |
+
self.adjust_freeze = adjust_freeze
|
| 85 |
+
self.cutout = cutout
|
| 86 |
+
self.cutout_length = cutout_length
|
| 87 |
+
|
| 88 |
+
def forward(self, model, x_natural, labels): #optimizer
|
| 89 |
+
model.eval()
|
| 90 |
+
if self.adjust_freeze:
|
| 91 |
+
for param in model.parameters():
|
| 92 |
+
param.requires_grad = False
|
| 93 |
+
|
| 94 |
+
# generate adversarial example
|
| 95 |
+
x_adv = x_natural.detach() + self.step_size * torch.randn(x_natural.shape).to(device).detach()
|
| 96 |
+
if self.distance == 'l_inf':
|
| 97 |
+
adv_loss = 0
|
| 98 |
+
for _ in range(self.perturb_steps):
|
| 99 |
+
x_adv.requires_grad_()
|
| 100 |
+
loss_ce = self.cross_entropy(model(x_adv), labels)
|
| 101 |
+
grad = torch.autograd.grad(loss_ce, [x_adv])[0]
|
| 102 |
+
x_adv = x_adv.detach() + self.step_size * torch.sign(grad.detach())
|
| 103 |
+
x_adv = torch.min(torch.max(x_adv, x_natural - self.epsilon), x_natural + self.epsilon)
|
| 104 |
+
x_adv = torch.clamp(x_adv, 0.0, 1.0)
|
| 105 |
+
else:
|
| 106 |
+
x_adv = torch.clamp(x_adv, 0.0, 1.0)
|
| 107 |
+
|
| 108 |
+
x_adv = Variable(x_adv, requires_grad=False)
|
| 109 |
+
|
| 110 |
+
if self.adjust_freeze:
|
| 111 |
+
for param in model.parameters():
|
| 112 |
+
param.requires_grad = True
|
| 113 |
+
|
| 114 |
+
if self.cutout:
|
| 115 |
+
batch_size = x_adv.shape[0]
|
| 116 |
+
c, h, w = x_adv.shape[1], x_adv.shape[2], x_adv.shape[3]
|
| 117 |
+
mask = torch.ones(batch_size, c, h, w).float()
|
| 118 |
+
for j in range(batch_size):
|
| 119 |
+
y = np.random.randint(h)
|
| 120 |
+
x = np.random.randint(w)
|
| 121 |
+
|
| 122 |
+
y1 = np.clip(y - self.cutout_length // 2, 0, h)
|
| 123 |
+
y2 = np.clip(y + self.cutout_length // 2, 0, h)
|
| 124 |
+
x1 = np.clip(x - self.cutout_length // 2, 0, w)
|
| 125 |
+
x2 = np.clip(x + self.cutout_length // 2, 0, w)
|
| 126 |
+
|
| 127 |
+
mask[j, :, y1: y2, x1: x2] = 0.0
|
| 128 |
+
x_adv = x_adv * mask.to(device)
|
| 129 |
+
|
| 130 |
+
model.train()
|
| 131 |
+
# optimizer.zero_grad()
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
logits = model(x_adv)
|
| 135 |
+
loss = self.cross_entropy(logits, labels)
|
| 136 |
+
|
| 137 |
+
return loss
|
| 138 |
+
|
| 139 |
+
|
| 140 |
+
def sat_loss(model, x, y,optimizer,step_size,epsilon,num_steps,attack_type,beta,criterion= torch.nn.CrossEntropyLoss()):
|
| 141 |
+
"""
|
| 142 |
+
Adversarial training (Madry et al, 2017).
|
| 143 |
+
"""
|
| 144 |
+
attack = create_attack(model, criterion, 'linf-pgd', epsilon, num_steps, step_size)
|
| 145 |
+
with ctx_noparamgrad_and_eval(model):
|
| 146 |
+
x_adv, _ = attack.perturb(x, y)
|
| 147 |
+
print(x_adv.shape)
|
| 148 |
+
y_adv = y
|
| 149 |
+
out = model(x_adv)
|
| 150 |
+
loss = criterion(out, y_adv)
|
| 151 |
+
|
| 152 |
+
return loss
|
| 153 |
+
|
| 154 |
+
|
| 155 |
+
|
| 156 |
+
|
| 157 |
+
|
| 158 |
+
|
robust_loss/trades.py
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
|
| 3 |
+
import torch
|
| 4 |
+
import torch.nn as nn
|
| 5 |
+
import torch.nn.functional as F
|
| 6 |
+
from torch.autograd import Variable
|
| 7 |
+
import torch.optim as optim
|
| 8 |
+
from utils.criterion import CrossEntropyWithLabelSmooth
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def squared_l2_norm(x):
|
| 13 |
+
flattened = x.view(x.unsqueeze(0).shape[0], -1)
|
| 14 |
+
return (flattened ** 2).sum(1)
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def l2_norm(x):
|
| 18 |
+
return squared_l2_norm(x).sqrt()
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def trades_loss(model, x_natural, y,optimizer = None, step_size=0.003, epsilon=0.031, perturb_steps=10, beta=1.0,
|
| 22 |
+
attack='l_inf',natural_criterion= nn.CrossEntropyLoss() ):
|
| 23 |
+
"""
|
| 24 |
+
TRADES training (Zhang et al, 2019).
|
| 25 |
+
"""
|
| 26 |
+
|
| 27 |
+
# define KL-loss
|
| 28 |
+
criterion_kl = nn.KLDivLoss(size_average=False)
|
| 29 |
+
model.eval()
|
| 30 |
+
batch_size = len(x_natural)
|
| 31 |
+
# generate adversarial example
|
| 32 |
+
x_adv = x_natural.detach() + 0.001 * torch.randn(x_natural.shape).cuda().detach()
|
| 33 |
+
p_natural = F.softmax(model(x_natural), dim=1)
|
| 34 |
+
|
| 35 |
+
if attack == 'l_inf':
|
| 36 |
+
for _ in range(perturb_steps):
|
| 37 |
+
x_adv.requires_grad_()
|
| 38 |
+
with torch.enable_grad():
|
| 39 |
+
loss_kl = criterion_kl(F.log_softmax(model(x_adv), dim=1), p_natural)
|
| 40 |
+
grad = torch.autograd.grad(loss_kl, [x_adv])[0]
|
| 41 |
+
x_adv = x_adv.detach() + step_size * torch.sign(grad.detach())
|
| 42 |
+
x_adv = torch.min(torch.max(x_adv, x_natural - epsilon), x_natural + epsilon)
|
| 43 |
+
x_adv = torch.clamp(x_adv, 0.0, 1.0)
|
| 44 |
+
|
| 45 |
+
elif attack == 'l2':
|
| 46 |
+
delta = 0.001 * torch.randn(x_natural.shape).cuda().detach()
|
| 47 |
+
delta = Variable(delta.data, requires_grad=True)
|
| 48 |
+
|
| 49 |
+
# Setup optimizers
|
| 50 |
+
optimizer_delta = optim.SGD([delta], lr=epsilon / perturb_steps * 2)
|
| 51 |
+
|
| 52 |
+
for _ in range(perturb_steps):
|
| 53 |
+
adv = x_natural + delta
|
| 54 |
+
|
| 55 |
+
# optimize
|
| 56 |
+
optimizer_delta.zero_grad()
|
| 57 |
+
with torch.enable_grad():
|
| 58 |
+
loss = (-1) * criterion_kl(F.log_softmax(model(adv), dim=1), p_natural)
|
| 59 |
+
loss.backward(retain_graph=True)
|
| 60 |
+
# renorming gradient
|
| 61 |
+
grad_norms = delta.grad.view(batch_size, -1).norm(p=2, dim=1)
|
| 62 |
+
delta.grad.div_(grad_norms.view(-1, 1, 1, 1))
|
| 63 |
+
# avoid nan or inf if gradient is 0
|
| 64 |
+
if (grad_norms == 0).any():
|
| 65 |
+
delta.grad[grad_norms == 0] = torch.randn_like(delta.grad[grad_norms == 0])
|
| 66 |
+
optimizer_delta.step()
|
| 67 |
+
|
| 68 |
+
# projection
|
| 69 |
+
delta.data.add_(x_natural)
|
| 70 |
+
delta.data.clamp_(0, 1).sub_(x_natural)
|
| 71 |
+
delta.data.renorm_(p=2, dim=0, maxnorm=epsilon)
|
| 72 |
+
x_adv = Variable(x_natural + delta, requires_grad=False)
|
| 73 |
+
else:
|
| 74 |
+
raise ValueError(f'Attack={attack} not supported for TRADES training!')
|
| 75 |
+
model.train()
|
| 76 |
+
|
| 77 |
+
x_adv = Variable(torch.clamp(x_adv, 0.0, 1.0), requires_grad=False)
|
| 78 |
+
|
| 79 |
+
optimizer.zero_grad()
|
| 80 |
+
# calculate robust loss
|
| 81 |
+
logits_natural = model(x_natural)
|
| 82 |
+
# print("loguts natural:{}".format(logits_natural))
|
| 83 |
+
logits_adv = model(x_adv)
|
| 84 |
+
# print("loguts adv:{}".format(logits_adv))
|
| 85 |
+
loss_natural = natural_criterion(logits_natural, y)
|
| 86 |
+
loss_robust = (1.0 / batch_size) * criterion_kl(F.log_softmax(logits_adv, dim=1),
|
| 87 |
+
F.softmax(logits_natural, dim=1))
|
| 88 |
+
loss = loss_natural + beta * loss_robust
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
return loss
|