def fgsm_attack(image, epsilon, data_grad):
sign_data_grad = data_grad.sign()

perturbed_image = image + epsilon*sign_data_grad

perturbed_image = t.clamp(perturbed_image, 0, 255)

return perturbed_image

def gen_adv(model, device, data, target, epsilon):
data, target = data.to(device), target.to(device)
data.requires_grad = True

output = model(data)
init_pred = output.max(1, keepdim=True)[1]
if init_pred.item() != target.item():
    return

loss = F.nll_loss(output, target)
model.zero_grad()
loss.backward()
data_grad = data.grad.data
data = unnormalized_show(data)

perturbed_data = fgsm_attack(data, epsilon, data_grad)
perturbed_data = perturbed_data.cpu().detach().numpy()
perturbed_data = perturbed_data.reshape(3, 224, 224)
perturbed_data = np.transpose(perturbed_data, (1, 2, 0))

return perturbed_data