|
|
import requests |
|
|
import torch |
|
|
from torchvision import datasets,models,transforms |
|
|
import torch.nn.functional as F |
|
|
import os |
|
|
|
|
|
import numpy as np |
|
|
import argparse |
|
|
import matplotlib.pyplot as plt |
|
|
import random |
|
|
|
|
|
from deeprobust.image import utils |
|
|
|
|
|
def run_attack(attackmethod, batch_size, batch_num, device, test_loader, random_targeted = False, target_label = -1, **kwargs): |
|
|
test_loss = 0 |
|
|
correct = 0 |
|
|
samplenum = 1000 |
|
|
count = 0 |
|
|
classnum = 10 |
|
|
for count, (data, target) in enumerate(test_loader): |
|
|
if count == batch_num: |
|
|
break |
|
|
print('batch:{}'.format(count)) |
|
|
|
|
|
data, target = data.to(device), target.to(device) |
|
|
if(random_targeted == True): |
|
|
r = list(range(0, target)) + list(range(target+1, classnum)) |
|
|
target_label = random.choice(r) |
|
|
adv_example = attackmethod.generate(data, target, target_label = target_label, **kwargs) |
|
|
|
|
|
elif(target_label >= 0): |
|
|
adv_example = attackmethod.generate(data, target, target_label = target_label, **kwargs) |
|
|
|
|
|
else: |
|
|
adv_example = attackmethod.generate(data, target, **kwargs) |
|
|
|
|
|
output = model(adv_example) |
|
|
test_loss += F.nll_loss(output, target, reduction='sum').item() |
|
|
|
|
|
pred = output.argmax(dim = 1, keepdim = True) |
|
|
|
|
|
correct += pred.eq(target.view_as(pred)).sum().item() |
|
|
|
|
|
batch_num = count+1 |
|
|
test_loss /= len(test_loader.dataset) |
|
|
print("===== ACCURACY =====") |
|
|
print('Attack Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format( |
|
|
test_loss, correct, batch_num * batch_size, |
|
|
100. * correct / (batch_num * batch_size))) |
|
|
|
|
|
def load_net(attack_model, filename, path): |
|
|
if(attack_model == "CNN"): |
|
|
from deeprobust.image.netmodels.CNN import Net |
|
|
|
|
|
model = Net() |
|
|
if(attack_model == "ResNet18"): |
|
|
import deeprobust.image.netmodels.resnet as Net |
|
|
model = Net.ResNet18() |
|
|
|
|
|
model.load_state_dict(torch.load(path + filename)) |
|
|
model.eval() |
|
|
return model |
|
|
|
|
|
def generate_dataloader(dataset, batch_size): |
|
|
if(dataset == "MNIST"): |
|
|
test_loader = torch.utils.data.DataLoader( |
|
|
datasets.MNIST('deeprobust/image/data', train = False, |
|
|
download = True, |
|
|
transform = transforms.Compose([transforms.ToTensor()])), |
|
|
batch_size = args.batch_size, |
|
|
shuffle = True) |
|
|
print("Loading MNIST dataset.") |
|
|
|
|
|
elif(dataset == "CIFAR" or args.dataset == 'CIFAR10'): |
|
|
test_loader = torch.utils.data.DataLoader( |
|
|
datasets.CIFAR10('deeprobust/image/data', train = False, |
|
|
download = True, |
|
|
transform = transforms.Compose([transforms.ToTensor()])), |
|
|
batch_size = args.batch_size, |
|
|
shuffle = True) |
|
|
classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck') |
|
|
print("Loading CIFAR10 dataset.") |
|
|
|
|
|
elif(dataset == "ImageNet"): |
|
|
test_loader = torch.utils.data.DataLoader( |
|
|
datasets.CIFAR10('deeprobust/image/data', train=False, |
|
|
download = True, |
|
|
transform = transforms.Compose([transforms.ToTensor()])), |
|
|
batch_size = args.batch_size, |
|
|
shuffle = True) |
|
|
print("Loading ImageNet dataset.") |
|
|
return test_loader |
|
|
|
|
|
def parameter_parser(): |
|
|
parser = argparse.ArgumentParser(description = "Run attack algorithms.", usage ='Use -h for more information.') |
|
|
|
|
|
parser.add_argument("--attack_method", |
|
|
default = 'PGD', |
|
|
help = "Choose a attack algorithm from: PGD(default), FGSM, LBFGS, CW, deepfool, onepixel, Nattack") |
|
|
parser.add_argument("--attack_model", |
|
|
default = "CNN", |
|
|
help = "Choose network structure from: CNN, ResNet") |
|
|
parser.add_argument("--path", |
|
|
default = "./trained_models/", |
|
|
help = "Type the path where the model is saved.") |
|
|
parser.add_argument("--file_name", |
|
|
default = 'MNIST_CNN_epoch_20.pt', |
|
|
help = "Type the file_name of the model that is to be attack. The model structure should be matched with the ATTACK_MODEL parameter.") |
|
|
parser.add_argument("--dataset", |
|
|
default = 'MNIST', |
|
|
help = "Choose a dataset from: MNIST(default), CIFAR(or CIFAR10), ImageNet") |
|
|
parser.add_argument("--epsilon", type = float, default = 0.3) |
|
|
parser.add_argument("--batch_num", type = int, default = 1000) |
|
|
parser.add_argument("--batch_size", type = int, default = 1000) |
|
|
parser.add_argument("--num_steps", type = int, default = 40) |
|
|
parser.add_argument("--step_size", type = float, default = 0.01) |
|
|
parser.add_argument("--random_targeted", type = bool, default = False, |
|
|
help = "default: False. By setting this parameter be True, the program would random generate target labels for the input samples.") |
|
|
parser.add_argument("--target_label", type = int, default = -1, |
|
|
help = "default: -1. Generate all attack Fixed target label.") |
|
|
parser.add_argument("--device", default = 'cuda', |
|
|
help = "Choose the device.") |
|
|
|
|
|
return parser.parse_args() |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
|
|
|
args = parameter_parser() |
|
|
|
|
|
|
|
|
example_model_path = './trained_models/MNIST_CNN_epoch_20.pt' |
|
|
if not (os.path.exists('./trained_models')): |
|
|
os.mkdir('./trained_models') |
|
|
print('create path: ./trained_models') |
|
|
model_url = "https://github.com/I-am-Bot/deeprobust_trained_model/blob/master/MNIST_CNN_epoch_20.pt?raw=true" |
|
|
r = requests.get(model_url) |
|
|
print('Downloading example model...') |
|
|
with open(example_model_path,'wb') as f: |
|
|
f.write(r.content) |
|
|
print('Downloaded.') |
|
|
|
|
|
model = load_net(args.attack_model, args.file_name, args.path) |
|
|
|
|
|
print("===== START ATTACK =====") |
|
|
if(args.attack_method == "PGD"): |
|
|
from deeprobust.image.attack.pgd import PGD |
|
|
test_loader = generate_dataloader(args.dataset, args.batch_size) |
|
|
attack_method = PGD(model, args.device) |
|
|
utils.tab_printer(args) |
|
|
run_attack(attack_method, args.batch_size, args.batch_num, args.device, test_loader, epsilon = args.epsilon) |
|
|
|
|
|
elif(args.attack_method == "FGSM"): |
|
|
from deeprobust.image.attack.fgsm import FGSM |
|
|
test_loader = generate_dataloader(args.dataset, args.batch_size) |
|
|
attack_method = FGSM(model, args.device) |
|
|
utils.tab_printer(args) |
|
|
run_attack(attack_method, args.batch_size, args.batch_num, args.device, test_loader, epsilon = args.epsilon) |
|
|
|
|
|
elif(args.attack_method == "LBFGS"): |
|
|
from deeprobust.image.attack.lbfgs import LBFGS |
|
|
try: |
|
|
if (args.batch_size >1): |
|
|
raise ValueError("batch_size shouldn't be larger than 1.") |
|
|
except ValueError: |
|
|
args.batch_size = 1 |
|
|
|
|
|
try: |
|
|
if (args.random_targeted == 0 and args.target_label == -1): |
|
|
raise ValueError("No target label assigned. Random generate target for each input.") |
|
|
except ValueError: |
|
|
args.random_targeted = True |
|
|
|
|
|
utils.tab_printer(args) |
|
|
test_loader = generate_dataloader(args.dataset, args.batch_size) |
|
|
attack_method = LBFGS(model, args.device) |
|
|
run_attack(attack_method, 1, args.batch_num, args.device, test_loader, random_targeted = args.random_targeted, target_label = args.target_label) |
|
|
|
|
|
elif(args.attack_method == "CW"): |
|
|
from deeprobust.image.attack.cw import CarliniWagner |
|
|
attack_method = CarliniWagner(model, args.device) |
|
|
try: |
|
|
if (args.batch_size > 1): |
|
|
raise ValueError("batch_size shouldn't be larger than 1.") |
|
|
except ValueError: |
|
|
args.batch_size = 1 |
|
|
|
|
|
try: |
|
|
if (args.random_targeted == 0 and args.target_label == -1): |
|
|
raise ValueError("No target label assigned. Random generate target for each input.") |
|
|
except ValueError: |
|
|
args.random_targeted = True |
|
|
|
|
|
utils.tab_printer(args) |
|
|
test_loader = generate_dataloader(args.dataset, args.batch_size) |
|
|
run_attack(attack_method, 1, args.batch_num, args.device, test_loader, random_targeted = args.random_targeted, target_label = args.target_label) |
|
|
|
|
|
elif(args.attack_method == "deepfool"): |
|
|
from deeprobust.image.attack.deepfool import DeepFool |
|
|
attack_method = DeepFool(model, args.device) |
|
|
try: |
|
|
if (args.batch_size > 1): |
|
|
raise ValueError("batch_size shouldn't be larger than 1.") |
|
|
except ValueError: |
|
|
args.batch_size = 1 |
|
|
|
|
|
utils.tab_printer(args) |
|
|
test_loader = generate_dataloader(args.dataset, args.batch_size) |
|
|
run_attack(attack_method, args.batch_size, args.batch_num, args.device, test_loader) |
|
|
|
|
|
elif(args.attack_method == "onepixel"): |
|
|
from deeprobust.image.attack.onepixel import Onepixel |
|
|
attack_method = Onepixel(model, args.device) |
|
|
try: |
|
|
if (args.batch_size > 1): |
|
|
raise ValueError("batch_size shouldn't be larger than 1.") |
|
|
except ValueError: |
|
|
args.batch_size = 1 |
|
|
|
|
|
utils.tab_printer(args) |
|
|
test_loader = generate_dataloader(args.dataset, args.batch_size) |
|
|
run_attack(attack_method, args.batch_size, args.batch_num, args.device, test_loader) |
|
|
|
|
|
elif(args.attack_method == "Nattack"): |
|
|
pass |
|
|
|
|
|
|